REPORT ON PORT OF ELECT COBOL APPLICATIONS

1. PROJECT SCOPE

The ELECT Application Suite comprises programs written in C and COBOL. The COBOL compiler in use was obsolete long ago. By using LINUX reverse compatibility loadable modules (iBCS/COFF), it was possible to compile COBOL to s-code and to run the COBOL interpreter. Thus we were able to continue using the original compiler, which is now over twenty years old. With each release of LINUX and change of hardware (e.g. 64-bit architecture), it became more difficult to maintain this strategy.

A project was undertaken to port the COBOL sources using the OpenCOBOL compiler to enable ELECT to run on current versions of LINUX on 32 and 64-bit platforms.

This report describes the differences between the superseded and superseding compilers encountered when porting the software, but only to highlight the hurdles other developers will need to clear when moving to OpenCOBOL. None of the comments in this report should be construed as a criticism of either COBOL compiler: the author is not qualified to comment on a compiler's adherence to ANSI Standards, etc. Nor is it the authors intention to attribute fault to either compiler. It is simply a matter of: difference. Inevitably, this report focuses on the differences - this may give a false impression. BCS have found OpenCOBOL to be well-featured, well-documented, robust and suitable for our production needs.

BCS/JR June 2012

2. THE SUPERSEDED COMPILER

The COBOL compiler in use is: Micro Focus COBOL/2 v1.1 revision 0

This compiler was installed in 1997.

The compiler was used to generate .int files which were interpreted at run time by the Micro Focus cobrun binary. The compiler was not used to generate executable binaries. Therefore this report relates to a specific compiler used in a specific way.

ELECT uses BCS developed screen-handling instead of COBOL display handling; so this area is not mentioned in this report.

ELECT used the Micro Focus supplied ISAM Handler to support indexed-files.

3. THE SUPERSEDING COMPILER

This report refers to two versions of OpenCOBOL: a reference version of OpenCOBOL and a version heavily modified by BCS. Wherever the term "OpenCOBOL" is used, it means the reference version of OpenCOBOL. Otherwise a term such as "BCS-modified OpenCOBOL" will be used.

3.1 OpenCOBOL COMPILER - REFERENCE VERSION

The reference version of the COBOL compiler is: OpenCOBOL 1.1 downloaded from www.opencobol.org.

The version signature is:

[root@prague open-cobol-1.1-ref]# cobc --version
cobc (OpenCOBOL) 1.1.0
Copyright (C) 2001-2009 Keisuke Nishida / Roger While
Built    Jul 31 2012 10:30:25
Packaged Feb 06 2009 10:30:55 CET

It was remade to use vbisam. No files (including fileio.c & cobio.c) were edited.

The operating system is:

LINUX 2.6.18-8.el5 #1 SMP Fri Jan 26 14:15:21 EST 2007 GNU/Linux
Both the 32-bit and 64-bit versions are being used. This LINUX installation was drawn from a Red Hat Enterprise LINUX 5 distribution.

Although OpenCOBOL was configured to be compatible with MicroFocus, it might be possible to detour some of the issues reported below by varying the configuration options used by OpenCOBOL.

The OpenCOBOL ./configure reports:


OpenCOBOL Configuration:

  CC                   gcc
  COB_CC               gcc
  CFLAGS                -O2 -march=i686 -mtune=pentium4 -finline-functions -fsigned-char -Wall -Wwrite-strings -Wmissing-prototypes -Wno-format-y2k
  COB_CFLAGS           -I/usr/local/bin/open-cobol-ref/include -I/usr/src/bawtry/util/c  
  COB_EXTRA_FLAGS      -march=i686 -mtune=pentium4
  LDFLAGS              -L/usr/local/lib -L/bawtry/cobol/open-cobol-1.1-ref/libcob/.libs
  COB_LDFLAGS          -L/usr/local/lib -L/bawtry/cobol/open-cobol-1.1-ref/libcob/.libs
  COB_LIBS             -L/usr/local/lib -L/bawtry/cobol/open-cobol-1.1-ref/libcob/.libs -L/usr/lib -lcob -lm -lvbisam -lgmp -lncurses
  COB_CONFIG_DIR       ${prefix}/share/open-cobol/config
  COB_COPY_DIR         ${prefix}/share/open-cobol/copy
  COB_LIBRARY_PATH     /usr/lib/open-cobol
  COB_MODULE_EXT       so
  COB_SHARED_OPT       -shared
  COB_PIC_FLAGS        -fPIC -DPIC
  COB_EXPORT_DYN       -Wl,--export-dynamic
  COB_STRIP_CMD        strip --strip-unneeded
  Dynamic loading      System

  Use gettext for international messages:      yes
  Use VBISAM for file I/O                      yes
  Use fcntl for file locking:                  yes
  Use ncurses/pdcurses/curses for screen I/O:  yes

3.2 OpenCOBOL COMPILER - BCS-MODIFIED VERSION

The BCS-modified OpenCOBOL compiler uses a rewritten version of cobio.c, a heavily modified version of fileio.c and a tweaked typeck.c and parser.y. The major changes are noted later in this report.

4. ISSUES REMEDIED BY EDITING COBOL SOURCE

4.1 MISSING FULL-STOPS (PERIODS)

OpenCOBOL is sensitive to missing full-stops.

COBOL source program 4.1

OpenCOBOL detects syntax error and immediately aborts the compilation. This has the unfortunate consequence that each compilation will detect at most a single missing "." :

report-4-1.CBL:26: Error: syntax error, unexpected "Literal", expecting EXTERNAL or GLOBAL
... excution aborted [1]
Cobol compilation erc=256

Micro Focus compiles clean:


* Micro Focus COBOL/2                v1.1 revision 000 61-???-11 09:49 Page   1
*                                    report-4-1.CBL
* Micro Focus COBOL/2                v1.1 revision 000 Compiler
* Copyright (c) 1984, 1987 Micro Focus Ltd.    URN AXUGG/AA0/00078L
*                                              REF GNB-100047046A4
*
* Total Messages:     0
* Data:         656     Code:          28     Dictionary:         237

4.2 SWITCHES NUMBERED FROM 1

OpenCOBOL numbers switches from 1. Switch 0 is illegal.

COBOL source program 4.2

OpenCOBOL generates syntax error:

report-4-2.CBL:16: Error: Unknown system-name 'switch-0'
report-4-2.CBL: In paragraph 'a01-000':
report-4-2.CBL:29: Error: 'trace' undefined
... excution aborted [1]
� Cobol compilation erc=256

Micro Focus compiles clean:

* Micro Focus COBOL/2                v1.1 revision 000 61-???-11 10:06 Page   1
*                                    report-4-2.CBL
* Micro Focus COBOL/2                v1.1 revision 000 Compiler
* Copyright (c) 1984, 1987 Micro Focus Ltd.    URN AXUGG/AA0/00078L
*                                              REF GNB-100047046A4
*
* Total Messages:     0
* Data:         648     Code:          48     Dictionary:         173

4.3 IMPLIED STATEMENT END

Micro Focus implies END-PERFORM END-IF etc if statement is terminated with a full-stop. OpenCOBOL generates a syntax error unless the END clause is explicitly declared when required.

COBOL source program 4.3

OpenCOBOL generates syntax error:

report-4-3.CBL: In paragraph 'a01-000':
report-4-3.CBL:33: Error: PERFORM statement not terminated by END-PERFORM
report-4-3.CBL:44: Error: PERFORM statement not terminated by END-PERFORM
... excution aborted [1]
� Cobol compilation erc=256

Micro Focus compiles clean:

* Micro Focus COBOL/2                v1.1 revision 000 61-???-11 10:26 Page   1
*                                    report-4-3.CBL
* Micro Focus COBOL/2                v1.1 revision 000 Compiler
* Copyright (c) 1984, 1987 Micro Focus Ltd.    URN AXUGG/AA0/00078L
*                                              REF GNB-100047046A4
*
* Total Messages:     0
* Data:         660     Code:         202     Dictionary:         164

4.4 REDEFINES SHOULD PRECEDE PIC CLAUSE

OpenCOBOL generates a WARNING if PIC clause precedes REDEFINES clause.

COBOL source program 4.4

OpenCOBOL generates warning at compile time:

preprocessing report-4-4.CBL into report-4-4.i
report-4-4.CBL:27: Warning: REDEFINES clause should follow entry-name

4.5 DELETE FILE NOT IMPLEMENTED

OpenCOBOL generates a WARNING if DELETE FILE statement used. This is documented as a (widely used) MF extension.

COBOL source program 4.5

OpenCOBOL generates syntax error:

report-4-5.CBL: In paragraph 'a01-000':
report-4-5.CBL:40: Error: syntax error, unexpected "FILE", expecting "Identifier"
... excution aborted [1]
� Cobol compilation erc=256

5. ISSUES REQUIRING CHANGES TO OpenCOBOL COMPILER

5.1 HANDLING NUMERIC FIELDS INITIALISED AT GROUP LEVEL

When a numeric field is initialised to nulls, Micro Focus performs arithmetic and comparisons as if the ZONE and SIGN of the field had been correctly initialised.

OpenCOBOL produces different results; in particular it will throw an exception if arithmetic is attempted on a field initialised this way.

In production code, large structures (i.e. COBOL GROUP-level fields) are conveniently initialised with the a single move such as: MOVE ALL x"00" TO 101-PAYROLL-TOTALS. This will fail in OpenCOBOL.

COBOL source program 5.1

Micro Focus produces this:

... move all x"00" to group with unsigned fields
... test is-numeric:
... 1-n-1 pic 9(6) is not numeric
... 1-n-2 pic 9(6) comp is numeric
... 1-n-3 pic 9(6) comp-3 is not numeric

... move all x"00" to group with signed fields
... test is-numeric:
... 2-n-1 pic s9(6) is not numeric
... 2-n-2 pic s9(6) comp is numeric
... 2-n-3 pic s9(6) comp-3 is not numeric

... move all x"00" to group with unsigned fields
... test equal-to-zero:
... 1-n-1 pic 9(6) is ZERO
... 1-n-2 pic 9(6) comp is ZERO
... 1-n-3 pic 9(6) comp-3 is ZERO

... move all x"00" to group with signed fields
... test equal-to-zero:
... 2-n-1 pic s9(6) is ZERO
... 2-n-2 pic s9(6) comp is ZERO
... 2-n-3 pic s9(6) comp-3 is ZERO

... move all x"00" to group with unsigned fields
... test basic arithmetic 7 + field:
... 9(6): 000007+
... 9(6) comp: 000007+
... 9(6) comp-3: 000007+

... move all x"00" to group with signed fields
... test basic arithmetic 7 + field:
... s9(6): 000007+
... s9(6) comp: 000007+
... s9(6) comp-3: 000007+
... end-of-test

OpenCOBOL (without -std=mf) produces this:

[root@prague cobol]# cobcrun test-5-1

... move all x"00" to group with unsigned fields
... test is-numeric:
... 1-n-1 pic 9(6) is not numeric
... 1-n-2 pic 9(6) comp is numeric
... 1-n-3 pic 9(6) comp-3 is not numeric

... move all x"00" to group with signed fields
... test is-numeric:
... 2-n-1 pic s9(6) is not numeric
... 2-n-2 pic s9(6) comp is numeric
... 2-n-3 pic s9(6) comp-3 is not numeric

... move all x"00" to group with unsigned fields
... test equal-to-zero:
... 1-n-1 pic 9(6) is not ZERO
... 1-n-2 pic 9(6) comp is ZERO
... 1-n-3 pic 9(6) comp-3 is ZERO

... move all x"00" to group with signed fields
... test equal-to-zero:
... 2-n-1 pic s9(6) is not ZERO
... 2-n-2 pic s9(6) comp is ZERO
... 2-n-3 pic s9(6) comp-3 is ZERO

... move all x"00" to group with unsigned fields
... test basic arithmetic 7 + field:
... 9(6): +000000
... 9(6) comp: +000007
... 9(6) comp-3: +000007

... move all x"00" to group with signed fields
... test basic arithmetic 7 + field:
... s9(6): +000007
... s9(6) comp: +000007
... s9(6) comp-3: +000007
... end-of-test

OpenCOBOL (with -std=mf) produces this:

[root@prague cobol]# cobcrun test-5-1

... move all x"00" to group with unsigned fields
... test is-numeric:
... 1-n-1 pic 9(6) is not numeric
... 1-n-2 pic 9(6) comp is numeric
... 1-n-3 pic 9(6) comp-3 is not numeric

... move all x"00" to group with signed fields
... test is-numeric:
... 2-n-1 pic s9(6) is not numeric
... 2-n-2 pic s9(6) comp is numeric
... 2-n-3 pic s9(6) comp-3 is not numeric

... move all x"00" to group with unsigned fields
... test equal-to-zero:
... 1-n-1 pic 9(6) is not ZERO
... 1-n-2 pic 9(6) comp is ZERO
... 1-n-3 pic 9(6) comp-3 is ZERO

... move all x"00" to group with signed fields
... test equal-to-zero:
... 2-n-1 pic s9(6) is not ZERO
... 2-n-2 pic s9(6) comp is ZERO
... 2-n-3 pic s9(6) comp-3 is ZERO

... move all x"00" to group with unsigned fields
... test basic arithmetic 7 + field:
... 9(6): 633975+
... 9(6) comp: 000007+
... 9(6) comp-3: 000007+

... move all x"00" to group with signed fields
... test basic arithmetic 7 + field:
... s9(6): 333143+
... s9(6) comp: 000007+
... s9(6) comp-3: 000007+
... end-of-test

BCS-modified OpenCOBOL produces this:

... move all x"00" to group with unsigned fields
... test is-numeric:
... 1-n-1 pic 9(6) is numeric
... 1-n-2 pic 9(6) comp is numeric
... 1-n-3 pic 9(6) comp-3 is numeric

... move all x"00" to group with signed fields
... test is-numeric:
... 2-n-1 pic s9(6) is numeric
... 2-n-2 pic s9(6) comp is numeric
... 2-n-3 pic s9(6) comp-3 is numeric

... move all x"00" to group with unsigned fields
... test equal-to-zero:
... 1-n-1 pic 9(6) is ZERO
... 1-n-2 pic 9(6) comp is ZERO
... 1-n-3 pic 9(6) comp-3 is ZERO

... move all x"00" to group with signed fields
... test equal-to-zero:
... 2-n-1 pic s9(6) is ZERO
... 2-n-2 pic s9(6) comp is ZERO
... 2-n-3 pic s9(6) comp-3 is ZERO

... move all x"00" to group with unsigned fields
... test basic arithmetic 7 + field:
... 9(6): 000007+
... 9(6) comp: 000007+
... 9(6) comp-3: 000007+

... move all x"00" to group with signed fields
... test basic arithmetic 7 + field:
... s9(6): 000007+
... s9(6) comp: 000007+
... s9(6) comp-3: 000007+
... end-of-test

5.2 ISAM KEY DECLARATIONS IN COBOL SOURCE MUST EXACTLY MATCH KEYS FOUND IN INDEX

OpenCOBOL is inflexible when processing the declaration of keys used on an ISAM dataset.

Suppose a file is indexed by a primary-key and n alternate keys. A program is written that requires to read the file by primary-key alone. OpenCOBOL will clean compile the source but fail when the program is run. The file SELECT declaration must declare every key (used to create the orginal ISAM index) and in the exact same order. For production programming this seems undesirable and unnecessary. The BCS-modified OpenCOBOL supports flexible declaration of ISAM keys.

NOTE: this is certainly true when using VBISAM for OpenCOBOL ISAM support. I don't believe a similar restriction applies when using Berkeley-DB - but I have not yet tested this. (Which - if true - confirms that this restriction is a side-effect of the implementation unspecified at COBOL source level.)

Program 5.2 demonstrates the problem in its simplest form. It creates an indexed file with a primary and 2 alternate keys. 3 records are written to the file. The file is closed. The file is reopened and read using the same COBOL FILE and then closed. The file is reopened and read using the second COBOL FILE which uses identical keys to the first, but the alternate keys are in a different order. The file is reopened and read using the third COBOL FILE which declares only the primary-key. The file is reopened and read using the fourth COBOL FILE which omits one of the alternate keys from its declaration.

COBOL source program 5.2

Micro Focus produces this:

Demonstrates OpenCOBOL's adherence to rigid
presence and ordering of ISAM keys.
(May not apply to Berkeley DB.)
... creating /tmp/isam-file-05 - 3 keys indexed
opened file OK
... closing /tmp/isam-file-05

... reading /tmp/isam-file-05 - FD declaring same keys used to create it
...  record: keys :: A, AA, AAA : rec: 1    
...  record: keys :: B, BB, BBB : rec: 2    
...  record: keys :: C, CC, CCC : rec: 3    
... finished reading: status=10

... reading /tmp/isam-file-05 - FD declaring keys key-1 -3 -2
...  record: keys :: A, AA, AAA : rec: 1    
...  record: keys :: B, BB, BBB : rec: 2    
...  record: keys :: C, CC, CCC : rec: 3    
... finished reading: status=10

... reading /tmp/isam-file-05 - FD declaring keys key-1 only
...  record: keys :: A, AA, AAA : rec: 1    
...  record: keys :: B, BB, BBB : rec: 2    
...  record: keys :: C, CC, CCC : rec: 3    
... finished reading: status=10

... reading /tmp/isam-file-05 - FD declaring keys key-1 -3
...  record: keys :: A, AA, AAA : rec: 1    
...  record: keys :: B, BB, BBB : rec: 2    
...  record: keys :: C, CC, CCC : rec: 3    
... finished reading: status=10

OpenCOBOL produces this:

[root@prague cobol]# cobcrun isam_05
Demonstrates OpenCOBOL's adherence to rigid
presence and ordering of ISAM keys.
(May not apply to Berkeley DB.)
... creating /tmp/isam-file-05 - 3 keys indexed
opened file OK
... closing /tmp/isam-file-05

... reading /tmp/isam-file-05 - FD declaring same keys used to create it
...  record: keys :: A, AA, AAA : rec: 1
...  record: keys :: B, BB, BBB : rec: 2
...  record: keys :: C, CC, CCC : rec: 3
... finished reading: status=10

... reading /tmp/isam-file-05 - FD declaring keys key-1 -3 -2
!!! failed to open file2: status=39

... reading /tmp/isam-file-05 - FD declaring keys key-1 only
!!! failed to open file3: status=39

... reading /tmp/isam-file-05 - FD declaring keys key-1 -3
!!! failed to open file4: status=39

5.3 ISAM KEY DECLARATION DOES NOT SUPPORT SPLIT-KEYS.

OpenCOBOL has not (yet) implemented split-keys. Split-keys are essential to many applications. Methods for detouring split-keys can proof expensive to implement and error-prone. MicroFocus COBOL and the BCS-modified OpenCOBOL support split-keys.

COBOL source program 5.3

Micro Focus produces this:

... creating /tmp/isam-file-07 - SPLIT KEYS
... file /tmp/isam-file-07 created
... reading /tmp/isam-file-07 - SPLIT KEYS
... read all records using file1-key-1
... sequential read next ref file1-key-1 OK: 0 :: Add444033
... sequential read next ref file1-key-1 OK: 1 :: Baa333102
... sequential read next ref file1-key-1 OK: 2 :: Cbb222211
... sequential read next ref file1-key-1 OK: 3 :: Dcc111320
... read all records using file1-key-2
... sequential read next ref file1-key-2 OK: 0 :: Baa333102
... sequential read next ref file1-key-2 OK: 1 :: Cbb222211
... sequential read next ref file1-key-2 OK: 2 :: Dcc111320
... sequential read next ref file1-key-2 OK: 3 :: Add444033
... read all records using file1-key-3
... sequential read next ref file1-key-3 OK: 0 :: Dcc111320
... sequential read next ref file1-key-3 OK: 1 :: Cbb222211
... sequential read next ref file1-key-3 OK: 2 :: Baa333102
... sequential read next ref file1-key-3 OK: 3 :: Add444033
... read record #2 using START/READ file1-key-3
... start file1-key-3 = 333 + aa
... start + read next ref file1-key-3 OK: 2 :: Baa333102
... read record #2 using READ KEY file1-key-2
... read KEY file1-key-2 = cc + 111
... read key file1-key-2 OK: 2 :: Dcc111320

OpenCOBOL produces this:

[root@prague cobol]# cobc isam_07.cbl
isam_07.cbl:28: Warning: 'SPLIT KEYS' not implemented
isam_07.cbl:29: Warning: 'SPLIT KEYS' not implemented
isam_07.cbl:26: Error: 'file1-key-2' undefined
isam_07.cbl:28: Error: 'file1-key-3' undefined
isam_07.cbl: In paragraph 'a12-300-read-sequential':
isam_07.cbl:148: Error: 'file1-key-2' undefined
isam_07.cbl: In paragraph 'a12-400-read-sequential':
isam_07.cbl:161: Error: 'file1-key-3' undefined
isam_07.cbl: In paragraph 'a12-700-read-random':
isam_07.cbl:175: Error: 'file1-key-3' undefined
isam_07.cbl:177: Error: 'file1-key-3' undefined
isam_07.cbl: In paragraph 'a12-800-read-random':
isam_07.cbl:197: Error: 'file1-key-2' undefined
isam_07.cbl:199: Error: 'file1-key-2' undefined

BCS-modified OpenCOBOL produces this:

[root@lima cobol]# bcs_cobrun test-5-3
... creating /tmp/isam-file-07 - SPLIT KEYS
... file /tmp/isam-file-07 created
... reading /tmp/isam-file-07 - SPLIT KEYS
... read all records using file1-key-1
... sequential read next ref file1-key-1 OK: 0 :: Add444033
... sequential read next ref file1-key-1 OK: 1 :: Baa333102
... sequential read next ref file1-key-1 OK: 2 :: Cbb222211
... sequential read next ref file1-key-1 OK: 3 :: Dcc111320
... read all records using file1-key-2
... sequential read next ref file1-key-2 OK: 0 :: Baa333102
... sequential read next ref file1-key-2 OK: 1 :: Cbb222211
... sequential read next ref file1-key-2 OK: 2 :: Dcc111320
... sequential read next ref file1-key-2 OK: 3 :: Add444033
... read all records using file1-key-3
... sequential read next ref file1-key-3 OK: 0 :: Dcc111320
... sequential read next ref file1-key-3 OK: 1 :: Cbb222211
... sequential read next ref file1-key-3 OK: 2 :: Baa333102
... sequential read next ref file1-key-3 OK: 3 :: Add444033
... read record #2 using START/READ file1-key-3
... start file1-key-3 = 333 + aa
... start + read next ref file1-key-3 OK: 2 :: Baa333102
... read record #2 using READ KEY file1-key-2
... read KEY file1-key-2 = cc + 111
... read key file1-key-2 OK: 2 :: Dcc111320

5.4 OPENCOBOL IO DOESN'T SUPPORT PIPES.

OpenCOBOL has not (yet) implemented (linux-style) pipes.

The BCS-modified OpenCOBOL supports input and output pipes (but not bi-directional pipes).

COBOL source program 5.4

OpenCOBOL produces this:

[root@prague cobol]# cobcrun test-5-4
... opening pipe  "> /usr/bin/tr 'ABCD' '1234'                                                                         " ...
!!! failed to open pipe: status=30

BCS-modified OpenCOBOL produces this:

[root@lima cobol]# bcs_cobrun test-5-4
... opening pipe "> /usr/bin/tr 'ABCD' '1234'                                                                         " ...
opened pipe OK
... writing pipe ...
write pipe OK
write pipe OK
write pipe OK
write pipe OK
... closing pipe
1 this is line one.
2 this is line two.
3 this is line three.
4 this is the last line.
closed pipe OK
... opening pipe "< /usr/bin/tail /var/log/messages                                                                   " ...
opened pipe OK
... reading pipe ...
next line: Aug  2 14:59:43 lima last message repeated 27 times
next line: Aug  2 15:02:36 lima last message repeated 9 times
next line: Aug  2 15:09:17 lima last message repeated 9 times
next line: Aug  2 15:10:43 lima last message repeated 23 times
next line: Aug  2 15:11:41 lima ntpd[2102]: synchronized to 212.59.0.1, stratum 2 
next line: Aug  2 15:13:01 lima avahi-daemon[2230]: Invalid query packet.
next line: Aug  2 15:13:54 lima last message repeated 21 times
next line: Aug  2 15:16:36 lima last message repeated 9 times
next line: Aug  2 15:21:06 lima last message repeated 18 times
next line: Aug  2 15:23:32 lima last message repeated 20 times
closed pipe OK

5.5 OPENCOBOL HANDLING OF NUMERIC FIELDS.

When a numeric field is initialised (at group level) with spaces, OpenCOBOL behaves slightly differently to MicroFocus COBOL when (illegal) processing occurs. This is very similar to item 5.1. MF COBOL appears to ignore the zone of each byte in the numeric field, working only with the digit part.

Why is this a problem - why put spaces in a numeric field? Consider a form-handling program, receiving input-data like:

      1  1000-form-data.
         2           1000-partno pic x(18).
         2           1000-qty-x.
          3          1000-qty pic 9(6).

Code processing the quantity field should read something like this:

      inspect 1000-qty-x replacing leading spaces by zero.
      if 1000-qty-x not numeric
         perform y80-illegal-qty
         go to d01-exit.
      add 1000-qty to w-total-qty.

However if the algorithm ignores lines with zero quantity, it is tempting to code:

      if (1000-qty = 0) go to d01-exit.
      ... carry on to process 1000-qty

MicroFocus COBOL will jump to d01-exit. OpenCOBOL does not and gives dubious values in the ensuing processing.

COBOL source program 5.5

Micro Focus produces this:

... numeric edited field: z(5)9
... 1-n-e [      ] is not numeric
... 1-n-e [      ] = SPACES
... 1-n-e [      ] not = 000000

... numeric field: 9(6)
... 1-n-n [      ] is not numeric
... 1-n-n [      ] = SPACES
... 1-n-n [      ] = 000000
... 1-n-n [      ] + 1 = 000001

Downstream consequences of numeric field containing some spaces.
... MOVE to field of same length and sign is optimised by OpenCOBOL to memcpy().
    This transfers the spaces to target field.
    1-n-n [      ] -> 000000
... MOVE to field of different length is assigned to numeric functions by OpenCOBOL.
    This strips the spaces to get 'right' result in target field.
    1-n-n [      ] -> 0000000000

OpenCOBOL produces similar results - except when the arithmetic is performed on the field. The result is different (but wrong!) whether or not the source is compiled with -std=mf.

OpenCOBOL (without -std=mf) produces this:

[root@prague cobol]# cobc  test-5-5.cbl
[root@prague cobol]# cobcrun test-5-5

... numeric edited field: z(5)9
... 1-n-e [      ] is not numeric
... 1-n-e [      ] = SPACES
... 1-n-e [      ] not = 000000

... numeric field: 9(6)
... 1-n-n [      ] is not numeric
... 1-n-n [      ] = SPACES
... 1-n-n [      ] not = 000000
... 1-n-n [      ] + 1 = 000000

Downstream consequences of numeric field containing some spaces.
... MOVE to field of same length and sign is optimised by OpenCOBOL to memcpy().
    This transfers the spaces to target field.
    1-n-n [      ] ->       
... MOVE to field of different length is assigned to numeric functions by OpenCOBOL.
    This strips the spaces to get 'right' result in target field.
    1-n-n [      ] -> 0000000000

OpenCOBOL (with -std=mf) produces this:

[root@prague cobol]# cobc -std=mf test-5-5.cbl
[root@prague cobol]# cobcrun test-5-5

... numeric edited field: z(5)9
... 1-n-e [      ] is not numeric
... 1-n-e [      ] = SPACES
... 1-n-e [      ] not = 000000

... numeric field: 9(6)
... 1-n-n [      ] is not numeric
... 1-n-n [      ] = SPACES
... 1-n-n [      ] not = 000000
... 1-n-n [      ] + 1 = 189521

Downstream consequences of numeric field containing some spaces.
... MOVE to field of same length and sign is optimised by OpenCOBOL to memcpy().
    This transfers the spaces to target field.
    1-n-n [      ] ->       
... MOVE to field of different length is assigned to numeric functions by OpenCOBOL.
    This strips the spaces to get 'right' result in target field.
    1-n-n [      ] -> 0000000000

BCS-modified OpenCOBOL produces this:

[root@lima cobol]# bcs_cobrun test-5-5

... numeric edited field: z(5)9
... 1-n-e [      ] is not numeric
... 1-n-e [      ] = SPACES
... 1-n-e [      ] not = 000000

... numeric field: 9(6)
... 1-n-n [      ] is not numeric
... 1-n-n [      ] = SPACES
... 1-n-n [      ] = 000000
... 1-n-n [      ] + 1 = 000001

Downstream consequences of numeric field containing some spaces.
... MOVE to field of same length and sign is optimised by OpenCOBOL to memcpy().
    This transfers the spaces to target field.
    1-n-n [      ] -> 000000
... MOVE to field of different length is assigned to numeric functions by OpenCOBOL.
    This strips the spaces to get 'right' result in target field.
    1-n-n [      ] -> 0000000000