If I use numerical parameters in an UDF, then I get wrong values. See this example.
:::cobolfreeIDENTIFICATIONDIVISION.PROGRAM-ID.testudf.AUTHOR.LaszloErdos.ENVIRONMENTDIVISION.CONFIGURATIONSECTION.REPOSITORY.FUNCTIONJ-SETSIZE.DATADIVISION.WORKING-STORAGESECTION.*>functionreturnvalue01WS-RETBINARY-INT.*>GUIelements01WS-BUTTONBINARY-INT.*>functionargs01WS-WIDTHBINARY-INT.01WS-HEIGHTBINARY-INT.PROCEDUREDIVISION.*>------------------------------------------------------------------------------MAIN-TESTUDFSECTION.*>------------------------------------------------------------------------------MOVE1TOWS-BUTTONDISPLAY"first call with variables"MOVE80TOWS-WIDTHMOVE20TOWS-HEIGHTMOVEJ-SETSIZE(WS-BUTTON,WS-WIDTH,WS-HEIGHT)TOWS-RETDISPLAY"second call without variables"MOVEJ-SETSIZE(WS-BUTTON,80,20)TOWS-RETSTOPRUN.MAIN-TESTUDF-EX.EXIT.ENDPROGRAMtestudf.IDENTIFICATIONDIVISION.FUNCTION-ID.J-SETSIZE.AUTHOR.LaszloErdos.ENVIRONMENTDIVISION.DATADIVISION.WORKING-STORAGESECTION.LINKAGESECTION.01LNK-ARG-0BINARY-INT.01LNK-ARG-1BINARY-INT.01LNK-ARG-2BINARY-INT.01LNK-RETBINARY-INT.PROCEDUREDIVISIONUSINGBYVALUELNK-ARG-0BYVALUELNK-ARG-1BYVALUELNK-ARG-2RETURNINGLNK-RET.MAIN-J-SETSIZESECTION.DISPLAY"LNK-ARG-0: "LNK-ARG-0DISPLAY"LNK-ARG-1: "LNK-ARG-1DISPLAY"LNK-ARG-2: "LNK-ARG-2*>ThisisaCfunction,thereforeweneed"BY VALUE"*>CALL"java_setsize"*>USINGBYVALUELNK-ARG-0*>BYVALUELNK-ARG-1*>BYVALUELNK-ARG-2*>RETURNINGOMITTED*>END-CALLMOVEZEROESTOLNK-RETGOBACK.MAIN-J-SETSIZE-EX.EXIT.ENDFUNCTIONJ-SETSIZE.
Compile:
cobc -x -free testudf.cob setsize.cob
Start:
$ ./testudf.exe
first call with variables
LNK-ARG-0: +0000000001
LNK-ARG-1: +0000000080
LNK-ARG-2: +0000000020
second call without variables
LNK-ARG-0: +0000000001
LNK-ARG-1: +0000012344
LNK-ARG-2: +0000012338
Question 1: Is there a problem by parameter passing?
Question 2: This function gives no value back, but I have to define a return variable.
I would like to write in my program only this:
"J-SETSIZE(WS-BUTTON, 80, 20)"
and not this:
"MOVE J-SETSIZE(WS-BUTTON, 80, 20) TO WS-RET"
Is it possible?
I use GnuCOBOL with cygwin (64 bit Windows).
$ cobc -version
cobc (GNU Cobol) 2.0.0
Copyright (C) 2001,2002,2003,2004,2005,2006,2007 Keisuke Nishida
Copyright (C) 2006-2012 Roger While
Copyright (C) 2009,2010,2012,2014 Simon Sobisch
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Built Dec 03 2014 09:52:44
Packaged Jan 20 2014 07:40:53 UTC
C version "4.8.3"
Thx - László
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Thank you for the Answer. A BINARY-INT is 4 bytes.
I changed all data types, here are some results.
BINARY-INT: not OK
$ ./testudf.exe
first call with variables
LNK-ARG-0: +0000000001
LNK-ARG-1: +0000000080
LNK-ARG-2: +0000000020
second call without variables
LNK-ARG-0: +0000000001
LNK-ARG-1: +0000012344
LNK-ARG-2: +0000012338
length of WS-BUTTON: 4
FUNCTION LENGTH: 000000004
PIC 9(4): OK (but I need negative values for another functions later)
$ ./testudf.exe
first call with variables
LNK-ARG-0: 0001
LNK-ARG-1: 0080
LNK-ARG-2: 0020
second call without variables
LNK-ARG-0: 0001
LNK-ARG-1: 80
LNK-ARG-2: 20
length of WS-BUTTON: 4
FUNCTION LENGTH: 000000004
PIC S9(4): not OK
$ ./testudf.exe
first call with variables
LNK-ARG-0: +0001
LNK-ARG-1: +0080
LNK-ARG-2: +0020
second call without variables
LNK-ARG-0: +0001
Attempt to reference unallocated memory (Signal SIGSEGV)
Abnormal termination - File contents may be incorrect
LNK-ARG-1:
PIC S9(8): not OK
$ ./testudf.exe
first call with variables
LNK-ARG-0: +00000001
LNK-ARG-1: +00000080
LNK-ARG-2: +00000020
second call without variables
LNK-ARG-0: +00000001
Attempt to reference unallocated memory (Signal SIGSEGV)
Abnormal termination - File contents may be incorrect
LNK-ARG-1:
PIC S9(4) BINARY: not OK
$ ./testudf.exe
first call with variables
LNK-ARG-0: +0
LNK-ARG-1: +P0
LNK-ARG-2: +0
second call without variables
LNK-ARG-0: +0
Attempt to reference unallocated memory (Signal SIGSEGV)
Abnormal termination - File contents may be incorrect
LNK-ARG-1:
I tried arithmetic expressions also, but I get errors. My cygwin terminal was freezen sometimes...
László
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
$ ./testudf.exe
first call with variables
LNK-ARG-0: +0000000001
LNK-ARG-1: +0000000080
LNK-ARG-2: +0000000020
second call without variables
LNK-ARG-0: +0000000001
LNK-ARG-1: +0000000048
LNK-ARG-2: +0000000049
length of WS-BUTTON: 4
FUNCTION LENGTH: 000000004
So, 48 and 49 are the ASCII values of 0 and 1.
There are also two problems with UDF.
- wrong interpretation of numeric values.
- can not process an arithmetic expressions.
László
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
OK, good work, explains the first results. You're getting character 80 and 20 then interpreted as little-endian binary. The hex of those is x'3032' and x'3038', or 02 and 08, which are 80 and 20 going from left-to-right. I saw those yesterday, but not used to thinking in ASCII :-)
It looks like there should be an implicit BY VALUE for the literal in the function call, which is presumably there in an intrinsic function.
An intrinsic function can have an arithmetic expression, so I assume a UDF should as well, with the result again being passed implicitly BY VALUE.
The other parameters for a UDF call should also be checked for being passed BY VALUE. Since the source fields are defined as BINARY-INT they may well be making it look like it "works". Perhaps change those in the caller to non-binary, and we then know if the rest of the UDF call is OK or not.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I agree with Bill in that you should try a different data-type.
You say you need a signed number so why not try an 's9(4) comp' or if that's not long enough then an 's9(9) comp'. I have a UDF that returns a number indicating the start point in a string and it allways gives the correct value.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
$ ./testudf.exe
first call with variables
LNK-ARG-0: +000000001
LNK-ARG-1: +000000080
LNK-ARG-2: +000000020
second call without variables
LNK-ARG-0: +000000001
LNK-ARG-1: +942669824
LNK-ARG-2: +842006528
length of WS-BUTTON: 4
FUNCTION LENGTH: 000000004
It works with variables independent from types.
But with numeric literal:
"MOVE J-SETSIZE(WS-BUTTON, 80, 20) TO WS-RET"
I get this:
second call without variables
LNK-ARG-0: +000000001
LNK-ARG-1: +942669824
LNK-ARG-2: +842006528
With an arithmetic expression in UDF:
"MOVE J-SETSIZE(WS-BUTTON, 80 + X, 20 + Y) TO WS-RET"
I get a runtime error:
Attempt to reference unallocated memory (Signal SIGSEGV)
Abnormal termination - File contents may be incorrect
László
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
This bug needs fixing. There is a constraint, due to spec, UDF arguments are always call by reference, modifiable values. Always, by spec. Kinda sad, but understandable. Given that constraint, literal values become a thing. Duck typing of numeric literals in COBOL is, umm, not really conducive to foreign function interfacing, being usage display.
Still it needs to be fixed, a fix that will likely correct the same problem with CALL by value stack frame setups. CALL has explicit (though also malfunctioning for literals) SIZE IS clauses for each argument.
There is a shadow stack of cobol field structure accessible for CALL and UDF arguments from C. I'm leaning to believe that this is part of the problem. All parameters end up cast to size of pointer. Using missing bit fill, and usage display rules not synched with what GnuCOBOL or foreign library data needs.
This is a repeat of a previous post, but I'm not sure it can be solely a compile time fix. The casting may have to be run-time casting, a conditional that may slow down CALL, more than s negligible amount. Burdened with selecting the proper casting during call frame setup, at runtime; a marshaling layer penalty for each and every CALL, or FUNCTION-ID.
Guessing.
Cheers,
Brian
Last edit: Brian Tiffin 2015-01-20
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Perhaps GNU Cobol should support by-value function arguments as a language extension? FFI absolutely requires some solution (unless one wants to write C marshalling code – some languages do this).
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
When we do, I'd actually volunteer to try and implement a by struct enhancement along with more robust and sane by value handling. The JSON based jq library begs out for call by struct. And jq is awesome.
Have good, make well,
Brian
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Oh, and the spec was updated. User defined functions now support BY REFERENCE, BY VALUE, BY CONTENT phrases on arguments.
I'm not sure of the timing, exactly, but it might have something to do with Roger pointing out that user defined and intrinsic functions only allowing BY REFERENCE in the Drafts, broke the commutative properties of ADD. But that would assume someone on the committee actually heard us complaining a few years back, so probably not a true suspicion. I don't have old drafts around to see when/if the change actually occurred or if it was just a misread oversight from years gone by.
8.4.2.2, 8.4.2.2.3, 8.4.2.2.4.
Just to point out the issue (which is no longer an issue when BY VALUE is allowed/used)
::cobolfree
ADD f(a, b) g(a, b) GIVING answer
could end up with a different result than
::cobolfree
ADD g(a, b) f(a, b) GIVING answer
depending on whether f() or g() changed a or b. A state of affairs that would likely send some chills down some necks.
Oh, and one more thing. The problem turned out to be two fold. One, it has nothing to do with the reflective shadow values, it has/had to do with datatype promotion at the C level. The dynamic call nature of GnuCOBOL did not cast all arguments in C, so all integer types were promoted to int and all real types were promoted to double by C standard. Extra level of casting is now in place for CALL, but still needs work in functions. So 16 bits stay as 16 bits, etc.
The other issue that still needs addressing is that function literals are passed to C as string literals. String literals have no explicit numeric type (1 2 4 or 8 bytes?), so the trick of moving through working storage for function literals is what fixes that part. Well that, and references to string literals aren't really numbers as one would assume them to be. We'll need to define some rules, and allow for casting literals with SIZE IS phrases when this eventually gets addressed.
From some discussion with Zeev when he was having issues with PCRE integration in GnuCOBOL, IBM assumes a 32bit integer for numeric literals, but this is hard documentation to come by, and Zeev found out by doing experiments.
Cheers,
Brian
Last edit: Brian Tiffin 2016-09-11
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Well, it's fixed by spec now, or at least options exist. BY REFERENCE is still the default unless explictly told otherwise. I kinda wish I had old drafts lying around, as I might be fibbing about when/if this changed, and it might just be Roger (and I) had misread things. I complained on LinkedIn, in a group that Donald Nelson reads from time to time, and no one mentioned that we had the wrong impression, but that doesn't mean we didn't. ;-)
Cheers,
Brian
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
The last 20xx draft has the "optional not by value" part in already but these are marked as change while UDF aren't marked as change. I'll recheck the 2002 standard for UDF and assume this is "only BY REFERENCE".
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
No, that was only a minimal example. One of the strengths of UDF is that you can use the return value directly in any expression (like conditions or computations), for CALL ... RETURNING you always need to define a variable to hold the result, and when you want to compare the results of multiple items then it gets dirty quite fast - especially when you compare with EVALUATE ... WHEN FUNC-A ... WHEN FUNC-B (a, b) ... which also highlights one other benefit - you can use these in any place.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
So with my EBCDIC conversion I found a method to evaluate comparative expressions "in place"
(Simon helped out)
IF FUNCTION FXASCII (P1X (1:2)) > '00'
Where: P1X is a character data element populated with EBCDIC values.
Prior to having written the UDF function "FXASCII" it was required that I must:
Convert P1X to ASCII
Execute the compartive expression
Restore P1X to EBCDIC
Using a UDF simplified the requirement to convert EBCDIC data values by evaluating the expression "in place".
All that glitters is not gold :-)
There is an edict from some governing body that requires allocating huge amounts of data (something like 99,000 bytes or 1 GB) per invocation of a UDF that utilizes "Any Length" / Returning syntax.
As implemented in 3.1 Dev memory is allocated as if an arithmetic progression is in effect.
Hence 'Any Length' or perhaps any parameter indicating a return value diminishes the value of the UDF since the GetMain occurs with every execution.
Given 100 or so repetitve executions of the UDF, memory grew to over 1 GB.
I tried a "CANCEL" after each invocation - made no difference - memory allocation continued to increase.
Another concern is portability of UDF(s) to other COBOL compilers.
I do not think there is a standard implementation.
Most UDF discussions contemplate SQL.
Ralph
Last edit: Ralph Linkletter 2020-06-28
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hi,
If I use numerical parameters in an UDF, then I get wrong values. See this example.
Compile:
cobc -x -free testudf.cob setsize.cob
Start:
$ ./testudf.exe
first call with variables
LNK-ARG-0: +0000000001
LNK-ARG-1: +0000000080
LNK-ARG-2: +0000000020
second call without variables
LNK-ARG-0: +0000000001
LNK-ARG-1: +0000012344
LNK-ARG-2: +0000012338
Question 1: Is there a problem by parameter passing?
Question 2: This function gives no value back, but I have to define a return variable.
I would like to write in my program only this:
"J-SETSIZE(WS-BUTTON, 80, 20)"
and not this:
"MOVE J-SETSIZE(WS-BUTTON, 80, 20) TO WS-RET"
Is it possible?
I use GnuCOBOL with cygwin (64 bit Windows).
$ cobc -version
cobc (GNU Cobol) 2.0.0
Copyright (C) 2001,2002,2003,2004,2005,2006,2007 Keisuke Nishida
Copyright (C) 2006-2012 Roger While
Copyright (C) 2009,2010,2012,2014 Simon Sobisch
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Built Dec 03 2014 09:52:44
Packaged Jan 20 2014 07:40:53 UTC
C version "4.8.3"
Thx - László
Hi,
Function Argument: "An identifier, a literal, or an arithmetic expression that specifies a value to be used in the evaluation of a function."
So it can be also an arithmetic expression. I think, a numeric value is also an arithmetic expression.
Can anybody confirm that?
Thx - László
I'm wondering if there is something with a post of Simon's from a few weeks ago.
The BINARY-INT seems to be getting storage allowing 10 digits (from the result of the DISPLAY).
A literal number should count as an arithmetic expression, yes.
When your literal number is "passed" to the CALLed program, I don't think the size of the literal is mapping correctly to the BINARY-INT.
Perhaps have a go with BINARY and a PIC 9(4) instead? Also, what is the LENGTH OF/FUNCTION LENGTH of BINARY-INT?
I suspect the literal is in two bytes, the BINARY-INT is at least four (from the number of digits in the DISPLAY) and could be even longer!
Thank you for the Answer. A BINARY-INT is 4 bytes.
I changed all data types, here are some results.
BINARY-INT: not OK
$ ./testudf.exe
first call with variables
LNK-ARG-0: +0000000001
LNK-ARG-1: +0000000080
LNK-ARG-2: +0000000020
second call without variables
LNK-ARG-0: +0000000001
LNK-ARG-1: +0000012344
LNK-ARG-2: +0000012338
length of WS-BUTTON: 4
FUNCTION LENGTH: 000000004
PIC 9(4): OK (but I need negative values for another functions later)
$ ./testudf.exe
first call with variables
LNK-ARG-0: 0001
LNK-ARG-1: 0080
LNK-ARG-2: 0020
second call without variables
LNK-ARG-0: 0001
LNK-ARG-1: 80
LNK-ARG-2: 20
length of WS-BUTTON: 4
FUNCTION LENGTH: 000000004
PIC S9(4): not OK
$ ./testudf.exe
first call with variables
LNK-ARG-0: +0001
LNK-ARG-1: +0080
LNK-ARG-2: +0020
second call without variables
LNK-ARG-0: +0001
Attempt to reference unallocated memory (Signal SIGSEGV)
Abnormal termination - File contents may be incorrect
LNK-ARG-1:
PIC S9(8): not OK
$ ./testudf.exe
first call with variables
LNK-ARG-0: +00000001
LNK-ARG-1: +00000080
LNK-ARG-2: +00000020
second call without variables
LNK-ARG-0: +00000001
Attempt to reference unallocated memory (Signal SIGSEGV)
Abnormal termination - File contents may be incorrect
LNK-ARG-1:
PIC S9(4) BINARY: not OK
$ ./testudf.exe
first call with variables
LNK-ARG-0: +0
LNK-ARG-1: +P0
LNK-ARG-2: +0
second call without variables
LNK-ARG-0: +0
Attempt to reference unallocated memory (Signal SIGSEGV)
Abnormal termination - File contents may be incorrect
LNK-ARG-1:
I tried arithmetic expressions also, but I get errors. My cygwin terminal was freezen sometimes...
László
I changed back to BINARY-INT, and I tried this:
MOVE J-SETSIZE(WS-BUTTON, 0, 1) TO WS-RET
Result:
$ ./testudf.exe
first call with variables
LNK-ARG-0: +0000000001
LNK-ARG-1: +0000000080
LNK-ARG-2: +0000000020
second call without variables
LNK-ARG-0: +0000000001
LNK-ARG-1: +0000000048
LNK-ARG-2: +0000000049
length of WS-BUTTON: 4
FUNCTION LENGTH: 000000004
So, 48 and 49 are the ASCII values of 0 and 1.
There are also two problems with UDF.
- wrong interpretation of numeric values.
- can not process an arithmetic expressions.
László
OK, good work, explains the first results. You're getting character 80 and 20 then interpreted as little-endian binary. The hex of those is x'3032' and x'3038', or 02 and 08, which are 80 and 20 going from left-to-right. I saw those yesterday, but not used to thinking in ASCII :-)
It looks like there should be an implicit BY VALUE for the literal in the function call, which is presumably there in an intrinsic function.
An intrinsic function can have an arithmetic expression, so I assume a UDF should as well, with the result again being passed implicitly BY VALUE.
The other parameters for a UDF call should also be checked for being passed BY VALUE. Since the source fields are defined as BINARY-INT they may well be making it look like it "works". Perhaps change those in the caller to non-binary, and we then know if the rest of the UDF call is OK or not.
I agree with Bill in that you should try a different data-type.
You say you need a signed number so why not try an 's9(4) comp' or if that's not long enough then an 's9(9) comp'. I have a UDF that returns a number indicating the start point in a string and it allways gives the correct value.
OK, I tried with 's9(9) comp':
$ ./testudf.exe
first call with variables
LNK-ARG-0: +000000001
LNK-ARG-1: +000000080
LNK-ARG-2: +000000020
second call without variables
LNK-ARG-0: +000000001
LNK-ARG-1: +942669824
LNK-ARG-2: +842006528
length of WS-BUTTON: 4
FUNCTION LENGTH: 000000004
It works with variables independent from types.
But with numeric literal:
"MOVE J-SETSIZE(WS-BUTTON, 80, 20) TO WS-RET"
I get this:
second call without variables
LNK-ARG-0: +000000001
LNK-ARG-1: +942669824
LNK-ARG-2: +842006528
With an arithmetic expression in UDF:
"MOVE J-SETSIZE(WS-BUTTON, 80 + X, 20 + Y) TO WS-RET"
I get a runtime error:
Attempt to reference unallocated memory (Signal SIGSEGV)
Abnormal termination - File contents may be incorrect
László
This bug needs fixing. There is a constraint, due to spec, UDF arguments are always call by reference, modifiable values. Always, by spec. Kinda sad, but understandable. Given that constraint, literal values become a thing. Duck typing of numeric literals in COBOL is, umm, not really conducive to foreign function interfacing, being usage display.
Still it needs to be fixed, a fix that will likely correct the same problem with CALL by value stack frame setups. CALL has explicit (though also malfunctioning for literals) SIZE IS clauses for each argument.
There is a shadow stack of cobol field structure accessible for CALL and UDF arguments from C. I'm leaning to believe that this is part of the problem. All parameters end up cast to size of pointer. Using missing bit fill, and usage display rules not synched with what GnuCOBOL or foreign library data needs.
This is a repeat of a previous post, but I'm not sure it can be solely a compile time fix. The casting may have to be run-time casting, a conditional that may slow down CALL, more than s negligible amount. Burdened with selecting the proper casting during call frame setup, at runtime; a marshaling layer penalty for each and every CALL, or FUNCTION-ID.
Guessing.
Cheers,
Brian
Last edit: Brian Tiffin 2015-01-20
View and moderate all "Help getting started" comments posted by this user
Mark all as spam, and block user from posting to "Discussion"
Perhaps GNU Cobol should support by-value function arguments as a language extension? FFI absolutely requires some solution (unless one wants to write C marshalling code – some languages do this).
We'll check this after 2.0 release and after the merge of rw-branch and debugger branch (likely needs some months) when the
CALLinterface is revised.When we do, I'd actually volunteer to try and implement a
by structenhancement along with more robust and saneby valuehandling. The JSON basedjqlibrary begs out forcall by struct. Andjqis awesome.Have good, make well,
Brian
Oh, and the spec was updated. User defined functions now support BY REFERENCE, BY VALUE, BY CONTENT phrases on arguments.
I'm not sure of the timing, exactly, but it might have something to do with Roger pointing out that user defined and intrinsic functions only allowing BY REFERENCE in the Drafts, broke the commutative properties of ADD. But that would assume someone on the committee actually heard us complaining a few years back, so probably not a true suspicion. I don't have old drafts around to see when/if the change actually occurred or if it was just a misread oversight from years gone by.
8.4.2.2, 8.4.2.2.3, 8.4.2.2.4.
Just to point out the issue (which is no longer an issue when BY VALUE is allowed/used)
could end up with a different result than
depending on whether
f()org()changedaorb. A state of affairs that would likely send some chills down some necks.Oh, and one more thing. The problem turned out to be two fold. One, it has nothing to do with the reflective shadow values, it has/had to do with datatype promotion at the C level. The dynamic call nature of GnuCOBOL did not cast all arguments in C, so all integer types were promoted to
intand all real types were promoted todoubleby C standard. Extra level of casting is now in place for CALL, but still needs work in functions. So 16 bits stay as 16 bits, etc.The other issue that still needs addressing is that function literals are passed to C as string literals. String literals have no explicit numeric type (1 2 4 or 8 bytes?), so the trick of moving through working storage for function literals is what fixes that part. Well that, and references to string literals aren't really numbers as one would assume them to be. We'll need to define some rules, and allow for casting literals with SIZE IS phrases when this eventually gets addressed.
From some discussion with Zeev when he was having issues with PCRE integration in GnuCOBOL, IBM assumes a 32bit integer for numeric literals, but this is hard documentation to come by, and Zeev found out by doing experiments.
Cheers,
Brian
Last edit: Brian Tiffin 2016-09-11
How do you find it with programs which look like they are using subscripting, but really they are using User-Defined Functions?
BY REFERENCE for a function? Someone didn't think that through.
Well, it's fixed by spec now, or at least options exist. BY REFERENCE is still the default unless explictly told otherwise. I kinda wish I had old drafts lying around, as I might be fibbing about when/if this changed, and it might just be Roger (and I) had misread things. I complained on LinkedIn, in a group that Donald Nelson reads from time to time, and no one mentioned that we had the wrong impression, but that doesn't mean we didn't. ;-)
Cheers,
Brian
The last 20xx draft has the "optional not by value" part in already but these are marked as change while UDF aren't marked as change. I'll recheck the 2002 standard for UDF and assume this is "only
BY REFERENCE".Isn't the intention of his user
FUNCTIONreally the same asCALLwith aRETURNINGclause?No, that was only a minimal example. One of the strengths of UDF is that you can use the return value directly in any expression (like conditions or computations), for
CALL ... RETURNINGyou always need to define a variable to hold the result, and when you want to compare the results of multiple items then it gets dirty quite fast - especially when you compare withEVALUATE ... WHEN FUNC-A ... WHEN FUNC-B (a, b) ...which also highlights one other benefit - you can use these in any place.So with my EBCDIC conversion I found a method to evaluate comparative expressions "in place"
(Simon helped out)
IF FUNCTION FXASCII (P1X (1:2)) > '00'
Where: P1X is a character data element populated with EBCDIC values.
Prior to having written the UDF function "FXASCII" it was required that I must:
Convert P1X to ASCII
Execute the compartive expression
Restore P1X to EBCDIC
Using a UDF simplified the requirement to convert EBCDIC data values by evaluating the expression "in place".
All that glitters is not gold :-)
There is an edict from some governing body that requires allocating huge amounts of data (something like 99,000 bytes or 1 GB) per invocation of a UDF that utilizes "Any Length" / Returning syntax.
As implemented in 3.1 Dev memory is allocated as if an arithmetic progression is in effect.
Hence 'Any Length' or perhaps any parameter indicating a return value diminishes the value of the UDF since the GetMain occurs with every execution.
Given 100 or so repetitve executions of the UDF, memory grew to over 1 GB.
I tried a "CANCEL" after each invocation - made no difference - memory allocation continued to increase.
Another concern is portability of UDF(s) to other COBOL compilers.
I do not think there is a standard implementation.
Most UDF discussions contemplate SQL.
Ralph
Last edit: Ralph Linkletter 2020-06-28