gnucobol-users
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [open-cobol-list] procedure division returning


From: Sergey Kashyrin
Subject: Re: [open-cobol-list] procedure division returning
Date: Tue, 16 Jul 2013 14:01:38 -0400

Hi Frank,
 
Just back from vacation.
It seems I've fixed it a little bit, but a little.
 
The way how returning is implemented in OC is not the best, because it is moving the returning value into RETURN-CODE, which is 32-bit int.
Returning can not be in a LOCAL-STORAGE at lest for OC 1.1, as in this case we need to change the order of events, and as of now local storage is freed before return-code is assigned.
 
I made some tests on mainframe, and I see that IBM is allocating static memory for "returning", even it is in a linkage section.
And "of course" they have a bug related to that :-)))
 
Try this one on mainframe:
 
       identification division.
       program-id. caller.
       data division.
       working-storage section.
       77  str      pic x(20) value 'This is a test'.
       77  str-len  pic s9(7) comp-4.
       01  p usage pointer.
       procedure division.
           set p to address of str-len.
           display 'str-len addr = ' p.
           call 'callee2' using str
                returning str-len
           display 'callee2 returned ' str-len
           goback.
       end program caller.
 
       identification division.
       program-id. callee2.
       data division.
       working-storage section.
       01  p usage pointer.
       01  len1  pic s9(7) comp-4.
       linkage section.
       01  str  pic x(20).
       01  len  pic s9(7) comp-4.
       procedure division using str returning len.
           set p to address of len.
           display 'len addr = ' p.
           set address of len to address of len1.
           set p to address of len.
           display 'len addr = ' p.
           compute len = function length(str)
           display 'len=' len
           display 'len1=' len1
           exit program.
       end program callee2.
ska 73> cob2 reterr2.cbl
 PP 5655-S71 IBM Enterprise COBOL for z/OS  4.2.0 in progress ...
 End of compilation 1,  program CALLER,  no statements flagged.
 End of compilation 2,  program CALLEE2,  no statements flagged.
ska 74> ./a.out
str-len addr = 0535552680
len addr = 0535421452
len addr = 0535552864
len=0000020
len1=0000020
callee2 returned 0000000
and the following works on mainframe but of course not in OC:
 
       identification division.
       program-id. caller.
       data division.
       working-storage section.
       01  str.
           02 val pic x(20) value 'This is a test'.
       procedure division.
           call 'callee' returning str
           display 'callee returned ' val
           goback.
       end program caller.
 
       identification division.
       program-id. callee.
       data division.
       working-storage section.
       01  p usage pointer.
       linkage section.
       01  str  pic x(20).
       procedure division returning str.
           set p to address of str.
           display 'str addr = ' p.
           move '12345678901234567890' to str.
           display 'str=' str
           exit program.
       end program callee.
 
Regards,
Sergey
 
 
----- Original Message -----
Sent: Sunday, June 30, 2013 10:40 PM
Subject: Re: [open-cobol-list] procedure division returning

Hi Sergey,

That works in a limited fashion, but still has some issues.  Issue #1:

14.1 Procedure division structure
14.1.1 General format
where procedure-division-header is:
PROCEDURE DIVISION [ using-phrase ] [ RETURNING data-name-2 ]

14.1.2 Syntax rules
5) Data-name-2 shall be defined as a level 01 entry or level 77 entry in the linkage section.
("in the linkage section" highlighted by me)

With your change the returning data item must be in the working-storage section.  (It doesn't even work if declared in the local-storage section.)

I've been looking at how IBM mainframe COBOL solves this issue.  It appears that if the returning data item is a non-group item the compiler automatically allocates stack storage for it (within the called routine) and then, in essence, does a "return" of that.  Seems like a reasonable way to do it.

Now if the returning data-item is a group data item, array, or string (really any item that cannot be returned in a register), the caller implicitly passes a reference to the return item as parameter 1, and the callee directly modifies the value at that location.  So, basically, the following two statements function in the same manner:

call 'callee' using by reference string-out string-in
call 'callee' using by reference string-in returning string-out

similarly, these are the same:

program-id. 'callee'.
data division.
linkage section.
01  output-string                          display   pic x(80).
01  input-string                             display   pic x(80).
procedure division using by reference output-string, input-string.
    move function reverse(input-string) to output-string
    exit program.

program-id. 'callee'.
data division.
linkage section.
01  output-string                          display   pic x(80).
01  input-string                             display   pic x(80).
procedure division using by reference input-string returning output-string.
    move function reverse(input-string) to output-string
    exit program.

and a C call to either would be something like this:
char output_string[80], input_string[80];
callee(output_string, input_string);
if the parms were structs the call would be something like
callee_struct(&out_struct, &in_struct);

I got a little sidetracked on the second point, but the first point has another issue.  It seems only to work with integer (comp/binary) parameters, but not with float/double (float-short, float-long) parameters.  See the following example:

local-storage section.
77  double-in                           comp-2 value 2.
77  double-out                          comp-2.

    call static 'cobatan2' using value double-in returning double-out

  /* Line: 18        : CALL               : ret_test2.cob */
  {
    {
      module.cob_procedure_params[0] = (f_5.data = "" + 0, &f_5);
      memset (&(module.cob_procedure_params[1]), 0, 32);
      cob_glob_ptr->cob_call_params = 1;
      (*(int *) (b_1)) = cobatan2 (*(double *)(cob_local_ptr + 0));
      cob_set_int ((f_6.data = "" + 16, &f_6), (*(int *) (b_1)));
    }
  }

Here the input parameter is properly cast to a pointer to a double, but the return value is treated as a pointer to an integer.  I'm not at all sure, but I would imagine the last lines should be something to the effect of this:
      (*(double *) (b_1)) = cobatan2 (*(double *)(cob_local_ptr + 0));
      cob_set_double ((f_6.data = "" + 16, &f_6), (*(double *) (b_1)));
And of course b_1, which is the "return-code special register" needs to be large enough to hold a double (8 bytes instead of 4).  Or use the actual variable directly.

Are you by chance able to see if this issue is resolved in OC 2.0?  I thought I'd read that 2.0 has user defined functions, and if it does it seems to me they would have had to solve this issue.

Frank









On 6/29/2013 4:29 AM, Sergey Kashyrin wrote:

http://www.kiska.net/opencobol/1.1/index.html


On 6/29/2013 12:39 AM, Frank Swarbrick wrote:
Well that's cool (and very fast!).  I don't suppose there's any way I can get this fix....?

On 6/28/2013 1:43 AM, Sergey Kashyrin wrote:
Hi Frank,

Just checked and can confirm that in 1.1 (all subversions) PROCEDURE DIVISION RETURNING was not implemented correctly yet.
I've fixed that in my 1.1 version.

Regards,
Sergey

On 6/28/2013 2:53 AM, Frank Swarbrick wrote:
ret_test.cob:48: Error: RETURNING item is not defined in LINKAGE SECTION

On 6/28/2013 12:47 AM, Sergey Kashyrin wrote:
Hi Frank,

It is not suppose to work. I mean it works exactly as expected, i.e. SEGFAULT
"len" is declared in linkage section and not referenced in "using", and that mean it is not allocated.
Referencing in "returning" does not allocate the memory for variable.
Move it to working or local storage and everything will be fine.

Regards,
Sergey

On 6/28/2013 1:35 AM, Frank Swarbrick wrote:
Anyone ever got this to work?
Take a look at this:

       >>SOURCE FORMAT IS FREE

program-id. caller.
data division.
local-storage section.
77  str-len  binary-long.
procedure division.
    call 'callee1' using content 'This is a test'
         returning str-len
    display str-len
    call 'callee2' using content 'This is a test!'
         returning str-len
    display str-len
    goback.
end program caller.

program-id. callee1.
data division.
linkage section.
01  str  pic x any length.
procedure division using str.
    compute return-code = function length(str)
    exit program.
end program callee1.

program-id. callee2.
data division.
linkage section.
01  str  pic x any length.
01  len  binary-long.
procedure division using str returning len.
    compute len = function length(str)
    exit program.
end program callee2.

callee1 works fine.  callee2 causes a core dump or some such thing.

Looking at the generated C code I see the following:

/* PROGRAM-ID : callee1 */
static cob_u8_t b_8[4];    /* RETURN-CODE */

/* PROGRAM-ID : callee2 */
static cob_u8_t b_14[4];    /* RETURN-CODE */


/* PROGRAM-ID : callee1 */
static cob_field f_8    = {4, b_8, &a_3};    /* RETURN-CODE */
static cob_field f_12    = {1, NULL, &a_1};    /* str */

/* PROGRAM-ID : callee2 */
static cob_field f_18    = {1, NULL, &a_1};    /* str */
static cob_field f_19    = {4, NULL, &a_2};    /* len */

/* LINKAGE SECTION (Items not referenced by USING clause) */
static unsigned char    *b_19 = NULL;  /* len */


The compute in callee1:
    cob_decimal_set_field (&d0, cob_intr_length (&f_12));
    cob_decimal_get_field (&d0, &f_8, 0);

The compute in callee2:
    cob_decimal_set_field (&d0, cob_intr_length (&f_18));
    cob_decimal_get_field (&d0, (f_19.data = "" &f_19), 0);

So what's happening is that in callee2 variable 'b_19', which is the address of the COBOL field 'len' is still set to NULL, and thus we get a null pointer exception when trying to set it.

So it seems to me that even though the returning clause of the procedure division is allowed syntactically its not actually supported in the run-time.  Bad news!  :-(

Interestingly, a small kludge will make it work.  I added the following before any attempt to use the returning field (len):
    set address of len to address of return-code

And now it works.

Comments?


------------------------------------------------------------------------------
This SF.net email is sponsored by Windows:

Build for Windows Store.

http://p.sf.net/sfu/windows-dev2dev


_______________________________________________
open-cobol-list mailing list
address@hidden
https://lists.sourceforge.net/lists/listinfo/open-cobol-list







------------------------------------------------------------------------------
This SF.net email is sponsored by Windows:

Build for Windows Store.

http://p.sf.net/sfu/windows-dev2dev


_______________________________________________
open-cobol-list mailing list
address@hidden
https://lists.sourceforge.net/lists/listinfo/open-cobol-list

reply via email to

[Prev in Thread] Current Thread [Next in Thread]