OCamlPro / gnucobol

A clone of the sourceforge GnuCOBOL compiler from COBOL to C.
https://get-superbol.com
GNU Lesser General Public License v3.0
16 stars 21 forks source link

Move static variables to local state structures in libcob/strings.c #137

Closed engboris closed 1 month ago

engboris commented 6 months ago

Answer to feature request #448 on Sourceforge.

Problem

The handling of the INSPECT, STRING and UNSTRING statements in libcob/strings.c is an obvious source of unthread-safe code because it relies on a lot of static variables.

The idea was to:

Comments about the modifications

In each generated C program, state structures are defined as local variables and used by the functions for INSPECT, STRING and UNSTRING statements.

Some "local" variables where static without any serious reason: figurative_ptr, figurative_size, alpha_fld and str_cob_low. The static keyword has been removed.

:warning: The cobglobptr variable is still static. I am not sure how to deal with it. What I have in mind is to turn it into a function argument and pass it to function calls in the generated C code (where it is defined as a local variable in .c.l.h files). But this probably goes outside the scope of the intial problem.

Testing

I added a new test suite tests/testsuite.src/backcomp_strings.at which contains the C code (compiled with the compiler before my modifications) for each tests of tests/testsuite.src/run_misc.at dealing with the INSPECT, STRING and UNSTRING statements.

All tests of the new test suite passes with both the version of the compiler before and after my modifications.

engboris commented 1 month ago

Ok, I'll try something

engboris commented 1 month ago

Unfortunately, several tests could only be compiled on GC 3.2 instead of GC 2.2 (expected minimal backward compatibility)...

GitMensch commented 1 month ago

That's strange - which ones? The only one I can think of are new elements like the GCOS TRANSFORM statement (that would only be reasonable to include with a 3.1.2 codegen if it was in and changed in 3.2, otherwise it can be dropped as the statement itself should be completely tested in the other parts of the testsuite yet.

engboris commented 1 month ago

Some have already been mentioned before:

And new ones:

My own personal testing file (compiled on 3.1) has the following error:

missing value between CHARACTERS/ALL/LEADING/TRAILING words

(but works fine in GC 3.1+)

engboris commented 1 month ago

Here is the test I use to cover strings: strings_stmt.txt

GitMensch commented 1 month ago

these are all no backward-compatibility points, so can be dropped here until we change the codegen

TRANSFORM and EXAMINE are new in 3.2, codegen shouldn't be different in 3.3dev

new ones: instead of EBCDIC use "EBC" and define that as an alphabet in the program, defined as EBCDIC; the two others should work when you directly code the collating sequence in the program instead of compiling with -fdefault-colseq - and those should definitely be tested

for your personal test: just comment that first part out, as the codegen was not possible with 2.2

engboris commented 1 month ago

the two others should work when you directly code the collating sequence in the program instead of compiling with -fdefault-colseq - and those should definitely be tested

How I did it (same for ASCII, by commenting/commenting out the right parts):

      IDENTIFICATION   DIVISION.
       PROGRAM-ID.      prog.
       ENVIRONMENT DIVISION.
       CONFIGURATION SECTION.
           OBJECT-COMPUTER.
             x86 PROGRAM COLLATING SEQUENCE IS EBCDIC-CODE.
       SPECIAL-NAMES.
           ALPHABET EBCDIC-CODE IS EBCDIC.
       PROCEDURE        DIVISION.
      * IF   EXPECT-ORDER  =  'ASCII'
      *    IF "1" NOT < "a"
      * ELIF EXPECT-ORDER  =  'EBCDIC'
           IF "a" NOT < "1"
      * END-IF
              DISPLAY "ERROR" END-DISPLAY
           END-IF.
           STOP RUN.
GitMensch commented 1 month ago

That's the way to go and works fine, right?

engboris commented 1 month ago

If works for everything except one test. It's weird but I get 'ERROR' when running tests with Alphanum comparison with default COLLATING SEQUENCE for EBCDIC but when I compile it myself it works well (no output) with cobc -x prog.cob -o prog then ./prog. There might be something I'm missing (the tests have been pushed).

engboris commented 1 month ago

Ok, I just realized it only works for GC 3.2+ (it's the code above)

GitMensch commented 1 month ago

If I understood correctly the test may better be named COLLATING SEQUENCE alphanum comparison and can drop default-colseq from the keywords. You also want to drop -fdefault-colseq and -DEXPECT from the command line as you already use the generated ebcdic.c (or ascii.c) so those should not be used any more.

When generating those with cobc 2.2 you'd best use two different programs one with ASCII and one with EBCDIC collation and expectation (not only drop the ascii, as this is likely not working when running the test on an ebcdic machine later).

engboris commented 1 month ago

The program for EBCDIC doesn't work (ERROR is displayed) before 3.2 (but works for 3.2 and 3.3~dev). I assume this is because EBCDIC wasn't correctly supported before? Maybe we should drop this test?

GitMensch commented 1 month ago

Checked and recognized the error when adding -Wall (that's commonly useful if something is strange):

warning: expression 'a' GREATER OR EQUAL '1' is always TRUE

With GC 2.2 you should compile both tests with -fno-constant-folding (it is otherwise falsely applied to the native collation).

engboris commented 1 month ago

OK everything should be fine now :pray:

ddeclerck commented 1 month ago

Ah, forgot about this one, I'll take care of merging it on SVN.

ddeclerck commented 1 month ago

Merged on SVN @ 5302 (to reattribute to Boris).

GitMensch commented 1 month ago

thanks, done

engboris commented 1 month ago

@GitMensch I just want to thank you for all your (meticulous) reviews even though I was struggling sometimes and had a lot of catching up to do on a lot of things. This PR is not great change to GnuCOBOL but I actually learned a lot.

GitMensch commented 1 month ago

Is the upstream update from gnucobol-3.x branch to gcos4gnucobol-3.x automatic or does this need to be manually triggered, or even done?

ddeclerck commented 1 month ago

We manually merge gnucobol-3.x into gcos4gnucobol-3.x from time to time. I'll do that in a bit.