Menu

#357 add extension (new option) to allow `PROCEDURE DIVISION USING` in main programs (including modules started by cobcrun)

unclassified
accepted
5 - default
2020-07-18
2019-07-13
No

While the USING phrase of PROCEDURE DIVISION may only be used for CALLed programs, it would possible to add an extra layer which will only be activated if the program is the very first program of the run.

This layer should only be added upon explicit request (and would also allow to use -x for those programs), get another internal funtion that would do the following before calling the actual "main" entry: for each given parameter (up to the maximum amount of parameters)

  • have a cob_field defined within the function that matches the field in the LINKAGE USING (not doing an ALLOCATEof the LINKAGE field as this would break recursive program calls) and also have a local data field for each
  • create a temporary field by either FUNCTION TRIM (argv[n] TRAILING) or FUNCTION NUMVAL (argv[n]) - depending on the class of the target field "n"
  • do an internal MOVE from the temporary field to the local one
  • set the linkage field pointer to the local field and adjust the counter of "passed" fields according to argc

Related

Discussion: CALLing main programs
Discussion: error: executable program requested but PROCEDURE/ENTRY has USING clause zOS compatibility ?
Wish List: #358
Wish List: #471

Discussion

  • Edward Hart

    Edward Hart - 2020-07-02

    Attached is an initial patch for this. It effectively adds a wrapper for the program within main. The program is compiled as normal (with -x) and, when executed, is passed the first argument from the command-line.

    To do:

    • No dialect config option (or Micro Focus directive).
    • No checking of the size of the parameter. The discussion [c352ac53b1] suggested there is a limit of 100. We could ignore this.
    • Truncation behaviour. If the argument is too large to fit in the parameter, is the size field set to the original size of the parameter or to its truncated size?
    • No consideration of cobcrun.
    • Perhaps an option to set the parameter from the environment variable PARM or COB_PARM instead?
     

    Related

    Discussion: c352ac53b1


    Last edit: Edward Hart 2020-07-02
    • Simon Sobisch

      Simon Sobisch - 2020-07-03

      Edward, it seems like you've mixed this FR with [feature-requests:#358].
      They are very related and it would be useful to either implement or at least prepare them together, but they are still separate.

       

      Related

      Wish List: #358

  • Edward Hart

    Edward Hart - 2020-07-02
    • labels: --> IBM compatibility, ibm
    • assigned_to: Edward Hart
     
  • Simon Sobisch

    Simon Sobisch - 2020-07-03

    I've rechecked the standard on this, the current draft says (unchanged) under 14.2 Procedure division structure, general rule 13:

    When either the activating or the activated runtime element is other than a COBOL runtime element, the implementor shall specify the restrictions and mechanisms for all supported language products.
    NOTE The details of these restrictions and mechanisms might include parameter matching, representation of a data type, return of a value, and omission of parameters.

    And we do see that different COBOL environments handle this differently, starting with forbidding, ending with different set of "magic" rules.

    Therefore this topic "main and linkage" (-fmain-linkage=enum) should be handled as dialect option with providing at least the values:

    • mapping: do what is specified in this ticket -> code-generated in the entry as mentioned here, only triggered if tthe program is not the first active in the run-time unit
    • warn (only relevant for -x, would be set in all "standard" COBOL dialects): common warning (which is raised because of likely portability issues), then go an as-if "mapping" was active
    • error (only relevant for -x and is the current behaviour), if -x was not used the code generation would stay as-is
    • chaining (this is for MF compatibility which specifies that "CHAINING and USING are considered identical") - but again; only active if the program is found to be the first in the runtime unit; rules for what happens withg CHAINGING (I'm not sure if we already do it that way):
      • If the program is initiated from the host operating system, each parameter is initialized to the corresponding command-line argument
      • Values are assigned to each parameter as if the value were the alphanumeric source for an elementary MOVE to parameter. If parameter is not alphanumeric, then it is treated as if it were implicitly redefined as alphanumeric before this MOVE occurs.
      • If there are fewer arguments than parameters, then the excess parameters are initialized according to the rules that would apply if they were not listed in the CHAINING phrase.
      • If there are more arguments than parameters, the excess arguments are ignored.
    • parm, see [feature-requests:#358]
    • unix, this is to handle for the [IBM z/OS UNIX handling}[1]: three parameters passed by reference:
      • Argument-count: a binary fullword integer containing the number of elements in each of the arrays that is passed as the second and third parameters.
      • Argument-length-list: an array of pointers. The Nth entry in the array is the address of a fullword binary integer containing the length of the Nth entry in the Argument-list (the third argument).
      • Argument-list: an array of pointers. The Nth entry in the array is the address of the Nth character string passed as an argument on the spawn(), exec(), or command invocation.
    • posix, argc+argv stored in libcob passed as-is, the parameters may be accessed by FUNCTION CONTENT-OF or manually UNSTRING .. DELIMITED BY LOW-VALUE

    In any case the check "am I the first program" and then the "trigger" to setup the parameters depending on the value of the main-linkage dialect option should be generated, the actual functions that handle this (in cases "mapping" and "chaining" passing the fields as vararg) should be found in libcob/call.c

     

    Related

    Wish List: #358


    Last edit: Simon Sobisch 2020-07-09
  • Edward Hart

    Edward Hart - 2020-07-09

    Attached is a quick update.

    • Added main-linkage option as above, but with "mapping" renamed to "parm" - I think the IBM terminology will be more familiar to users.
    • Added the COMMANDLINELINKAGE directive.

    It remains to extract all the new codegen code to a new function in libcob/call.c.

     
    • Simon Sobisch

      Simon Sobisch - 2020-07-09

      The actual handling of the parm value and the CMDLINELINKAGE directive is noted in [feature-requests:#358] - mapping is very different from this as this maps possibly multiple entries directly ´(similar to CHAINING but the variables included in LINKAGE and internally MOVEd to from intermediate fields, possibly with a numeric conversion).
      Please keeo those "mapping", what this FR was initialially about and "parm" logically separate (I'm also fine with a single commit implementing both FR at once, they are obviously very related).

      The new config option (otherwise than the missing first entry "mapping") is fine, for acu.conf it seems it should be set to error, at least from its documentation. RM/COBOL and Realia looks fine, I've just dropped a quote from its doc in the other FR.

      I've not checked any part of the codegen yet, but here's a test case for the mapping value:

      AT_SETUP([mapping LINKAGE in main program])
      AT_KEYWORDS([misc])
      
      AT_DATA([prog.cob], [
      
             IDENTIFICATION   DIVISION.
             PROGRAM-ID.      prog.
      
             DATA             DIVISION.
             WORKING-STORAGE  SECTION.
      
             LINKAGE          SECTION.
             01  name-set.
                 03  name1    PIC X(10).
                 03  name2    PIC X(10).
             01  some         PIC XX
             01  x            PIC 9(4).
             01  y            PIC S999v99.
      
             PROCEDURE        DIVISION USING name-set x y some.
                 DISPLAY name1 ': ' x
                 DISPLAY name2 ': ' y ' - ' some '.'
                 .
      ])
      AT_CHECK([$COMPILE -fmain-linkage=mapping prog.cob], [0], [], [])
      AT_CHECK([$COBCRUN_DIRECT ./prog "Mister    Moe" 1 15 -42.3], [0],
      [Mister    : 0001
      Moe       : -042.30 - 1 .
      ])
      
       

      Related

      Wish List: #358

  • Edward Hart

    Edward Hart - 2020-07-10

    Patch version 3:

    • parm shim moved to call.c,
    • -fmain-linkage=mapping added as pending (along with testsuite entry above).

    The actual handling of the parm value and the CMDLINELINKAGE directive is noted in [feature-requests:#358] - mapping is very different from this as this maps possibly multiple entries directly

    Thanks for this! I hadn't seen the difference between #357 and #358 before you mentioned this. Well, I'll keep posting patches here for consistency's sake.

    ... acu.conf it seems it should be set to error, at least from its documentation.

    I think chaining is right - General Rule 6 describes how CHAINING works. Is that not what -fmain-linkage=chaining should do?

     

    Related

    Wish List: #358

    • Simon Sobisch

      Simon Sobisch - 2020-07-10

      I'm fine with the patch-posting here, as long as the differences are clear :-)

      Yes, CHAINING behaviour is what should happen for -fmain-linkage=chaining, which is (according to the MF docs) what MF does, but ACUCOBOL explicit specifies that LINKAGE may not be used for main programs and CHAINING only for main programs, which is why I think it should be an error there)

      So... what are the thing you want to add to this patch and what rough time estimate do you have for this?

       
      • Edward Hart

        Edward Hart - 2020-07-11

        I think I've basically done [feature-requests:#358] now, so I would like to commit the patch as-is.

        As for what to do next:

        1. posix should be very quick to do
        2. unix should also be relatively easy
        3. chaining syntax checks will also be easy
        4. chaining implementation might take a while and would probably be best done with the (MF/AcuCOBOL) CHAIN or (RM/COBOL) CALL PROGRAM statements
        5. mapping might be quite hard - I think it will have to be implemented in cobc/codegen.c, instead of a wrapper in libcob/call.c
         

        Related

        Wish List: #358


        Last edit: Edward Hart 2020-07-11
        • Simon Sobisch

          Simon Sobisch - 2020-07-11

          CHAIN / CALL PROGRAM would be nice but should be definitely kept out here. If we don't have a FR for this please create it. You're inbited to handle it, of course, but that's not mandatory.

          I think it would be something like:

          • try to resolve the target, if it doesn't work -> common exception handling, program goes on
          • if it does work: "register" the call and copy the arguments to a new static argc/argv array
          • internally do a STOP RUN (we'd have to check if the file tear-down should be done or the file states have to be kept)
          • as part of this: if the call was registered: do a cob_init with the static argc/argv and start the new program

          For -fmain-linkage=chaining we'd have to condidtionally call the wrapper (= the default is the normal LINKAGE handling but if it is the first module then the handling we normally only generate for CHAINING gets activated).

          I think mapping should be relative easy and be possible in libcob/call.c:

          • again: only call the wrapper if the program is the first active
          • pass the PROCECDURE DIVISION USING fields as vararg to the wrapper
          • depending on the field definition the wrapper allocates the storage and assign it to the fields, then set the value with the recently added cob_put_field_str, if that returns EINVAL cob_move a zero to it.
           
  • Edward Hart

    Edward Hart - 2020-07-17

    Patch version 4: cobcrun support added, with a new parameter --param. This is some ugliness:

    • The options for PARM-style linkage depends on the endianness of COMP, which must be indicated by --param=parm-big-endian or --param=parm-native.
    • I chose a random number of 1024 for the maximum size of the parameter. This could be too small or could lead to spurious "OCCURS DEPENDING ON out of bounds" errors. (I'm open to ideas for a better constant.) Maybe add a compiler warning if a program has a PARM-like parameter and is being compiled as a module?

    EDIT: Forgot to attach the patch.

     

    Last edit: Edward Hart 2020-07-17
    • Simon Sobisch

      Simon Sobisch - 2020-07-17

      Thank you for keeping working on this!

      I need to inspect the patch to say something to this, so here only to your comments:
      it should be completely supported to have PARM'd programs as modules, and you can actually CALL those on the mainframe, too.
      The maximum size is whatever the maximum in the definitions from IBM I be copied here or in the related FR says.
      The actual size passed to the program should be trimmed to the arguments size.

      For the first iteration we should use the default endianness, and for a second one load the module only first (if we don't have a special entry point for that yet it should be added in any case) and then read a (possibly new) flag on the module structure specifying the expected endianness.

       
    • Simon Sobisch

      Simon Sobisch - 2020-07-18

      Rechecked with the patch: as noted before cobcrun should not get (nor need) a new param option - it will just do the initialization "as always" and the minimal difference in the codegen (according to the compile option) will recognize "I'm main" and ask libcob for the necessary setup, and could also specify the expected endianness for PARM.

      Just wondering: Why did you change output_line to a manual output + line in the one codegen place?

       

Log in to post a comment.