From this Micro Focus documentation on CALL prototypes I believe to have learned that I can write program prototypes (just like in a C/C header file) and use them to have Visual COBOL validate my CALL parameters. As far as I understood, a program prototype is created by appending the IS EXTERNAL qualifier to the prototype's Program-Id.
Yet, I don't seem to be able to correctly describe my program parameters. The JIT compiler is always complaining (see error messages in the screenshot below).
The error messages I get don't give hints on what to do in order to solve the problem, so they are leaving me in a dead-end situation.
What am I doing wrong?
Your answers are highly appreciated.
Please find my sample project in the ZIP file attached.
And below is a screenshot depicting the main source file (containing the prototype, the corresponding contained subprogram, and the main program).

BlackKnight,
The USING parameters in your call prototype do not specify how the parameters are passed, the default being BY REFERENCE. So, as you are using BY CONTENT in the CALL statement itself for the first two parameters there is a mismatch, hence the error. So you need to either change the call prototype to specify BY CONTENT if that is how you actually want to pass the parameters or remove the BY CONTENT from the CALL statement if the call prototype is correct.
Gael
From this Micro Focus documentation on CALL prototypes I believe to have learned that I can write program prototypes (just like in a C/C header file) and use them to have Visual COBOL validate my CALL parameters. As far as I understood, a program prototype is created by appending the IS EXTERNAL qualifier to the prototype's Program-Id.
Yet, I don't seem to be able to correctly describe my program parameters. The JIT compiler is always complaining (see error messages in the screenshot below).
The error messages I get don't give hints on what to do in order to solve the problem, so they are leaving me in a dead-end situation.
What am I doing wrong?
Your answers are highly appreciated.
Please find my sample project in the ZIP file attached.
And below is a screenshot depicting the main source file (containing the prototype, the corresponding contained subprogram, and the main program).

It looks as if the two 1057 errors have occurred because the compiler was incorrectly giving an error when the prototype used BY REFERENCE and the CALL statement had BY CONTENT. This has been fixed in the latest, soon to be released, (V6) version of the product.
The 1059 error is because the length of the parameter specified in the CALL statement (15) is less than the length specified in the prototype (20). The error is reasonable, since memory could be corrupted if the called program moves data into the full length of the parameter. However I must admit that I did not at first understand what was causing it, and a clearer description would certainly be helpful.
It looks as if the two 1057 errors have occurred because the compiler was incorrectly giving an error when the prototype used BY REFERENCE and the CALL statement had BY CONTENT. This has been fixed in the latest, soon to be released, (V6) version of the product.
The 1059 error is because the length of the parameter specified in the CALL statement (15) is less than the length specified in the prototype (20). The error is reasonable, since memory could be corrupted if the called program moves data into the full length of the parameter. However I must admit that I did not at first understand what was causing it, and a clearer description would certainly be helpful.
Hi, Gael and Robert,
:
> The USING parameters in your call prototype do not specify how the parameters are passed, the default being BY REFERENCE.
Actually, the only values available for the prototype declaration are REFERENCE and VALUE. There is no CONTENT option:

When I type BY CONTENT manually, the JIT compiler gives errors:

If I use BY VALUE instead (as suggested by COBOL IntelliSense) the JIT COBOL compiler returns errors, too:
So there is actually no option available to make this work. Or do you see another option here?
:
Thanks for sharing this information!
Yet, there's one more thing that doesn't seem right to me:
When I omit the IS EXTERNAL clause and just create a copy of the full subprogram, the compiler doesn't give errors, even when I change the PROCEDURE DIVISION in one of the two instances:

Is this behaviour supposed to be expected?
Hi, Gael and Robert,
:
> The USING parameters in your call prototype do not specify how the parameters are passed, the default being BY REFERENCE.
Actually, the only values available for the prototype declaration are REFERENCE and VALUE. There is no CONTENT option:

When I type BY CONTENT manually, the JIT compiler gives errors:

If I use BY VALUE instead (as suggested by COBOL IntelliSense) the JIT COBOL compiler returns errors, too:
So there is actually no option available to make this work. Or do you see another option here?
:
Thanks for sharing this information!
Yet, there's one more thing that doesn't seem right to me:
When I omit the IS EXTERNAL clause and just create a copy of the full subprogram, the compiler doesn't give errors, even when I change the PROCEDURE DIVISION in one of the two instances:

Is this behaviour supposed to be expected?
Hi BlackKnight, I believe this is expected behaviour.
When you omit EXTERNAL in the first definition of PrintValue, you create an actual entry point (although one that doesn't do very much). The second instance of PrintValue is a nested program, and only visible from within its containing program Program1. As such, it is permitted to have different parameters from the first PrintValue. If you remove PrintValue from Program1 (i.e. place it after end program Program1), you'll find you do get errors, at least when compiling for .NET.
Hi BlackKnight, I believe this is expected behaviour.
When you omit EXTERNAL in the first definition of PrintValue, you create an actual entry point (although one that doesn't do very much). The second instance of PrintValue is a nested program, and only visible from within its containing program Program1. As such, it is permitted to have different parameters from the first PrintValue. If you remove PrintValue from Program1 (i.e. place it after end program Program1), you'll find you do get errors, at least when compiling for .NET.
:
Following your explanation I conducted the following test:
I commented the nested subprogram while at the same time I kept the - as you named it - second entry point (Below I attached the new, amended sample project with this message).
Then I made a, well, unexpected observation:
(Please pardon me for now asking a COBOL programming question rather than a Micro Focus question. I need some enlightenment here, I'm afraid.)
After removing the nested subprogram by commenting it, I didn't get a COBOL compiler error for the CALL statement that was calling the nested subprogram. "OK", I thought, "that's because there is a second entry point with the same name, so COBOL will call the second entry point with the same name then."
Then, after building the project, I still didn't get any error. So, apparently, the COBOL linker seemed to have found the second entry point as destination for the CALL statement.
But when I then ran the program, I got a runtime error, telling me that the called program could not be found:

So, while neither the compiler nor the linker seemed to have trouble finding and identifying the entry point, the runtime did?? So there is no compile time check available for this situation?
Nonetheless, is it true then, that the CALL statement can find nested subprograms and entry points in other files, but it cannot find an entry point from the same file?

Is this really true? Or did I do something wrong?
:
Following your explanation I conducted the following test:
I commented the nested subprogram while at the same time I kept the - as you named it - second entry point (Below I attached the new, amended sample project with this message).
Then I made a, well, unexpected observation:
(Please pardon me for now asking a COBOL programming question rather than a Micro Focus question. I need some enlightenment here, I'm afraid.)
After removing the nested subprogram by commenting it, I didn't get a COBOL compiler error for the CALL statement that was calling the nested subprogram. "OK", I thought, "that's because there is a second entry point with the same name, so COBOL will call the second entry point with the same name then."
Then, after building the project, I still didn't get any error. So, apparently, the COBOL linker seemed to have found the second entry point as destination for the CALL statement.
But when I then ran the program, I got a runtime error, telling me that the called program could not be found:

So, while neither the compiler nor the linker seemed to have trouble finding and identifying the entry point, the runtime did?? So there is no compile time check available for this situation?
Nonetheless, is it true then, that the CALL statement can find nested subprograms and entry points in other files, but it cannot find an entry point from the same file?

Is this really true? Or did I do something wrong?
So, while neither the compiler nor the linker seemed to have trouble finding and identifying the entry point, the runtime did?? So there is no compile time check available for this situation?
The COBOL CALL statement is, by default, resolved at runtime. This is explained in the product documentation, at some length. See for example the reference text for CALL ("Alternatively, the name of the called program may be a name which identifies a file that contains executable program code for the called program") and the various topics under COBOL Programming > Calling COBOL Programs.
When you have a CALL "literal" statement in your program, it is not (by default) resolved at compile time; it's resolved at runtime. There are compiler options to change this behavior.
So, while neither the compiler nor the linker seemed to have trouble finding and identifying the entry point, the runtime did?? So there is no compile time check available for this situation?
The COBOL CALL statement is, by default, resolved at runtime. This is explained in the product documentation, at some length. See for example the reference text for CALL ("Alternatively, the name of the called program may be a name which identifies a file that contains executable program code for the called program") and the various topics under COBOL Programming > Calling COBOL Programs.
When you have a CALL "literal" statement in your program, it is not (by default) resolved at compile time; it's resolved at runtime. There are compiler options to change this behavior.
So, why isn't it found then if it's in the same file? A nested subprogram would also reside in the same file.
So, why isn't it found then if it's in the same file? A nested subprogram would also reside in the same file.
I don't know. I can't tell what your code currently looks like, from the hash of screenshots in your various posts. I'm disinclined to try to read code in screenshots anyway; they're not an accommodating medium. If you posted a text representation of code, inline or in an attachment, that you believe behaves incorrectly or in an unexpected way I could take a look, time permitting. Or someone else may respond.
I don't know. I can't tell what your code currently looks like, from the hash of screenshots in your various posts. I'm disinclined to try to read code in screenshots anyway; they're not an accommodating medium. If you posted a text representation of code, inline or in an attachment, that you believe behaves incorrectly or in an unexpected way I could take a look, time permitting. Or someone else may respond.
Certainly a CALL statement will find entry points specified in the same file as the CALL statement itself.
Did you remove the word EXTERNAL from the first instance of PrintValue (i.e. did you convert it from a prototype into an actual code entry point)? If PrintValue is only defined as a prototype in your code, then the error 173 is expected.
But yes, as Michael says, when compiling to native code there is no compile-time check for the existence of the entry point specified in the CALL literal statement. When compiling for .NET or JVM, a warning will be produced if a suitable entry point is not found.
Certainly a CALL statement will find entry points specified in the same file as the CALL statement itself.
Did you remove the word EXTERNAL from the first instance of PrintValue (i.e. did you convert it from a prototype into an actual code entry point)? If PrintValue is only defined as a prototype in your code, then the error 173 is expected.
But yes, as Michael says, when compiling to native code there is no compile-time check for the existence of the entry point specified in the CALL literal statement. When compiling for .NET or JVM, a warning will be produced if a suitable entry point is not found.
: Please refer to my previous comment in regard to code attached: There, you can see that I attached the sample project to my message. (Quote: "Below I attached the new, amended sample project with this message.")
et al.:
Thank you for trying to shed light on this issue.
"Search Conventions Used for Calling Programs" reads: "When a program is called, the run-time system checks to see if the program has already been loaded or logically canceled. If the program is already available in memory, the run-time system passes control to it." -
The program to be called resides in the same file the calling program is in. So, the program should have been loaded into memory; particularly as it precedes the calling program in code. So, I would assume it to be found.
: Please refer to my previous comment in regard to code attached: There, you can see that I attached the sample project to my message. (Quote: "Below I attached the new, amended sample project with this message.")
et al.:
Thank you for trying to shed light on this issue.
"Search Conventions Used for Calling Programs" reads: "When a program is called, the run-time system checks to see if the program has already been loaded or logically canceled. If the program is already available in memory, the run-time system passes control to it." -
The program to be called resides in the same file the calling program is in. So, the program should have been loaded into memory; particularly as it precedes the calling program in code. So, I would assume it to be found.
Hi BlackKnight,
The 173 error is due to a bug in the way the project gets built. If you move PrintFunction after Program1 in Program1.cbl it will work.
And just to add to the comments about CALLs being resolved at run-time, they are absolutely correct. However, you *can* get them to be resolved at build time by using the LITLINK compiler directive or by specifying a call-convention in the special-names and using it on the call statements. eg
environment division.
special-names.
call-convention 8 is litlink.
and then use
call litlink "prog"
Gael
Hi BlackKnight,
The 173 error is due to a bug in the way the project gets built. If you move PrintFunction after Program1 in Program1.cbl it will work.
And just to add to the comments about CALLs being resolved at run-time, they are absolutely correct. However, you *can* get them to be resolved at build time by using the LITLINK compiler directive or by specifying a call-convention in the special-names and using it on the call statements. eg
environment division.
special-names.
call-convention 8 is litlink.
and then use
call litlink "prog"
Gael
:
I did as you suggested:
- I moved the program prototype below the calling program (due to the compiler error you mentioned).
- I uncommented the actual subprogram (from the sample code I provided in my previous comment).
The result:
- Another unexpected compiler error.
- The prototype does not check calling arguments.
See this animation for details:

Am I still doing something wrong here?
:
I did as you suggested:
- I moved the program prototype below the calling program (due to the compiler error you mentioned).
- I uncommented the actual subprogram (from the sample code I provided in my previous comment).
The result:
- Another unexpected compiler error.
- The prototype does not check calling arguments.
See this animation for details:

Am I still doing something wrong here?
As I said in my previous reply I simply moved the code in $region PrintValue below the code for Program1. I did not uncomment anything or create any prototypes. That worked for me.
The change you made did not create a program prototype because the code is still in the procedure division. You would need to remove that and the working-storage section. When I did that, that also worked for me.
I have attached Program1.zip containing a prototype for PrintValue at the top of the file and the uncommented version of PrintValue at the bottom, which is what I think you intended.
As I said in my previous reply I simply moved the code in $region PrintValue below the code for Program1. I did not uncomment anything or create any prototypes. That worked for me.
The change you made did not create a program prototype because the code is still in the procedure division. You would need to remove that and the working-storage section. When I did that, that also worked for me.
I have attached Program1.zip containing a prototype for PrintValue at the top of the file and the uncommented version of PrintValue at the bottom, which is what I think you intended.
Hi, ,
today, I used your code version ... and I still got the same errors/warnings as before:

You wrote that this version is showing no flaws on your machine equipped with Visual COBOL v6.x.
So, summing up this issue:
- Everything is alright with my/your code.
- It's Visual COBOL version 5.x that's giving false warnings. Version 6.x is not going to show these warnings.
Would you please kindly confirm? Then I will be able to tick off this issue.
----
PS: Your piece of code is missing the DATA DIVISION line in front of the LINKAGE SECTION line. Yet, this doesn't appear to be an error. Is this behaviour correct?
Hi, ,
today, I used your code version ... and I still got the same errors/warnings as before:

You wrote that this version is showing no flaws on your machine equipped with Visual COBOL v6.x.
So, summing up this issue:
- Everything is alright with my/your code.
- It's Visual COBOL version 5.x that's giving false warnings. Version 6.x is not going to show these warnings.
Would you please kindly confirm? Then I will be able to tick off this issue.
----
PS: Your piece of code is missing the DATA DIVISION line in front of the LINKAGE SECTION line. Yet, this doesn't appear to be an error. Is this behaviour correct?
Previously you were getting build errors and errors at run-time and the changes I suggested were to allow you to progress past those. I have tried 5.0 and see the same warnings you have shown but the code does run correctly and you can step into the PrintValue program, which is what you were unable to do before.
The warnings do not occur in 6.0.
When using the Micro Focus dialect to compile you can omit part of the program structure and the compiler will compile the code without any problem so, yes, that is correct. But if you wanted to use a different dialect, for compatibility with a mainframe for example it would need to be present.
Previously you were getting build errors and errors at run-time and the changes I suggested were to allow you to progress past those. I have tried 5.0 and see the same warnings you have shown but the code does run correctly and you can step into the PrintValue program, which is what you were unable to do before.
The warnings do not occur in 6.0.
When using the Micro Focus dialect to compile you can omit part of the program structure and the compiler will compile the code without any problem so, yes, that is correct. But if you wanted to use a different dialect, for compatibility with a mainframe for example it would need to be present.
Thank you very much, , for being so patient and passionate to aid me through my question. Your answers (plus the answers of the and ) have been very helpful to me.
Cheers,
Axel