Bettering cob_call

  • Brian Tiffin
    Brian Tiffin

    Hello all,

    We have

            unifunc.funcvoid = cob_resolve_cobol (name, 0, 1);
            pargv = cob_malloc (COB_MAX_FIELD_PARAMS * sizeof(void *));
            /* Set number of parameters */
            cobglobptr->cob_call_params = argc;
            for (i = 0; i < argc; ++i) {
                    pargv[i] = argv[i];
            i =  unifunc.funcint (pargv[0], pargv[1], pargv[2], pargv[3],
                                    pargv[4], pargv[5], pargv[6], pargv[7],
                                    pargv[8], pargv[9], pargv[10], pargv[11],
    #if     COB_MAX_FIELD_PARAMS == 16
                                    pargv[12], pargv[13], pargv[14], pargv[15]);
    #elif   COB_MAX_FIELD_PARAMS == 36
                                    pargv[12], pargv[13], pargv[14], pargv[15],
                                    pargv[16], pargv[17], pargv[18], pargv[19],
                                    pargv[20], pargv[21], pargv[22], pargv[23],
                                    pargv[24], pargv[25], pargv[26], pargv[27],
                                    pargv[28], pargv[29], pargv[30], pargv[31],
                                    pargv[32], pargv[33], pargv[34], pargv[35]);
    #error  "Invalid COB_MAX_FIELD_PARAMS value"
            free (pargv);
            return i;

    at the end of cob_call in libcob/call.c

    Umm, this is amazingly powerful, with the shadow parameter blocks elsewhere in the code, adding reflective properties to the run-time, but, it borks a lot of foreign interface code.

    All these parameters are put on the call stack assuming a reference, 8 bytes on 64 bits, 4 on 32 (roughly, yada yada edge cases). This doesn't really allow for mixing float and double BY VALUE, for instance. So, at least two lines of C are required every time there is a function signature special case. Most times, CALL works by default, but sometimes by fluke, on particular hardware, but may not on t'others.

    This code needs casting, which blows, but without the proper sizing, GNU Cobol remains limited in library access without a helper C file.

    Need to move the information from SIZE IS ala

    CALL "thing" BY VALUE SIZE 4 float BY VALUE SIZE 8 double RETURNING size-known-by-def

    into cob_call. Current sizes allow for 1,2,4,8.

    And, ... more soon.


    Last edit: Brian Tiffin 2014-05-13
  • Simon Sobisch
    Simon Sobisch

    Sounds interesting. If I understood it correctly you want to invent a new GNU COBOL-only extension (likely with a change to parser.y, codegen.c and call.c).

    If yes I'd suggest to use

    CALL "c_library_function"
         BY VALUE  float-item  SIZE IS 4
         BY VALUE  double-item SIZE IS 8
         RETURNING size-known-by-def

    and maybe add a conf option if this is OK or not (set to true in default.conf while set to false in all others).


    • Brian Tiffin
      Brian Tiffin

      The compiler already supports SIZE IS for BY VALUE call fields and PROCEDURE DIVISION USING BY VALUE fields. (I pestered Roger a long time ago, then he allowed float by value too, but... there are limitations due to the shadowing).

      Syntax is already in as

      CALL "thing"
         BY VALUE SIZE IS 4 field

      we just need to implement something like

      i = unifunc.funcint (
      (params[0]->size == 1) ? (force-1)pargv[0] : (params[0]->size == 2) ?  (force-2)pargv[0] : (params[0]->size == 4) ? (force-4)pargv[0] : (force-8)pargv[0],
      (params[1]->size == 1) ? (force-1)pargv[1]...,

      36 times. I think. It'd be smart to check for 4 first, the default, then 8 then the 2 and 1 etc, and testing, lots and lots of testing.

      Where the force-1, force-2, are types that will inform C to lay down the right sized item. Sadly, this is run-time testing, on each CALL frame build, but, not bad for the extra correctness, I'd opine.

      Roger also put in SIZE IS AUTO, which might help with float double, int long scenarios, but that could be a fair pile of tests in cob_call.

      Will play around soon.

      On a 64 bit machine the MathGL example works, but it'll likely be misaligned on 32 bit as MathGL is expecting 8 byte doubles.

      Writing a PDF writer with libharu today, font size needs to be a float, won't work on 64bit, probably would on 32. (Two hours of staring at a line of code that should have worked, (being all einstein and trying the same thing over and over again, expecting different results) prompting this post)


      This can be fixed, or for the now, for anyone reading along, it can ALWAYS be made to work with a few lines of C in the middle. So nothing is ever out of reach.


      Last edit: Brian Tiffin 2014-05-13