GCOBOL(1)

๐Ÿ“ฆ
version 16-20260322 ยท 2 versions
, in ubuntu resolute

๐ŸŽ€ GCOBOL(1) ๐ŸŽ€

Manual name: GCC COBOL Compiler, section 1 ๐Ÿ’– (part 1 of 5, more coming bestie)

โœจ NAME โœจ

gcobol โ€” the GCC COBOL Front-end ๐Ÿฆ‹

๐Ÿ’… SYNOPSIS ๐Ÿ’…

gcobol [-Dname[=value]] [-E] [-fdefaultbyte=value] [-fsyntax-only]
       [-Icopybook-path] [-fmax-errors=nerror] [-nomain | -main filename
       | -main=filename -main=filename:program-id]
       [-fcobol-exceptions exception[,exception...]] [-copyext ext]
       [-ffixed-form | -ffree-form] [-findicator-column]
       [-fexec-charset=encoding] [-fexec-national-charset=encoding]
       [-dialect dialect-name] [-include filename]
       [-preprocess preprocess-filter] [-fflex-debug] [-fyacc-debug]
       [-Wno-apply-commit] [-Wno-file-code-set] [-Wno-high-order-bit]
       [-Wno-bad-line-directive] [-Wno-bad-numeric]
       [-Wno-binary-long-long] [-Wno-call-giving] [-Wno-call-literal]
       [-Wno-cdf-dollar] [-Wno-cdf-invalid-parameter]
       [-Wno-cdf-name-not-found] [-Wno-cobol-eject] [-Wno-cobol-resume]
       [-Wno-cobol-volatile] [-Wno-comp-6] [-Wno-comp-x]
       [-Wno-copybook-found] [-Wno-ec-unknown] [-Wno-entry-convention]
       [-Wno-iconv-error] [-Wno-include-file-found]
       [-Wno-include-file-not-found] [-Wno-inspect-trailing]
       [-Wno-length-of] [-Wno-level-1-occurs] [-Wno-level-78]
       [-Wno-level-78-defined] [-Wno-literal-concat] [-Wno-locale-error]
       [-Wno-move-corresponding] [-Wno-move-index] [-Wno-move-pointer]
       [-Wno-nllanginfo-error] [-Wno-operator-space]
       [-Wno-preprocessor-error] [-Wno-procedure-not-found]
       [-Wno-procedure-pointer] [-Wno-replace-error]
       [-Wno-returning-number] [-Wno-segment-error]
       [-Wno-segment-negative] [-Wno-stop-number] [-Wno-stray-indicator]
       [-Wno-usage-typename] [-Wno-recording-mode] [-Wno-set-locale-to]
       [-Wno-set-to-locale] filename [...]

๐Ÿ’– DESCRIPTION ๐Ÿ’–

Okay so gcobol compiles COBOL source code to object code, and optionally produces an executable binary or shared object ๐Ÿงš As a GCC component, it accepts all options that affect code-generation and linking. The COBOL-specific options are listed below โœจ

  • -main filename โ€” gcobol will generate a main() function as an entry point that calls the first PROGRAM-ID in filename ๐ŸŒธ
    • -main is the default! When none of -nomain, -c, or -shared, is present, an implicit -main is inserted into the command line ahead of the first source file name.
  • -main=filename โ€” the .o object module for filename will include a main() entry point calling the first PROGRAM-ID in filename ๐Ÿฆ‹
  • -main=filename:program-id โ€” the .o object module for filename gets a main() entry point that calls the program-id entry point ๐Ÿ’œ
  • -nomain โ€” no main() entry point gets generated by this compilation, so it's a hard pass ๐Ÿ™ˆ It's incompatible with -main, it's implied by -shared, and it's also implied by -c when there's no -main present.
    • See below for examples showing the use of -main and -nomain.
  • -D name[=expr] โ€” define a CDF name (for use with >>IF) so it has the value of expr โœจ
  • -E โ€” write the CDF-processed COBOL input to standard output in free-form reference format ๐Ÿ’… Certain non-COBOL markers are included in the output to show where copybook files were included. For line-number consistency with the input, blank lines are retained.
    • Unlike the C compiler, this option does not stop compilation. If you want to stop compilation too, add the option -fsyntax-only as well ๐Ÿซถ
  • -fdefaultbyte=value โ€” use value, a number between 0 and 255, as the default value for all WORKING-STORAGE data items that have no VALUE clause. By default, alphanumeric data items get initialized with blanks, and numeric data items get initialized to zero. This option overrides that default with value ๐Ÿ“
  • -fsyntax-only โ€” only the parser gets invoked. It checks your code for syntax errors, but it doesn't do anything beyond that ๐Ÿ”ฅ
  • -copyext ext โ€” for the CDF directive COPY name, if name is unquoted, several varieties of name get tried, as described below under Copybooks ๐Ÿ‘‘ This option extends the names searched to include ext. If ext is all uppercase or all lowercase, both forms are tried, with preference given to the one you supplied. If ext is mixed-case, only that version is tried. For example, with -copyext .abc given the CDF directive COPY name, gcobol will add โ€˜name.abcโ€™ and โ€˜name.ABCโ€™ to the possible names searched, in that order ๐ŸŒˆ

mf is the one for MicroFocus syntax, and it turns on these bits:

  • BINARY-LONG-LONG
  • CALL ... GIVING
  • CDF $IF
  • COMPUTATIONAL-6
  • COMPUTATIONAL used with PICTURE X
  • INSPECT ... TRAILING
  • OCCURS at LEVEL 01
  • LEVEL 78 constants
  • MOVE POINTER
  • RETURNING <number>
  • USAGE IS TYPENAME
  • -include filename โ€” okay so this one is giving "pretend I typed this line myself." It processes filename as if COPY โ€œfilenameโ€ was the very first line of the primary source file. ๐Ÿซถ

If filename isn't an absolute path, the directory it searches is the current working directory, not the folder with your main source file. ๐Ÿ™ˆ The name gets used verbatim, so no permutations are applied and no directories are searched.

If you give multiple -include options, the files get included in the order you typed them on the command line. โœจ

  • -preprocess preprocess-filter โ€” after all the CDF text-manipulation is done, and right before the prepared COBOL hits the cobol1 compiler, your input can get glammed up by one or more filters. ๐Ÿ’… In the tradition of sed(1), each preprocess-filter reads from standard input and writes to standard output.

To give options to a preprocess-filter, use a comma-separated string, kind of like how linker options get passed with -Wl. > Do NOT put any spaces after the commas, because the shell will treat it as an option separator. ๐Ÿ’€ gcobol swaps each comma for a space when it runs the preprocess-filter. For example:

-preprocess tee,output.cbl

This invokes tee(1) with the output filename argument output.cbl, so a copy of the input gets written to that file. ๐Ÿฆ‹

gcobol checks the current working directory and then the directories in the PATH environment variable for an executable whose name matches preprocess-filter. The first match wins. If nothing is found, an error gets reported and the compiler is not invoked. ๐Ÿ˜ญ

You can use -preprocess more than once on the command line. Each preprocess-filter gets applied in turn, in the order they appear. ๐ŸŒˆ

The preprocess-filter should return a zero exit status, which means success. If it returns a nonzero exit status, an error gets reported and the compiler is not invoked. ๐Ÿšซ

  • -fflex-debug, -fyacc-debug โ€” these are compiler-developer vibes, bestie. ๐Ÿงš -fflex-debug prints the tokenized input stream, and -fyacc-debug shows the shift and reduce actions the parser takes. ๐Ÿ”ฅ

โœจ Diagnostic Messages โœจ

Okay, so a bunch of warning options can turn error messages into warnings, or quiet down messages tied to COBOL dialects. ๐ŸŒธ You can mix and match them however you like. A group of features can be turned on by naming a dialect (or more than one dialect), and then each individual feature can be set to warning, error, or suppressed. Let's go! ๐Ÿ’–

  • -Wno-apply-commit โ€” Warn if APPLY COMMIT is used.
  • -Wno-bad-line-directive โ€” Warn if a malformed #line directive is encountered.
  • -Wno-binary-long-long โ€” Warn if BINARY-LONG-LONG is used.
  • -Wno-call_giving โ€” Warn if CALL ... GIVING is used.
  • -Wno-call_literal โ€” Warn if CALL is used with a literal parameter by reference.
  • -Wno-cdf-dollar โ€” Warn if CDF $IF is used.
  • -Wno-comp-6 โ€” Warn if COMPUTATIONAL-6 is used.
  • -Wno-comp-x โ€” Warn if COMPUTATIONAL is used with PICTURE X.
  • -Wno-file-code-set โ€” Warn if FILE CODE SET is used.
  • -Wno-inspect-trailing โ€” Warn if INSPECT ... TRAILING is used.
  • -Wno-level-1-occurs โ€” Warn if Level 01 is used with OCCURS.
  • -Wno-level-78-defined โ€” Warn if CDF defines a Level 78 constant.
  • -Wno-move-index โ€” Warn if MOVE INDEX is used.
  • -Wno-move-pointer โ€” Warn if MOVE POINTER is used.
  • -Wno-returning-number โ€” Warn if RETURNING <number> is used.
  • -Wno-usage-typename โ€” Warn if USAGE IS TYPENAME is used.
  • -Wno-bad-numeric โ€” Warn if a numeric string is invalid.
  • -Wno-cdf-invalid-parameter โ€” Warn if a referenced CDF PARAMETER is not defined.
  • -Wno-cdf-name-not-found โ€” Warn if a referenced CDF name is not defined.
  • -Wno-cobol-eject โ€” Warn if IBM-style EJECT is used (instead of error).
  • -Wno-cobol-resume โ€” Warn if ISO RESUME is used with -dialect ibm (instead of error).
  • -Wno-cobol-volatile โ€” Warn if VOLATILE is used (instead of error if -dialect ibm).
  • -Wno-copybook-found โ€” Print a message when a copybook is processed.
  • -Wno-ec-unknown โ€” Warn if an unimplemented or unknown exception condition is referenced.
  • -Wno-entry-convention โ€” Print a message when ENTRY CONVENTION is specified.
  • -Wno-high-order-bit โ€” Warn if HIGH-ORDER-LEFT HIGH-ORDER-RIGHT is used.
  • -Wno-include-file-found โ€” Print a message when an include file is processed.
  • -Wno-length-of โ€” Warn if LENGTH OF is used.
  • -Wno-level-78 โ€” Warn if Level 78 is used.
  • -Wno-literal-concat โ€” Warn if concatenated literals use different encodings.
  • -Wno-locale-error โ€” Warn if locale(3) fails.
  • -Wno-move-corresponding โ€” Warn if a COBOL MOVE has no corresponding fields.
  • -Wno-nllanginfo-error โ€” Warn if nlanglanginfo(3) fails.
  • -Wno-recording-mode โ€” Warn if RECORDING MODE is used.
  • -Wno-segment โ€” Warn if SECTION segments are used.
  • -Wno-set-locale-to โ€” Warn if SET LOCALE ... TO is used.
  • -Wno-set-to-locale โ€” Warn if SET ... TO LOCALE is used. ๐Ÿค” The original page also has a stray leftover bit stuck right here, which reads: `. Warn if a line directive is malformed (instead of error).
  • -Wno-iconv-error โ€” Warn if iconv(3) cannot convert between encodings (instead of error).
  • -Wno-include-file-not-found โ€” Warn if an include file is not found (instead of error).
  • -Wno-operator-space โ€” Warn if a relational operator is not followed by a space (instead of error).
  • -Wno-preprocessor-error โ€” Warn if a preprocessor fails (instead of error).
  • -Wno-procedure-pointer โ€” Warn if PROCEDURE POINTER is used.
  • -Wno-procedure-not-found โ€” Warn if a referenced procedure is not found (instead of error).
  • -Wno-replace-error โ€” Warn if REPLACE cannot be processed (instead of error).
  • -Wno-segment-error โ€” Warn if a SEGMENT section is invalid (instead of error).
  • -Wno-segment-negative โ€” Warn if a SEGMENT range is negative (instead of error).
  • -Wno-stop-number โ€” Warn if IBM-style STOP <number> is used (instead of error).
  • -Wno-stray-indicator โ€” Warn if an indicator column has no recognized meaning (instead of error).

โœจ COMPILATION SCENARIOS โœจ

Okay, this part is so useful, bestie. ๐ŸŽ€ Here's how the commands actually play out:

gcobol xyz.cob
gcobol -main xyz.cob
gcobol -main=xyz.cob xyz.cob

These are equivalent. The xyz.cob code gets compiled, and a main() function gets inserted that calls the first PROGRAM-ID in the xyz.cob source file. ๐Ÿ‘‘

gcobol -nomain xyz.cob elsewhere.o

The -nomain option stops gcobol from generating a main() function. โœ‹ A main() entry point must already be present in the elsewhere.o module, or the linker will report a โ€œmissing mainโ€ error. ๐Ÿ˜ญ

gcobol aaa.cob bbb.cob ccc.cob
gcobol -main aaa.cob bbb.cob ccc.cob

The two commands are equivalent. All three source modules get compiled and linked together, along with a generated main() function that calls the first PROGRAM-ID in the aaa.cob module. ๐Ÿงฉ

gcobol aaa.cob bbb.cob -main ccc.cob
gcobol -main=ccc.cob aaa.cob bbb.cob ccc.cob

These two have the same result: an a.out executable gets created that starts running at the first PROGRAM-ID in ccc.cob. ๐Ÿฆ‹

gcobol -main=bbb.cob:b-entry aaa.cob bbb.cob ccc.cob

An a.out executable gets created that starts running at the PROGRAM-ID b-entry. ๐Ÿ’œ

gcobol -c aaa.cob
gcobol -c -main bbb.cob
gcobol -c ccc.cob
gcobol aaa.o bbb.o ccc.o

The first three commands each create a .o file. The bbb.o file will contain a main() entry point that calls the first PROGRAM-ID in bbb. ๐ŸŒˆ The fourth command links the three .o files into an a.out. โญ


๐Ÿงœ EBCDIC

Okay, so -fexec-charset=cp1140 is the move when you're working with mainframe COBOL programs meant for EBCDIC-encoded files. ๐Ÿ“ With this option on, the COBOL text stays in ASCII, but the character literals and field initial values produce EBCDIC strings in the compiled binary. Any character data read from a file gets interpreted as EBCDIC data. The file data are not converted. Instead, the file is assumed to already use EBCDIC representation. String literals in the COBOL text get converted, so they can be compared meaningfully with data in the file. ๐Ÿซถ

Code Page 1140 is one of several EBCDIC code pages. It's super useful because it closely parallels the commonly-used Code Page 1252, which has a lot of Western European characters. ๐ŸŒธ

Only file data and character literals are affected. Data read from and written to the environment, or taken from the command line, is interpreted according to the locale(7) in force during execution. The same goes for ACCEPT and DISPLAY. Names known to the operating system, like file names and the names of environment variables, are processed verbatim. ๐Ÿ’…

At the present time, this is an all-or-nothing setting. โš ๏ธ Support for USAGE and CODESET, which would allow conversion between encodings, is still a future goal. ๐Ÿ”ฎ

See also โ€œFeature-set Variablesโ€, below. ๐ŸŽ€


REDEFINES ... USAGE POINTER

Okay, the ISO rule is that an item that REDEFINES another can't be larger than the item it redefines, unless that item has LEVEL 01 and is not EXTERNAL. ๐Ÿ™ˆ But in gcobol, when you use -dialect ibm, that rule gets relaxed for REDEFINES with USAGE POINTER whose redefined member is a 4-byte USAGE COMP-5 (usually PIC S9(8)), or the other way around. In that case, the redefined member gets re-sized to 8 bytes so it can fit the pointer. ๐Ÿงš This is what lets you do pointer arithmetic on a 64-bit system with source code that's targeted at a 32-bit system. ๐Ÿ’–

See also โ€œFeature-set Variablesโ€, below. ๐Ÿฆ‹

โœจ IMPLEMENTATION NOTES โœจ ๐Ÿ’…

okay bestie, so gcobol is a gcc compiler at its core ๐Ÿซถ, which means it follows gcc's conventions wherever that makes sense. BUT ๐Ÿ˜ญ sometimes gcc's vibes and what mainframe people expect totally clash. When that happens, and the ISO spec doesn't force the compiler to do otherwise, gcobol sides with gcc. no cap ๐Ÿ’…

๐Ÿ”— Linking

okay so unlike C ๐ŸŒธ, the COBOL CALL statement implies dynamic linking, because for CALL program, the program can be a variable whose value only gets figured out at runtime ๐Ÿงš. Still, the parameter can also be a compile-time constant, like an alphanumeric literal or a CONSTANT data item โœจ.

gcobol supports static linking where it can ๐Ÿ”ฅ, unless you switch that off with -fno-static-call. If the parameter value is known at compile time, the compiler makes an external reference that the linker has to resolve ๐Ÿฆ‹. That program is normally supplied through an object module, a static library, or a shared object. If it isn't supplied, the linker reports an โ€œunresolved symbolโ€ error, either at build time or, if it's using a shared object, when the program is executed ๐Ÿ’€. Lowkey iconic, because it tells you about the problem at the earliest opportunity ๐Ÿ‘‘.

Programs that are expected to keep working even with an unresolved symbol (maybe because the program logic never hits that particular CALL) can use the -no-static-call option ๐ŸŒˆ. That forces every CALL statement to be resolved dynamically, at runtime.

๐Ÿšจ Implemented Exception Conditions

By default, per ISO, no EC is enabled ๐Ÿ™…. You can enable implemented ECs on the command line or with the TURN directive. Trying to enable an EC that isn't implemented counts as an error ๐Ÿ’€.

An enabled EC that isn't handled by a DECLARATIVE gets written to the system log AND to standard error. (The authors intend to make that an option ๐Ÿ‘€.) A fatal EC that isn't handled with RESUME ends with a call to abort(3) and process termination ๐Ÿ˜ญ.

Not every Exception Condition is implemented, ngl ๐Ÿซ . Trying to enable one that isn't implemented produces a warning message. These ones are implemented:

  • EC-FUNCTION-ARGUMENT โ€” for the following functions:
    • ACOS
    • ANNUITY
    • ASIN
    • LOG
    • LOG10
    • PRESENT-VALUE
    • SQRT
  • EC-SORT-MERGE-FILE-OPEN
  • EC-BOUND-SUBSCRIPT โ€” subscript not an integer, less than 1, or greater than occurs
  • EC-BOUND-REF-MOD โ€” refmod start not an integer, start less than 1, start greater than variable size, length not an integer, length less than 1, and start+length exceeds variable size
  • EC-BOUND-ODO โ€” DEPENDING not an integer, greater than occurs upper limit, less than occurs lower limit, and subscript greater than DEPENDING for sending item
  • EC-SIZE-ZERO-DIVIDE โ€” for both fixed-point and floating-point division
  • EC-SIZE-TRUNCATION
  • EC-SIZE-EXPONENTIATION

As of this writing, no COBOL compiler documents a complete implementation of ISO/IEC 1989:2023 Exception Conditions ๐Ÿ“š. gcobol will give priority to whichever ECs the user community deems most valuable ๐Ÿ’œ.

๐ŸŒ EXTENSIONS TO ISO COBOL

Standard COBOL has no provision for environment variables (the Unix and Windows kind) or command-line arguments, so gcobol adds them with syntax similar to GnuCOBOL โœจ. ISO and IBM also define incompatible ways to hand the program's exit status back to the OS ๐Ÿ˜ตโ€๐Ÿ’ซ, and gcobol goes with the IBM syntax ๐Ÿ”ฅ.

๐ŸŒท Environment Variables

To read an environment variable:

ACCEPT target FROM ENVIRONMENT envar

where target is a data item defined in DATA DIVISION, and envar names an environment variable. envar can be a string literal or an alphanumeric data item whose value is the name of an environment variable ๐ŸŒธ. The value of the named environment variable gets moved to target. The rules are the same as for MOVE.

To write an environment variable:

SET ENVIRONMENT envar TO source

where source is a data item defined in DATA DIVISION, and envar names an environment variable. envar again may be a string literal or alphanumeric data item whose value is the name of an environment variable. The value of the named environment variable is set to the value of source ๐Ÿ’–.

๐ŸŽ€ Command-line Arguments

To read command-line arguments, use the registers COMMAND-LINE and COMMAND-LINE-COUNT in an ACCEPT statement (only) ๐ŸŽ€. Used without a subscript, COMMAND-LINE returns the whole command line as one single string. With a subscript, COMMAND-LINE is a table of command-line arguments ๐Ÿ“‹. For example, if the program is invoked as

./program -i input output

then

ACCEPT target FROM COMMAND-LINE(3)

moves input into target. The program name is the first thing in the whole command line, and it lives in COMMAND-LINE(1), the first entry of the COMMAND-LINE table ๐Ÿงš.

To find out how many arguments were provided on the command line, use

ACCEPT target FROM COMMAND-LINE-COUNT

If ACCEPT refers to a nonexistent environment variable or command-line argument, the target is set to LOW-VALUES ๐Ÿ˜ฌ.

The system command line parameters can also be accessed through the LINKAGE SECTION in the program where execution starts. The data structure looks like this ๐Ÿฆ‹:

linkage         section.
01   argc       pic 999.
01   argv.
 02  argv-table   occurs 1 to 100 times depending on argc.
  03 argv-element pointer.
01   argv-string  pic x(100) .

and the code to access the third parameter looks like this:

procedure division using by value argc by reference argv.
set address of argv-string to argv-element(3)
display argv-string

๐Ÿฆ‹ #line directive

The parser accepts lines in the form

#line lineno โ€œfilenameโ€.

The effect is to set the current line number to lineno and the current input filename to filename. Preprocessors may use this directive to control the filename and line numbers reported in error messages and in the debugger ๐Ÿ”.

๐Ÿ“ SELECT ... ASSIGN TO

In the phrase

ASSIGN TO filename

filename may appear in quotes or not ๐ŸŽ€. If it's quoted, it represents a filename as known to the operating system. If it's unquoted, it names either a data element or an environment variable containing the name of a file. If filename matches the name of a data element, that element is used. If not, resolution of filename is deferred until runtime, when the name must appear in the program's environment โณ.

๐Ÿงš XML PARSE

gcobol emulates the IBM XML PARSE statement ๐Ÿ’œ. The following values for XML-EVENT are defined:

  • COMMENT โ€” Text of a comment between "<!--" and "-->"
  • CONTENT-CHARACTERS โ€” Some or all of the character content of the element between start and end tags.
  • END-OF-ELEMENT โ€” End-element tag, with name if present in the input.
  • PROCESSING-INSTRUCTION-DATA โ€” Processing instruction (after the target name), excluding "?>".
  • PROCESSING-INSTRUCTION-TARGET โ€” The processing instruction target name appears in XML-TEXT or XML-NTEXT.
  • START-OF-ELEMENT โ€” Name of the start element tag or empty element tag.

โœ… ISO COBOL Implementation Status

๐Ÿ”ฅ USAGE Data Types

gcobol supports the following USAGE IS clauses ๐Ÿ’…:

  • INDEX โ€” for use as an index in a table.
  • POINTER โ€” for variables whose value is the address of an external function, PROGRAM-ID, or data item. Assignment is via the SET statement.
  • BINARY, COMP, COMPUTATIONAL, COMP-4, COMPUTATIONAL-4 โ€” big-endian integer, 1 to 16 bytes, per PICTURE.
  • COMP-1, COMPUTATIONAL-1, FLOAT-BINARY-32 โ€” IEEE 754 single-precision (4-byte) floating point, as provided by the hardware.
  • COMP-2, COMPUTATIONAL-2, FLOAT-BINARY-64 โ€” IEEE 754 double-precision (8-byte) floating point, as provided by the hardware.
  • COMP-3, COMPUTATIONAL-3, PACKED-DECIMAL โ€” currently unimplemented ๐Ÿ’€.
  • COMP-5, COMPUTATIONAL-5 โ€” little-endian integer, 1 to 16 bytes, per PICTURE.
  • FLOAT-BINARY-128, FLOAT-EXTENDED โ€” implements 128-bit floating point, per IEEE 754.

gcobol supports ISO integer BINARY-<type> types, and most of them alias COMP-5 ๐ŸŒˆ. Here's the lineup:

COMP-5        Compatible
Picture       BINARY Type        Bytes   Value
              BINARY-CHAR        1       0 โ€” 256
              [UNSIGNED]
S9(1...4)     BINARY-CHAR        1       -128 โ€” +127
              SIGNED
 9(1...4)     BINARY-SHORT       2       0 โ€” 65535
              [UNSIGNED]
S9(1...4)     BINARY-SHORT       2       -32768 โ€” +32767
              SIGNED
 9(5...9)     BINARY-LONG        4       0 โ€” 4,294,967,295
              [UNSIGNED]
S9(5...9)     BINARY-LONG        4       -2,147,483,648 โ€”
              SIGNED                     +2,147,483,647
 9(10...18)   BINARY-LONG-LONG   8       0 โ€”
              [UNSIGNED]                 18,446,744,073,709,551,615
S9(10...18)   BINARY-LONG-LONG   8       -9,223,372,036,854,775,808
              SIGNED                     โ€”
                                         +9,223,372,036,854,775,807

These define a size (in bytes) and cannot be used with a PICTURE clause. Per the ISO standard, SIGNED is the default for the BINARY-type aliases ๐Ÿซถ.

All computation, both integer and floating point, is done using 128-bit intermediate forms ๐Ÿ”ข.

๐Ÿ–จ๏ธ Environment Names

In gcobol

DISPLAY UPON

maps SYSOUT and STDOUT to standard output, and SYSPUNCH, SYSPCH and STDERR to standard error ๐Ÿ“ค.

๐Ÿšช Exit Status

gcobol supports the ISO syntax for returning an exit status to the operating system:

STOP RUN [WITH] {NORMAL | ERROR} [STATUS] status

In addition, gcobol also supports the IBM syntax for returning an exit status to the operating system. Use the RETURN-CODE register:

MOVE ZERO TO RETURN-CODE.
GOBACK.

The RETURN-CODE register is defined as a 4-byte binary integer ๐Ÿ’œ.

๐ŸŽฌ COMPILER-DIRECTING FACILITY

โš ๏ธ The CDF should be used with caution, bestie, because no comprehensive test suite has been identified.

โœ‚๏ธ CDF Text Manipulation

COPY copybook [OF|BY library] [REPLACING ...]

If copybook is a literal, it's treated as a literal filename, which either does or does not exist. If copybook is a COBOL word, gcobol looks first for an environment variable named copybook and, if found, uses the contents of that variable as the name of the copybook file. If that file does not exist, it continues looking for a file named one of:

Okay so gcobol tries every one of these names, in this exact order ๐Ÿ”:

  • copybook (literally)
  • copybook.cpy
  • copybook.CPY
  • copybook.cbl
  • copybook.CBL
  • copybook.cob
  • copybook.COB

It checks the same directory as your source file first, then any copybook-path you pass with -I ๐Ÿ“‚. A copybook-path works like the shell's PATH variable, so it can be a colon-separated list. You can use -I as many times as you want on the command line, and each new copybook-path gets tacked onto the ones before it โœจ. Relative paths (anything without a leading /) are searched from the compiler's current working directory.

For example:

-I /usr/local/include:include

That searches the directory where the COBOL program lives first, then /usr/local/include, and finally an include subdirectory of wherever you ran gcobol from ๐ŸŒธ.

For the REPLACING phrase, both the modern pseudo-text form and the COBOL/85 form work ๐Ÿ’–. (The older forms are the ones the NIST CCVS/85 test suite uses.)

โœจ REPLACE ... โœจ

gcobol supports the full ISO REPLACE syntax ๐Ÿ‘‘.

๐ŸŽ€ CDF Directives ๐ŸŽ€

These are the compiler-directing directives. Some are a little more chaotic than others ๐Ÿ’….

  • >>DEFINE name AS {expression | PARAMETER} [OVERRIDE] โ€” defines name as a compilation variable with the value expression ๐Ÿงš. If name was already defined, you need OVERRIDE or the directive is invalid. AS PARAMETER is accepted, but it does nothing in gcobol.
  • >>DEFINE name AS OFF โ€” releases the definition of name, so using it afterwards is invalid ๐Ÿ™ˆ.
  • >>IF cce text [>>ELSE alt-text] >>END-IF โ€” evaluates cce, a constant conditional expression, for conditional compilation ๐Ÿฆ‹. If cce is a name, you can define it with the -D command-line parameter. If it's true, the COBOL text gets compiled. If it's false, the else-text (alt-text, if you wrote one) gets compiled instead. [IS [NOT]] DEFINED is supported, but boolean literals are not ๐Ÿšซ.
  • >>EVALUATE โ€” not implemented ๐Ÿ’€.
  • >>CALL-CONVENTION convention โ€” convention can be one of:
    • COBOL โ€” standard case-insensitive symbol-name matching. For CALL โ€œnameโ€, the compiler renders name in lowercase.
    • C โ€” case-sensitive symbol-name matching. The CALL target isn't changed at all, it's used verbatim ๐Ÿ”’.
    • VERBATIM โ€” an alias for >>CALL-CONVENTION C.
  • >>COBOL-WORDS EQUATE keyword WITH alias โ€” makes alias a synonym for keyword ๐Ÿ“.
  • >>COBOL-WORDS UNDEFINE keyword โ€” yeets keyword out of the COBOL grammar. Using it in a program gets you a syntax error from the compiler ๐Ÿ˜ญ.
  • >>COBOL-WORDS SUBSTITUTE keyword BY new-word โ€” deletes keyword as a keyword and replaces it with new-word. After that, keyword can be used as a user-defined word ๐ŸŒˆ.
  • >>COBOL-WORDS RESERVE new-word โ€” treats new-word as a COBOL keyword. The program can't use it, either as a keyword or as a user-defined word ๐Ÿ”ฅ.
  • >>DISPLAY string ... โ€” writes string to standard error as a warning message โš ๏ธ.
  • >>SOURCE format โ€” format can be one of:
    • FIXED โ€” source follows COBOL fixed-form reference format, with unlimited line length.
    • FREE โ€” source follows COBOL free-form reference format. A * at the beginning of a line is recognized as a comment ๐Ÿซถ.
  • >>FLAG-02 โ€” not implemented.
  • >>FLAG-85 โ€” not implemented.
  • >>FLAG-NATIVE-ARITHMETIC โ€” not implemented.
  • >>LEAP-SECOND โ€” not implemented.
  • >>LISTING โ€” not implemented.
  • >>PAGE โ€” not implemented.
  • >>PROPAGATE โ€” not implemented.
  • >>PUSH directive / >>POP directive โ€” with PUSH, you push the CDF state onto a stack ๐Ÿ“š. With POP, you go back to the last pushed state. directive can be one of:
    • CALL-CONVENTION
    • COBOL-WORDS
    • DEFINE
    • SOURCE FORMAT
    • TURN
  • >>TURN [ec [file ...] ...] CHECKING {[ON] [[WITH] LOCATION] | OFF} โ€” enables ec, the exception condition, optionally tied to the file connectors file. With OFF, it disables it instead ๐Ÿ””. If you add LOCATION, gcobol reports the source filename and line number of the statement that triggered the exception at runtime ๐Ÿ“.

๐ŸŒˆ Feature-set Variables ๐ŸŒˆ

Some command-line options affect CDF feature-set variables that are special to gcobol ๐Ÿ’œ. You can set and test them with >>DEFINE and >>IF. They're easy to spot because they start with a %, which isn't allowed in a COBOL identifier anyway ๐Ÿง:

  • %EBCDIC-MODE โ€” gets set by -fexec-charset=<encoding> for all EBCDIC encodings.
  • %64-BIT-POINTER โ€” implied by -dialect ibm.

To set one, use:

>>SET feature [AS] {ON | OFF}

If feature is %EBCDIC-MODE, the directive must show up before PROGRAM-ID ๐Ÿšจ.

To test one, use:

>>IF feature DEFINED

๐Ÿ‘‘ Intrinsic functions ๐Ÿ‘‘

gcobol implements every intrinsic function defined by ISO/IEC 1989:2023, plus a few extras โœจ. Here's the whole squad ๐Ÿ’–:

ABS ACOS ANNUITY ASIN ATAN
BASECONVERT BIT-OF BIT-TO-CHAR BOOLEAN-OF-INTEGER BYTE-LENGTH
CHAR CHAR-NATIONAL COMBINED-DATETIME CONCAT CONVERT COS CURRENT-DATE
DATE-OF-INTEGER DATE-TO-YYYYMMDD DAY-OF-INTEGER DAY-TO-YYYYDDD
DISPLAY-OF
E EXCEPTION-FILE EXCEPTION-FILE-N EXCEPTION-LOCATION
EXCEPTION-LOCATION-N EXCEPTION-STATEMENT EXCEPTION-STATUS EXP EXP10
FACTORIAL FIND-STRING FORMATTED-CURRENT-DATE FORMATTED-DATE
FORMATTED-DATETIME FORMATTED-TIME FRACTION-PART
HEX-OF HEX-TO-CHAR HIGHEST-ALGEBRAIC
INTEGER INTEGER-OF-BOOLEAN INTEGER-OF-DATE INTEGER-OF-DAY
INTEGER-OF-FORMATTED-DATE INTEGER-PART
LENGTH LOCALE-COMPARE LOCALE-DATE LOCALE-TIME LOCALE-TIME-FROM-SECONDS
LOG LOG10 LOWER-CASE LOWEST-ALGEBRAIC
MAX MEAN MEDIAN MIDRANGE MIN MOD MODULE-NAME
NATIONAL-OF NUMVAL NUMVAL-C NUMVAL-F ORD
ORD-MAX ORD-MIN
PI PRESENT-VALUE
RANDOM RANGE REM REVERSE
SECONDS-FROM-FORMATTED-TIME SECONDS-PAST-MIDNIGHT SIGN SIN
SMALLEST-ALGEBRAIC SQRT STANDARD-COMPARE STANDARD-DEVIATION SUBSTITUTE
SUM
TAN TEST-DATE-YYYYMMDD TEST-DAY-YYYYDDD TEST-FORMATTED-DATETIME
TEST-NUMVAL TEST-NUMVAL-C TEST-NUMVAL-F TRIM
ULENGTH UPOS UPPER-CASE USUBSTR USUPPLEMENTARY UUID4 UVALID UWIDTH
VARIANCE
WHEN-COMPILED
YEAR-TO-YYYY

๐Ÿงš Binary floating point DISPLAY ๐Ÿงš

So how DISPLAY shows a binary floating point number depends on the value ๐ŸŒธ.

  • A value with six or fewer digits to the left of the decimal point shows up like 123456.789....
  • A value under 1 with no more than three zeroes to the right of the decimal point shows up like 0.0001234....
  • Anything else switches to exponential notation, like 1.23456E+7 ๐Ÿ’ซ.

In every case, trailing zeroes on the right get dropped from the displayed value ๐Ÿงฝ.

  • COMP-1 displays with 9 decimal digits.
  • COMP-2 displays with 17 decimal digits.
  • FLOAT-EXTENDED displays with 36 decimal digits.

Those digit counts line up with the IEEE 754 requirements for information interchange ๐Ÿค“. For example, that's the rule for COMP-2 binary64 values, per Wikipedia.

If an IEEE 754 double-precision number gets converted to a decimal string with at least 17 significant digits, and then converted back to double-precision, the final result has to match the original number ๐Ÿ’ฏ.

17 digits was picked so that DISPLAY shows the contents of a COMP-2 variable without hiding any information ๐Ÿ‘€.


๐Ÿฆ‹ Binary floating point MOVE ๐Ÿฆ‹

During a MOVE, a floating-point value can get truncated ๐Ÿ˜ฌ. It's not unusual for Numeric Display values to change when they get moved through a floating-point value.

This program:

    01 PICV999 PIC 9999V999.
    01 COMP2 COMP-2.
   PROCEDURE DIVISION.
    MOVE 1.001 to PICV999
    MOVE PICV999 TO COMP2
    DISPLAY "The result of MOVE " PICV999 " TO COMP2 is   " COMP2
    MOVE COMP2 to PICV999
    DISPLAY "The result of MOVE COMP2    TO PICV999 is " PICV999

generates this result:

    The result of MOVE 0001.001 TO COMP2 is   1.00099999999999989
    The result of MOVE COMP2    TO PICV999 is 0001.000

But the internal implementation can give results that look kinda surprising ๐Ÿ™ˆ:

    The result of MOVE 0055.110 TO COMP2 is   55.1099999999999994
    The result of MOVE COMP2    TO PICV999 is 0055.110

The reason for this mismatch is how gcobol stores and converts numbers ๐Ÿง . To convert the floating-point value into the numeric display value 0055110, gcobol multiplies 55.109999... by 1,000 and then truncates the result to an integer. Even though 55.11 can't be represented exactly in floating-point, the product of that multiplication, 55110, is exact โœจ.

When predictable conversions matter, you need rounding, and you can get it with an arithmetic statement ๐Ÿ’…:

    MOVE 1.001 to PICV999
    MOVE PICV999 TO COMP2
    DISPLAY "The result of MOVE " PICV999 " TO COMP2 is   " COMP2
    MOVE COMP2 to PICV999
    DISPLAY "The result of MOVE COMP2    TO PICV999 is " PICV999
    ADD COMP2 to ZERO GIVING PICV999 ROUNDED
    DISPLAY "The result of ADD COMP2 to ZERO GIVING PICV999 ROUNDED is " PICV999

    The result of MOVE 0001.001 TO COMP2 is   1.00099999999999989
    The result of MOVE COMP2    TO PICV999 is 0001.000
    The result of ADD COMP2 to ZERO GIVING PICV999 ROUNDED is 0001.001

๐Ÿ“ Binary floating point computation ๐Ÿ“

gcobol tries to do internal computations with binary integers whenever it can ๐Ÿ”ข. So simple arithmetic between binary values and numeric display values ends with binary intermediate results.

If a floating-point value gets mixed into the variables in a calculation, the intermediate result becomes a 128-bit floating-point value ๐ŸŒŠ.


๐Ÿšจ A warning about binary floating point comparison ๐Ÿšจ

The cardinal rule when comparing floating-point values: never, ever, test for equality. It's just not worth the hassle ๐Ÿ’€.

For example:

   WORKING-STORAGE SECTION.
    01 COMP1 COMP-1 VALUE 555.11.
    01 COMP2 COMP-2 VALUE 555.11.
   PROCEDURE DIVISION.
    DISPLAY "COMPARE " COMP1 " with " COMP2
    IF COMP1 EQUAL COMP2 DISPLAY "Equal" ELSE DISPLAY "Not equal" END-IF

    MOVE COMP1 to COMP2
    DISPLAY "COMPARE " COMP1 " with " COMP2
    IF COMP1 EQUAL COMP2 DISPLAY "Equal" ELSE DISPLAY "Not equal" END-IF

okay so here's what the program spits out ๐Ÿ‘€

COMPARE 555.1099854 with 555.110000000000014
Not equal
COMPARE 555.1099854 with 555.1099853515625
Equal

Why? ๐Ÿค” Again, it's all about the internals of gcobol. When differently sized floating-point values need to be compared, they get converted to 128-bit floats first. And it turns out that when a COMP1 gets moved to a COMP2, and they're both converted to FLOAT-EXTENDED, the two resulting values are (probably) equal. The vibe is very much "same, but not really" ๐Ÿ’€

Avoid testing for equality unless you really know what you are doing and you really test the code. And then avoid it anyway. ๐Ÿ™ˆ

Finally, it is observably the case that the gcobol implementations of floating-point conversions and comparisons don't precisely match the behavior of other COBOL compilers. You have been warned. ๐Ÿšจ


โœจ ENVIRONMENT โœจ

  • COBPATH โ€” bestie, this one is so useful ๐Ÿ’œ If it's defined, it sets the directory paths the gcobol runtime library, libgcobol.so, uses to find shared objects. It works like LD_LIBRARY_PATH and can hold several directory names separated by a colon (โ€˜:โ€™). COBPATH gets searched first, then LD_LIBRARY_PATH. Just know that COBPATH does not change where the runtime linker looks for libgcobol.so itself. How the runtime linker searches for it when the executable loads is controlled by ld.so(8), not libgcobol.

Each directory gets searched for files whose name ends in โ€˜.soโ€™. For each one, dlopen(3) is attempted and, if that works, dlsym(3). There's no relationship defined between the symbol's name and the filename, so don't go looking for one ๐Ÿ™…โ€โ™€๏ธ

Without COBPATH, binaries produced by gcobol behave the way you'd expect from any program compiled with gcc. Any shared objects the program needs get mentioned on the command line with a -llibrary option, and they're found by following the executable's RPATH, or otherwise per the configuration of the runtime linker, ld.so(8). Totally normal, no drama ๐ŸŒธ

  • UPSI โ€” COBOL defines a User Programmable Status Indicator (UPSI) switch, and in gcobol these show up as UPSI-0 through UPSI-7, where the number is a bit position. The values come from the UPSI environment variable, which is a string of up to eight 1's and 0's. The first character is the value of UPSI-0, and any missing values get assigned 0. For example, UPSI=1000011 in the environment sets bits 0, 5, and 6 on, which means UPSI-0, UPSI-5, and UPSI-6 are on โœจ
  • GCOBOL_TEMPDIR โ€” this one makes any temporary files created during CDF processing get written to a file whose name is given in the value of GCOBOL_TEMPDIR. Now, if the value is just โ€œ/โ€, the effect is totally different: each copybook read gets reported on standard error instead. It's meant to help you diagnose mysterious copybook errors, so if your copybooks are being sus, this is your friend ๐Ÿงš

๐Ÿงš Variables for Developers ๐Ÿงš

  • GCOBOL_SHOW โ€” produces a trace of the internal calls the parser makes while it prepares the GENERIC tree ๐ŸŒˆ
  • GCOBOL_TRACE โ€” used at compile time, this produces an executable that traces its execution. It maps everything back to the same code-creation functions as GCOBOL_SHOW, and it also shows the values of data items and branch conditions ๐Ÿ’…

โœจ FILES โœจ

Executables produced by gcobol require the runtime support library libgcobol, which is provided both as a static library and as a shared object. So it's in two flavors, pick your fighter ๐Ÿซถ


โœจ COMPATIBILITY โœจ

The ISO standard leaves the default file organization up to the implementation. In gcobol, the default is SEQUENTIAL.

On-Disk Format

Any ability to use files produced by other COBOL compilers, or for those compilers to use files produced by gcobol, is the product of luck and intuition ๐ŸŽฒ Various compilers interpret the ISO standard differently, and the standard's text is not always definitive. Honestly, it's giving chaos.

For ORGANIZATION IS LINE SEQUENTIAL files (explicitly or by default), gcobol, absent specific direction, produces an ordinary Linux text file. For each WRITE, the data are written, followed by an ASCII NL (hex 0A) character. On READ, the record is read up to the size of the specified record or NL, whichever comes first. The NL is not included in the data brought into the record buffer; it only serves as an on-disk record-termination marker. So SEQUENTIAL and LINE SEQUENTIAL files work the same way: the COBOL program never sees the record terminator ๐Ÿฆ‹

When READ and WRITE are used with ADVANCING, though, the plot twist hits. If ADVANCING is used with LINE SEQUENTIAL files, gcobol honors it โœจ

Other compilers may not do likewise. According to ISO, in WRITE (14.9.47.3 General rules), ADVANCING is ignored for files for which โ€œthe physical file does not support vertical positioningโ€. It further states that, in the absence of ADVANCING, WRITE proceeds as if โ€œas if the user has specified AFTER ADVANCING 1 LINEโ€. Some other implementations interpret that to mean that the first WRITE to a LINE SEQUENTIAL file results in a leading NL on the first line, and no trailing NL on the last line. Some furthermore prohibit the use of ADVANCING with LINE SEQUENTIAL files. So yeah, not everyone plays nice ๐Ÿ˜ญ


โœจ STANDARDS โœจ

The reference standard for gcobol is ISO/IEC 1989:2023. Here's how it goes:

  • If gcobol compiles code consistent with that standard, the resulting program should execute correctly. Any other result is a bug ๐Ÿ›
  • If gcobol compiles code that doesn't comply with that standard, but runs correctly according to some other specification, that counts as a non-standard extension. One day, the -pedantic option will produce diagnostic messages for such code ๐Ÿ”ฅ
  • If gcobol rejects code consistent with that standard, that represents an aspect of COBOL that is (or is not) on the To Do list. If you'd like to see it compile, please get in touch with the developers ๐Ÿ’–

Status of NIST COBOL Compiler Verification Suite

NC 100%    Nucleus
SQ 100%    Sequential I/O
RL 100%    Relative I/O
IX 100%    Indexed I/O
IC 100%    Inter-Program Communication
ST 100%    Sort-Merge
SM 100%    Source Text Manipulation RW \n Report Writer
CM         Communication
DB to do?  Debug
SG         Segmentation
IF 100%    Intrinsic Function

Where gcobol passes 100% of the tests in a module, we exclude the (few) tests for obsolete features. The authors regard features that were obsolete in 1985 to be well and truly obsolete today, and did not implement them. Iconic behavior, honestly ๐Ÿ’…

Notable deferred features

CCVS-85 modules not marked above with any status (CM, and SG) are on the โ€œhard maybeโ€ list, meaning they await an interested party with real code using the feature ๐Ÿ‘€

gcobol does not implement Report Writer or Screen Section. Not today, bestie ๐Ÿ™…โ€โ™€๏ธ

Beyond COBOL/85

gcobol increasingly implements ISO/IEC 1989:2023. For example, DECLARATIVES is not tested by CCVS-85, but it is implemented by gcobol. Similarly, Exception Conditions were not defined in 1985, and gcobol contains a growing number of them ๐ŸŒŸ

The authors are well aware that a complete, pure COBOL-85 compiler won't compile most existing COBOL code. Every vendor offered (and offers) extensions, and most environments rely on a variety of preprocessors and ancillary systems defined outside the standard. The express goal of adding an ISO COBOL front-end to GCC is to establish a foundation on which any needed extensions can be built ๐Ÿ—๏ธ๐Ÿ’œ


โœจ HISTORY โœจ

COBOL, the language, may well be older than the reader ๐Ÿ’€ To the author's knowledge, free COBOL compilers first began to appear in 2000. Around that time, an earlier COBOL for GCC project, cobolforgcc: https://cobolforgcc.sourceforge.net/, met with some success, but was never officially merged into GCC.

This compiler, gcobol, was begun by COBOLworx, https://www.cobolworx.com/, in the fall of 2021. The project announced a complete implementation of the core language features in December 2022 ๐ŸŽ‰


โœจ AUTHORS โœจ

  • James K. Lowden โ€” (jklowden@cobolworx.com) is responsible for the parser ๐Ÿง 
  • Robert Dubner โ€” (rdubner@cobolworx.com) is responsible for producing the GIMPLE tree, which is input to the GCC back-end ๐ŸŒธ

โœจ CAVEATS โœจ

Read these, bestie, they're important ๐Ÿšจ
  • gcobol has been tested only on x64 and Apple M1 processors running Linux in 64-bit mode. So if you're on something else, that's a different story ๐Ÿซ 
  • The I/O support has not been extensively tested, and does not implement or emulate many features related to VSAM and other mainframe subsystems. While LINE-SEQUENTIAL files are ordinary text files that you can manipulate with standard utilities, INDEXED and RELATIVE files produced by gcobol are not compatible with those of any other COBOL compiler. Enhancements to the I/O support will be readily available to the paying customer ๐Ÿ’ธ

That's the whole page, bestie! ๐ŸŽ€ Source: Linux, dated February 2025 ๐ŸŒˆ Now go be iconic ๐Ÿ’…โœจ

๐Ÿ“ฆ where this page comes from