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
|