GCOBOL(1)
๐ GCOBOL(1) โ the GCC COBOL Compiler ๐
okay so this is the manual page for gcobol, the GCC COBOL compiler, and bestie it is so serious ๐
โจ
โจ NAME โจ
the name bit is short and sweet ๐ gcobol is the GCC COBOL Front-end ๐ธ
โจ SYNOPSIS โจ
here's the full lineup of ways you can call it, and yes there are a lot of flags ๐ญ๐ซถ
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]
[-finternal-ebcdic] [-dialect dialect-name] [-include filename]
[-preprocess preprocess-filter] [-fflex-debug] [-fyacc-debug]
filename [...]
โจ DESCRIPTION โจ
okay bestie, so gcobol takes your COBOL source code and compiles it into object code ๐ป, and if you want, it'll even make an executable binary or a shared object for you ๐ฆ. As a GCC component it accepts all the options that affect code-generation and linking (so many, literally), and the COBOL-specific ones are listed below ๐
๐ Entry points: -main and -nomain
-main filenameโ gcobol makes amain()function as the entry point, and it calls the first PROGRAM-ID infilename๐-mainis the default. If none of-nomain,-c, or-sharedshows up in the command line, an implicit-maingets slipped in ahead of the first source file name ๐
-main=filenameโ the.oobject module forfilenamewill include amain()entry point that calls the first PROGRAM-ID infilenameโจ-main=filename:program-idโ the.oobject module forfilenamewill include amain()entry point that calls theprogram-identry point ๐ง-nomainโ nomain()entry point gets generated by this compilation ๐ฅฒ-nomainis incompatible with-main, and it's implied by-shared. It's also implied by-cwhen there's no-mainpresent ๐ซถ- Check out the examples further down to see
-mainand-nomainin action ๐
๐ธ Defines and listings
-D name[=expr]โ defines a CDF name (for use with>>IF) so it has the value ofexpr๐-Eโ writes the CDF-processed COBOL input to standard output in free-form reference format ๐. Some non-COBOL markers show up to point out where copybook files got included, and blank lines are kept so the line numbers still match the input ๐ฆ- Unlike the C compiler, this option does not stop compilation. If you want compilation stopped, add
-fsyntax-onlytoo ๐ซ
- Unlike the C compiler, this option does not stop compilation. If you want compilation stopped, add
๐ง Data and defaults
-fdefaultbyte=valueโvalueis a number from 0 to 255 that becomes the default for all WORKING-STORAGE data items with no VALUE clause ๐งธ. By default, alphanumeric items get blanks and numeric items get zero, but this option overrides that withvalue๐
๐ซง Syntax, copybooks and format
-fsyntax-onlyโ only the parser runs โ . It checks the code for syntax errors but doesn't do anything beyond that ๐-copyext extโ for the CDF directiveCOPY name, whennameis unquoted, several varieties ofnameget tried, as described below under Copybooks ๐. This option extends the names searched to includeext. Ifextis all uppercase or all lowercase, both forms get tried, with preference given to the one you supplied. Ifextis mixed-case, only that version gets tried ๐ง- For example, with
-copyext .abcgiven the CDF directiveCOPY name, gcobol adds โname.abcโ and โname.ABCโ to the possible names searched, in that order ๐
- For example, with
-ffixed-formโ strict fixed-form reference format ๐: 72-character lines, a 6-character sequence area, and an indicator column. Data past column 72 gets ignored ๐-ffree-formโ forces the COBOL input to be read as free-form reference format ๐. Line breaks don't matter, except that a*at the start of a line acts as a comment marker ๐ฌ. This is equivalent to-indicator-column 0๐ง-findicator-columnโ describes where the Indicator Area lives in a COBOL file in Reference Format ๐. The first 6 columns (the โSequence Number Areaโ) get ignored, and the 7th column (the Indicator Area) may hold a character of significance to the compiler ๐- Strictly speaking, reference format ignores data after column 72, but with this option gcobol accepts long COBOL lines, sometimes called extended source format ๐ฆ. Text past column 72 is treated as ordinary COBOL text. Line continuation stays in effect, as long as no text appears past column 72 โจ
- There's no maximum line length ๐คฏ. Regardless of source code format, the entire program could appear on one line
- By default, gcobol auto-detects the source code format by examining the line that contains the text "program-id" ๐. When there are characters past column 72 on that line, the file is assumed to be extended source format, with the indicator area in column 7. Otherwise, columns 1-6 get examined. If those characters are all digits or blanks, the file is assumed to be fixed-form reference format, also with the indicator in column 7. If it isn't auto-detected as fixed-form reference format or extended source format, the file is assumed to be free-form reference format ๐
๐ฅ Exceptions
-fcobol-exceptions exception [,exception...]โ by default, no exception condition is enabled (fatal ones included), and ISO standard exception conditions only turn on through the CDF TURN directive ๐ค. This option enables one or more exception conditions by default, as though TURN had appeared at the top of the first source code file ๐. It may appear more than once on the command line ๐- The value of
exceptionis a Level 1, 2, or 3 exception condition name, as described by ISO/IEC 1989:2023.EC-ALLmeans enable all exceptions ๐ฅ - The
-fno-cobol-exceptionsform turns offexception, just as though>>TURN exception CHECKING OFFhad appeared ๐ซถ - > Not all exception conditions are implemented. Any that aren't will produce a warning message โ ๏ธ
- The value of
๐ Error limits
-fmax-errors=nerrorโnerroris the number of error messages produced ๐งฎ. Without this option, gcobol tries to recover from a syntax error by resuming at the next statement, continuing until end-of-file ๐. With it, gcobol counts the messages as they're produced and stops oncenerroris reached โ
๐ CALL linking
-fstatic-call,-fno-static-callโ with-fno-static-call, gcobol never uses static linking forCALL program๐- By default, or with
-fstatic-call, ifprogramis an alphanumeric literal, gcobol uses static linkage. That means the compiler produces an external symbolprogramfor the linker to resolve ๐. (In the future, that will work with CONSTANT data items, too ๐ฎ) - With static linkage, if
programisn't supplied by the source code module, another object file, or a library at build time, the linker will produce an โunresolved symbolโ error ๐ฌ - With
-fno-static-call, gcobol always uses dynamic linking ๐ฆ - This option affects the CALL statement for literals only. If
programis a non-constant data item, it's always resolved using dynamic linking, withdlsym(3), because its value is determined at run time โฑ๏ธ
- By default, or with
๐ฃ๏ธ Dialects
-dialect dialect-nameโ by default, gcobol accepts COBOL syntax as defined by ISO/IEC 1989:2023, with some extensions for backward compatibility with COBOL-85 ๐. To make the compiler more generally useful, this option supports some additional syntax ๐- The value of
dialect-namemay be:ibmโ to indicate IBM COBOL 6.3 syntax, specificallySTOP <number>gnuโ to indicate GnuCOBOL syntaxmfโ to indicate MicroFocus syntax, specifically LEVEL 78 constants
- Only a few of these non-standard constructs are accepted, and gcobol makes no claim to emulate other compilers ๐. But to the extent that a feature is popular but nonstandard, this option gives a way to support it, or add it ๐
- The value of
๐ Includes and filters
-include filenameโ processesfilenameas ifCOPY โfilenameโappeared as the first line of the primary source file ๐. Iffilenameisn't an absolute path, the directory searched is the current working directory, not the directory containing the main source file ๐. The name is used verbatim. No permutations are applied, and no directories are searched ๐ซ- If multiple
-includeoptions are given, the files are included in the order they appear on the command line ๐ข
- If multiple
-preprocess preprocess-filterโ after all CDF text manipulation has been applied, and before the prepared COBOL is sent to thecobol1compiler, the input may be further altered by one or more filters ๐งผ. Like sed(1), eachpreprocess-filterreads from standard input and writes to standard output ๐ช- To supply options to
preprocess-filter, use a comma-separated string, similar to how linker options are supplied to-Wl. Do not put any spaces after the commas, because the shell will treat it as an option separator ๐ . gcobol replaces each comma with a space whenpreprocess-filteris invoked. For example,-preprocess tee,output.cblinvokes tee(1) with the output filename argumentoutput.cbl, causing a copy of the input to be written to the file ๐ - gcobol searches the current working directory and the
PATHenvironment variable directories for an executable file whose name matchespreprocess-filter. The first one found is used. If none is found, an error is reported and the compiler is not invoked ๐ - The
-preprocessoption may appear more than once on the command line. Eachpreprocess-filteris applied in turn, in order of appearance ๐ - The
preprocess-filtershould return a zero exit status, indicating success. If it returns a nonzero exit status, an error is reported and the compiler is not invoked ๐ฅฒ
- To supply options to
๐ ๏ธ Compiler debugging
-fflex-debug,-fyacc-debugโ produce messages useful for compiler development ๐ง . The-fflex-debugoption prints the tokenized input stream, and the-fyacc-debugoption shows the shift and reduce actions taken by the parser ๐ค
โจ COMPILATION SCENARIOS โจ
okay so let's talk about actually building stuff ๐ ๏ธ๐ these first three are all the same vibe:
gcobol xyz.cob
gcobol -main xyz.cob
gcobol -main=xyz.cob xyz.cob
They're equivalent ๐
xyz.cob gets compiled and gcobol slides in a main() function that calls the first PROGRAM-ID in the xyz.cob source file. main character energy ๐
gcobol -nomain xyz.cob elsewhere.o
-nomain is the "nah, I've got my own main" flag ๐
โโ๏ธ It stops gcobol from generating a main(). That means elsewhere.o has to already have a main() entry point, or the linker will throw a โmissing mainโ error ๐
gcobol aaa.cob bbb.cob ccc.cob
gcobol -main aaa.cob bbb.cob ccc.cob
These two are equivalent ๐ซถ All three source modules get compiled and linked together, plus a generated main() that calls the first PROGRAM-ID in aaa.cob.
gcobol aaa.cob bbb.cob -main ccc.cob
gcobol -main=ccc.cob aaa.cob bbb.cob ccc.cob
Same result here ๐ฆ You end up with an a.out executable that starts running at the first PROGRAM-ID in ccc.cob.
gcobol -main=bbb.cob:b-entry aaa.cob bbb.cob ccc.cob
This one's so specific it's giving sniper ๐ฏ You get an a.out that starts 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 each make a .o file ๐ง The bbb.o file is the special one because it'll contain a main() entry point that calls the first PROGRAM-ID in bbb. The last line links all three .o files into an a.out ๐
๐ EBCDIC ๐
the -finternal-ebcdic option is โจ for mainframe COBOL programs that are meant for EBCDIC-encoded files โจ Here's the tea: the COBOL text itself stays in ASCII, but character literals and field initial values turn into EBCDIC strings in the compiled binary. Any character data read from a file gets interpreted as EBCDIC too ๐ The file data itself is not converted. The file is just assumed to be EBCDIC. String literals in the COBOL text do get converted, so you can actually compare them meaningfully with what's in the file ๐
Only file data and character literals are affected ๐ Data read from and written to the environment, or taken from the command line, gets interpreted according to the locale(7) in force during execution. Same deal for ACCEPT and DISPLAY. Names the operating system already knows about, like file names and environment variable names, are processed verbatim ๐ซถ
At the present time this is an all-or-nothing setting. Support forUSAGEandCODESET, which would allow conversion between encodings, is a future goal, not something that exists yet ๐ญ
See also โFeature-set Variablesโ, below ๐ฆ
๐ฆ REDEFINES ... USAGE POINTER ๐ฆ
okay so per ISO, an item that REDEFINES another can't be bigger than the item it redefines, unless that item is LEVEL 01 and not EXTERNAL ๐ gcobol has a little exception for this when you use -dialect ibm ๐ธ It relaxes the rule for REDEFINES with USAGE POINTER when the 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 resized to 8 bytes so the pointer fits. This is what lets you do pointer arithmetic on a 64-bit system with source code that was written for a 32-bit system ๐
See also โFeature-set Variablesโ, below โจ
โจ IMPLEMENTATION NOTES โจ
gcobol is a gcc compiler, so it follows gcc conventions wherever that makes sense ๐ง Sometimes those conventions (and what users expect) clash with common mainframe practice. Unless the ISO spec requires otherwise, any clash gets resolved in favor of gcc ๐
๐ Linking
Unlike C, the COBOL CALL statement implies dynamic linking, because for
CALL program
the program can be a variable whose value isn't determined until runtime ๐ It can also be a compile-time constant, either an alphanumeric literal or a CONSTANT data item.
gcobol supports static linking where it can, unless you turn it off with -fno-static-call ๐ If the parameter's value is known at compile time, the compiler makes an external reference for the linker to resolve. That referenced program is normally supplied through an object module, a static library, or a shared object. If it's missing, the linker will report an โunresolved symbolโ error, either at build time or, if you're using a shared object, when the program runs. This is intentional: it tells you about the error at the earliest possible moment ๐
Programs that are expected to run fine 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 ๐ โโ๏ธ Implemented ECs can be enabled on the command line or with the TURN directive. Trying to enable an EC that isn't implemented is treated 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 ๐ญ Trying to enable an EC that isn't implemented produces a warning message. These are the ones that are implemented:
EC-FUNCTION-ARGUMENTโ for these functions:ACOSANNUITYASINLOGLOG10PRESENT-VALUESQRT
EC-SORT-MERGE-FILE-OPENEC-BOUND-SUBSCRIPTโ the subscript is not an integer, is less than 1, or is greater thanoccursEC-BOUND-REF-MODโ the refmod start is not an integer, is less than 1, or is greater than the variable size. The length is not an integer, is less than 1, or start+length exceeds the variable sizeEC-BOUND-ODOโDEPENDINGis not an integer, is greater than theoccursupper limit, or is less than theoccurslower limit. Also, the subscript is greater thanDEPENDINGfor the sending itemEC-SIZE-ZERO-DIVIDEโ for both fixed-point and floating-point division โEC-SIZE-TRUNCATIONEC-SIZE-EXPONENTIATION
As of this writing, no COBOL compiler documents a complete implementation of ISO/IEC 1989:2023 Exception Conditions ๐คฏ gcobol will prioritize the ECs that 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 support for them, using syntax similar to GnuCOBOL ๐ซถ ISO and IBM also define incompatible ways to return the program's exit status to the operating system. gcobol goes with IBM syntax ๐
๐ฟ Environment Variables
To read an environment variable:
ACCEPT target FROM ENVIRONMENT envar
target is a data item defined in the 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, and the rules are the same as for MOVE ๐
To write an environment variable:
SET ENVIRONMENT envar TO source
source is a data item defined in the DATA DIVISION, and envar names an environment variable. Again, envar can be a string literal or an alphanumeric data item holding the name of an environment variable. The named environment variable gets 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 gets invoked like this:
./program -i input output
then this:
ACCEPT target FROM COMMAND-LINE(3)
moves input into target ๐ฆ The program name is the first thing in the whole command line, so it lives in COMMAND-LINE(1) of the COMMAND-LINE table.
To find out how many arguments were provided, use:
ACCEPT target FROM COMMAND-LINE-COUNT
If ACCEPT refers to a nonexistent environment variable or command-line argument, the target gets set to LOW-VALUES ๐
The system command-line parameters can also be reached 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 this form:
#line lineno โfilenameโ.
This sets the current line number to lineno and the current input filename to filename ๐ Preprocessors can 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 can be in quotes or not ๐ If it's quoted, it represents a filename as the operating system knows it. If it's unquoted, it names either a data element or an environment variable that contains the name of a file. If filename matches the name of a data element, that element gets used. If not, resolving filename gets deferred until runtime, and at that point the name has to be in the program's environment ๐
โจ ISO COBOL Implementation Status โจ
๐ USAGE Data Types
okay so gcobol supports these USAGE IS clauses, bestie ๐
INDEXโ for when you need an index into a table ๐POINTERโ for variables that hold the address of an external function, aPROGRAM-ID, or a data item. You assign to them with theSETstatement ๐งBINARY,COMP,COMPUTATIONAL,COMP-4,COMPUTATIONAL-4โ big-endian integer, 1 to 16 bytes, sized by thePICTURE๐ฅCOMP-1,COMPUTATIONAL-1,FLOAT-BINARY-32โ IEEE 754 single-precision floating point, 4 bytes, handled by the hardware ๐ฆCOMP-2,COMPUTATIONAL-2,FLOAT-BINARY-64โ IEEE 754 double-precision floating point, 8 bytes, also handled by the hardware ๐COMP-3,COMPUTATIONAL-3,PACKED-DECIMALโ currently unimplemented ๐
Heads up, these three are not implemented yet, so don't build your whole life around COMP-3 just yet.
COMP-5,COMPUTATIONAL-5โ little-endian integer, 1 to 16 bytes, sized by thePICTUREโจFLOAT-BINARY-128,FLOAT-EXTENDEDโ 128-bit floating point, per IEEE 754 ๐
gcobol supports the ISO integer BINARY-<type> types, and most of them are just aliases for COMP-5. It's giving organized ๐
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, so you cannot use them 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. Math with main character energy ๐
๐ธ Environment Names
In gcobol, DISPLAY UPON is the one doing the mapping:
DISPLAY UPON
It maps SYSOUT and STDOUT to standard output, and SYSPUNCH, SYSPCH and STDERR to standard error ๐ฃ
๐ Exit Status
gcobol supports the ISO syntax for handing an exit status back to the operating system:
STOP RUN [WITH] {NORMAL | ERROR} [STATUS] status
It also supports the IBM syntax, which uses the RETURN-CODE register. The vibe is very "old school but make it work" ๐
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 because no comprehensive test suite has been identified. Be careful out here, bestie ๐ญ
๐ฆ CDF Text Manipulation
The COPY statement looks like this:
COPY copybook [OF|BY library] [REPLACING ...]
So if copybook is a literal, it's treated as a literal filename, and that file may or may not exist ๐ If copybook is a COBOL word instead, gcobol first checks for an environment variable with that same name. If it finds one, it uses the contents of that variable as the name of the copybook file. If that file doesn't exist, it keeps looking for a file with one of these names, in this order:
copybook(literally)copybook.cpycopybook.CPYcopybook.cblcopybook.CBLcopybook.cobcopybook.COB
It checks the same directory as the source code file first, then any copybook-path you set with the -I option. A copybook-path can be a colon-separated list, just like the shell's PATH variable. You can pass -I multiple times on the command line, and each new path gets added onto the ones before it. Relative paths (the ones without a leading /) are searched relative to the compiler's current working directory. ๐บ๏ธ
For example:
-I /usr/local/include:include
This searches the directory where the COBOL program lives first, then /usr/local/include, and finally an include subdirectory of the directory you invoked gcobol from ๐งญ
For the REPLACING phrase, both the modern pseudo-text form and the COBOL/85 form are recognized. The older forms are the ones used in the NIST CCVS/85 test suite, so they're still around for a reason ๐ซถ
gcobol supports the full ISO REPLACE syntax:
REPLACE ...
๐ CDF Directives
Here's the directive lineup. Slay the whole list ๐
>>DEFINE
>>DEFINE name AS {expression | PARAMETER} [OVERRIDE]
This 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 has no effect in gcobol ๐
>>DEFINE name AS OFF
This releases the definition of name, so using it after that is invalid ๐ซ
>>IF
>>IF cce text [>>ELSE alt-text] >>END-IF
This 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, alt-text gets compiled instead, if you included one. [IS [NOT]] DEFINED is supported. Boolean literals are not supported ๐ซโจ
>>EVALUATE
Not implemented ๐
>>CALL-CONVENTION
>>CALL-CONVENTION convention
convention can be one of:
COBOLโ standard COBOL case-insensitive symbol-name matching. ForCALL โnameโ, the compiler rendersnamein lowercase ๐คCโ case-sensitive symbol-name matching. TheCALLtarget isn't changed at all, it's used verbatim ๐ฏVERBATIMโ an alias for>>CALL-CONVENTION C๐ฆ
>>COBOL-WORDS
>>COBOL-WORDS EQUATE keyword WITH alias
This makes alias a synonym for keyword ๐ฏโโ๏ธ
>>COBOL-WORDS UNDEFINE keyword
This removes keyword from the COBOL grammar. If a program uses it, the compiler will throw a syntax error ๐จ
>>COBOL-WORDS SUBSTITUTE keyword BY new-word
This 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
This treats new-word as a COBOL keyword. The program can't use it at all, either as a keyword or as a user-defined word ๐
>>DISPLAY
>>DISPLAY string ...
This writes string to standard error as a warning message โ ๏ธ
>>SOURCE
>>SOURCE format
format can be one of:
FIXEDโ the source follows the COBOL fixed-form reference format, with unlimited line length ๐FREEโ the source follows the COBOL free-form reference format. Aโ*โat the beginning of a line is recognized as a comment ๐ฌ
Not-yet-real directives
These are all not implemented yet, so they're just vibes for now ๐ป
>>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 and >>POP
>>PUSH directive
>>POP directive
With PUSH, you push the CDF state onto a stack. With POP, you go back to the prior pushed state ๐ The directive can be one of: CALL-CONVENTION, COBOL-WORDS, DEFINE, SOURCE FORMAT, or TURN.
>>TURN
>>TURN [ec [file ...] ...] CHECKING {[ON] [[WITH] LOCATION] | OFF}
This enables the exception condition ec, or disables it if you use OFF. You can optionally tie ec to the file connectors file ๐ If you include LOCATION, gcobol reports at runtime the source filename and line number of the statement that set off the exception condition ๐
๐ Feature-set Variables
Some command-line options affect CDF feature-set variables that are special to gcobol. You can set and test them using >>DEFINE and >>IF. They're easy to spot because they start with a %, which isn't valid in a COBOL identifier anyway ๐
%EBCDIC-MODEโ set by-finternal-ebcdic.%64-BIT-POINTERโ implied by-dialect ibm.
To set a feature-set variable, use:
>>SET feature [AS] {ON | OFF}
Iffeatureis%EBCDIC-MODE, the directive must appear beforePROGRAM-ID. Order matters, bestie ๐
To test a feature-set variable, use:
>>IF feature DEFINED
๐ Intrinsic functions
gcobol implements all the intrinsic functions defined by ISO/IEC 1989:2023, plus a few extras. They're lined up alphabetically below ๐ญ
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
How DISPLAY presents binary floating point numbers depends on the value. It's giving "the number decides its own outfit" ๐
- If a value has six or fewer digits to the left of the decimal point, it's shown like
123456.789.... - If a value is less than 1 and has no more than three zeroes to the right of the decimal point, it's shown like
0.0001234.... - Otherwise, you get exponential notation, like
1.23456E+7๐
In all cases, trailing zeroes on the right of the number get removed from the displayed value. โจ
COMP-1โ displayed with 9 decimal digits ๐COMP-2โ displayed with 17 decimal digits โจFLOAT-EXTENDEDโ displayed with 36 decimal digits ๐
Those digit counts are lowkey giving IEEE 754 energy ๐ค, since they match the requirements for information interchange. As one example, check out the description 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 representation, the final result must match the original number. Iconic, right? โจ
17 digits was picked so that DISPLAY shows the contents of a COMP-2 variable without hiding any information. No secrets, no cap ๐
๐ฆ Binary floating point MOVE ๐ฆ
Okay, so during a MOVE statement, a floating-point value may be truncated ๐ญ. It's not unusual for Numeric Display values to get altered 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
However, the internal implementation can produce results that might seem surprising ๐:
The result of MOVE 0055.110 TO COMP2 is 55.1099999999999994
The result of MOVE COMP2 TO PICV999 is 0055.110
The tea behind this inconsistency is how gcobol stores and converts numbers โ. Converting the floating-point value to the numeric display value 0055110 is done by multiplying 55.109999... by 1,000 and then truncating the result to an integer. And it turns out that even though 55.11 can't be represented in floating-point as an exact value, the product of the multiplication, 55110, is an exact value ๐คฏ.
If you need conversions to have predictable results, you'll want to apply rounding, which you can do 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 possible ๐ง . So simple arithmetic between binary values and numeric display values wraps up with binary intermediate results.
If a floating-point value gets included in the mix of variables in a calculation, then 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
the results:
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 is moved to a COMP2, and they're both converted to FLOAT-EXTENDED, the two resulting values are (probably) equal ๐คทโโ๏ธ.
Avoid testing for equality unless you really know what you're 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โ If this is defined, it specifies the directory paths the gcobol runtime library, libgcobol.so, uses to locate shared objects ๐ง. Like LD_LIBRARY_PATH, it can hold several directory names separated by a colon (โ:โ). COBPATH gets searched first, followed by LD_LIBRARY_PATH.- Each directory gets searched for files whose name ends in โ.soโ. For each one of those files, dlopen(3) is attempted and, if successful, dlsym(3). No relationship is defined between the symbol's name and the filename ๐ค.
- 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).
UPSIโ COBOL defines a User Programmable Status Indicator (UPSI) switch ๐๏ธ. In gcobol, the settings are denoted UPSI-0 through UPSI-7, where 0-7 indicates a bit position. The value of the UPSI switches comes from the UPSI environment variable, whose value is a string of up to eight 1's and 0's. The first character represents the value of UPSI-0, and missing values are assigned 0. For example,UPSI=1000011in the environment sets bits 0, 5, and 6 on, which means that UPSI-0, UPSI-5, and UPSI-6 are on โจ.GCOBOL_TEMPDIRโ This one causes any temporary files created during CDF processing to be written to a file whose name is specified in the value of GCOBOL_TEMPDIR. If the value is just โ/โ, the effect is different: each copybook read is reported on standard error ๐ฃ. It's meant to help diagnose mysterious copybook errors ๐ต๏ธโโ๏ธ.
๐ FILES ๐
Executables produced by gcobol require the runtime support library libgcobol, which is provided both as a static library and as a shared object ๐ฆ.
๐ฆ 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 ๐.
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 gets 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 twists ๐. If ADVANCING is used with LINE SEQUENTIAL files, it is honored by gcobol.
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 even furthermore prohibit the use of ADVANCING with LINE SEQUENTIAL files ๐ โโ๏ธ.
๐ STANDARDS ๐
The reference standard for gcobol is ISO/IEC 1989:2023 ๐.
- 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 represents 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% โ NucleusSQโ 100% โ Sequential I/ORLโ 100% โ Relative I/OIXโ 100% โ Indexed I/OICโ 100% โ Inter-Program CommunicationSTโ 100% โ Sort-MergeSMโ 100% โ Source Text ManipulationRW \n Report WriterCMโ (no status listed) โ CommunicationDBโ "to do?" โ DebugSGโ (no status listed) โ SegmentationIFโ 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 as well and truly obsolete today, so they didn't implement them ๐ฅ.
๐ Notable deferred features ๐
CCVS-85 modules not marked above with any status (CM and SG) are on the โhard maybeโ list ๐คทโโ๏ธ. That means they're waiting on an interested party with real code that uses the feature.
gcobol does not implement Report Writer or Screen Section ๐ โโ๏ธ.
๐ Beyond COBOL/85 ๐
gcobol increasingly implements ISO/IEC 1989:2023 ๐. For example, DECLARATIVES is not tested by CCVS-85, but gcobol implements it anyway. Similarly, Exception Conditions weren't 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 still 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 โจ
Okay so, COBOL the language is literally older than you, bestie ๐ ๐ฆ Free COBOL compilers, to the author's knowledge, first started showing up around 2000. Right around then, the cobolforgcc project (https://cobolforgcc.sourceforge.net/) had some real success ๐ธ It was never officially merged into GCC though, which is a whole plot twist ๐ญ
Then came gcobol, started by COBOLworx (https://www.cobolworx.com/) in the fall of 2021 โจ In December 2022 the project announced a complete implementation of the core language features. Iconic behavior, honestly ๐
โจ AUTHORS โจ
The two brains behind this compiler, and what each of them handles ๐
- 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 the input to the GCC back-end ๐ง
โจ CAVEATS โจ
Okay, real talk, this section is important so pay attention ๐
gcobolhas only been tested on x64 and Apple M1 processors, and only while running Linux in 64-bit mode ๐- The I/O support has not been extensively tested, and it doesn't implement or emulate many features tied to
VSAMand other mainframe subsystems.LINE-SEQUENTIALfiles are ordinary text files that you can happily poke at with standard utilities ๐ซถ ButINDEXEDandRELATIVEfiles produced bygcobolare not compatible with those from any other COBOL compiler. โ ๏ธ Enhancements to the I/O support will be readily available to the paying customer. ๐ธ
โ ๏ธ Bestie, if you're relying onINDEXEDorRELATIVEfiles to play nice with other compilers, don't. It's giving incompatibility ๐
That's the whole page, bestie! ๐ This manual page came from Linux, dated February 2025, and it's the GCOBOL(1) page. Now go forth and compile something iconic โจ๐
๐ฆ where this page comes from
- ubuntu questing: gcobol-15-aarch64-linux-gnu 15.2.0-4ubuntu4cross1
- ubuntu resolute: gcobol-15-aarch64-linux-gnu 15.2.0-16ubuntu1cross1
- ubuntu stonking: gcobol-15-aarch64-linux-gnu 15.3.0-4ubuntu1cross1
- ๐ girlified by claude-haiku-5-5 on : a language model's rewrite of the original, under its terms