Words, Literals and Figurative Constants

This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production.

The reference material consulted while preparing these pages is listed in the section bibliography.

This page is written against ISO/IEC 1989:2023 (edition 3, January 2023; an edition 4 is upcoming, in DIS ballot), GnuCOBOL 3.2 (28 July 2023, the latest release) and IBM Enterprise COBOL for z/OS 6.5 (PTFs through September 2026), and was checked on 2026-10-20. Every portable example below was compiled with cobc -x -Wall (GnuCOBOL 3.2.0, fixed reference format) and run, and, unless a section says otherwise, also with -std=ibm; the output and the diagnostics shown are real. The ISO standard is paywalled and was not read: the rules for the standard come from the vendor manuals, which say where they follow it.

Every COBOL source is a stream of character-strings and separators. A character-string is a COBOL word, a literal, a PICTURE character-string or a comment-entry; separators (spaces and punctuation) mark where one ends and the next begins. This page covers the three building blocks that every other page of the section uses without explaining: the words a program may invent and the words it may not, the literals that write values directly into the source, and the figurative constants that stand for a repeated or special value. How the lines are laid out on the card or screen is a separate subject, covered in Reference Format Fixed and Free, and where the words are used is covered in Program Structure and Divisions.

The character set and separators

The basic COBOL character set has the Latin letters A to Z and a to z, the digits 0 to 9, and the special characters space, +, -, *, /, =, $, ,, ;, :, ., ", ', (, ), <, > and _ (Enterprise COBOL Language Reference, Characters). Lowercase single-byte letters are equivalent to uppercase ones everywhere except inside literals, so move and MOVE are the same word and "abc" and "ABC" are different values. The characters that actually reach the program (the contents of a literal, the collating sequence that decides whether "a" is less than "B") depend on the code page: EBCDIC on z/OS and, by default, ASCII or the local code page under GnuCOBOL. That is the subject of National UTF-8 and Code Pages.

The separator rules are short, and they explain several errors that look mysterious:

  • A space is a separator and may precede or follow any other separator. Several spaces count as one; spaces inside a literal are part of the literal.

  • A period, comma and semicolon must each be followed by a space. A period ends a sentence (or a data description or other entry); commas and semicolons may be used between operands and statements in the Procedure Division, and compilers treat them as a space. MOVE 10 TO WS-A, WS-B. is legal; MOVE 10 TO WS-A,WS-B. is not, because the comma is not followed by a space.

  • Parentheses must be balanced. They enclose subscripts, reference modification, function arguments, arithmetic expressions and conditions.

  • Quotation marks and apostrophes must be balanced. An opening mark follows a space or a left parenthesis; a closing mark precedes a space, comma, semicolon, period, right parenthesis or pseudo-text delimiter.

  • The prefixes Z, G, N, U, X, B, NX, UX follow the same placement rules as an opening quotation mark.

  • The pseudo-text delimiter == (used by COPY ... REPLACING and REPLACE) must be balanced as well.

  • Punctuation inside a literal, a PICTURE string or a comment is part of that text and is not a separator.

The special-character words +, -, *, /, **, =, <, >, <=, >=, the floating comment *>, == and the directive marker >> are written without surrounding spaces only where the rules allow it; arithmetic operators in an expression must have a space on both sides, which is why A-B is a data name and A - B is a subtraction.

User-defined words

A user-defined word is a name the programmer chooses for a data item, condition-name, paragraph, section, file, program, index, mnemonic name, class, alphabet, symbolic character and so on. The rules (Enterprise COBOL Language Reference, COBOL words with single-byte characters and User-defined words):

  • letters, digits, hyphens, and (in Enterprise COBOL 6.5) underscores;

  • a hyphen is not the first or last character, an underscore is not the first character;

  • at least one letter, except for section names, paragraph names, priority numbers and level numbers, which may be all digits (0100-READ-LOAN, 100 and 2ND-COPY-FLAG are fine; a data name of 123 is not);

  • a limit of 30 bytes in Enterprise COBOL 6.5; the number of characters depends on the compile-time code page.

GnuCOBOL lets the dialect decide. cobc --list-reserved and the dialect files shipped with the compiler show the limits: word-length is 63 in the default dialect, 31 in cobol2014.conf, and 30 in cobol85.conf and ibm-strict.conf. (ibm.conf includes the strict file and then relaxes it, which is why -std=ibm accepts the long name shown below.) COBOL 2023 raises the limit for words to 63 characters (INCITS announcement of the 2023 edition; the standard text itself is paywalled), and the cobol2014.conf file shows 31 for the 2002 and 2014 editions. The hyphen is why COBOL names read as words (BOOK-COPIES, LOAN-MEMBER-ID) and why a subtraction needs spaces around the -.

The example uses only the allowed characters, mixes case, and starts one name with a digit.

       IDENTIFICATION DIVISION.
       PROGRAM-ID. WORDS.
      * User-defined words: letters, digits and hyphens.
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       COPY BOOKREC.
       01  2ND-COPY-FLAG       PIC X     VALUE "N".
       01  Copies-Left         PIC 9(3)  VALUE 7.
       PROCEDURE DIVISION.
       MAIN-PARAGRAPH.
           move 12 to book-copies
           ADD COPIES-LEFT TO BOOK-COPIES
           DISPLAY "COPIES: " BOOK-COPIES " FLAG: " 2ND-COPY-FLAG
           STOP RUN.

Compiled with cobc -x -Wall words.cob (and with -std=ibm), the program prints:

COPIES: 019 FLAG: N

The length limit is a dialect decision, not a property of the language. The same source with a 35-character name compiles in the default dialect and in -std=ibm, and is rejected by -std=ibm-strict and -std=cobol85:

       IDENTIFICATION DIVISION.
       PROGRAM-ID. LONGWORD.
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01  THE-NUMBER-OF-AVAILABLE-COPIES-LEFT PIC 9(3) VALUE 2.
       PROCEDURE DIVISION.
           DISPLAY THE-NUMBER-OF-AVAILABLE-COPIES-LEFT
           STOP RUN.
longword.cob:5: error: word length exceeds 30 characters: 'THE-NUMBER-OF-AVAILABLE-COPIES-LEFT'
    3 |        DATA DIVISION.
    4 |        WORKING-STORAGE SECTION.
    5 >        01  THE-NUMBER-OF-AVAILABLE-COPIES-LEFT PIC 9(3) VALUE 2.
    6 |        PROCEDURE DIVISION.
    7 |            DISPLAY THE-NUMBER-OF-AVAILABLE-COPIES-LEFT
longword.cob:7: error: word length exceeds 30 characters: 'THE-NUMBER-OF-AVAILABLE-COPIES-LEFT'
    5 |        01  THE-NUMBER-OF-AVAILABLE-COPIES-LEFT PIC 9(3) VALUE 2.
    6 |        PROCEDURE DIVISION.
    7 >            DISPLAY THE-NUMBER-OF-AVAILABLE-COPIES-LEFT
    8 |            STOP RUN.
    9 | <EOF>

The compact advice that follows from the limit: keep names under 30 characters so the program compiles under every dialect, and choose names that describe the business meaning (BOOK-COPIES), not the storage (WS-FLD-3).

Reserved words

A reserved word is a character-string with a predefined meaning. It cannot be used as a user-defined word or as a system-name. Enterprise COBOL groups them as follows (Language Reference, Reserved words):

  • keywords, required in a clause, entry or statement (MOVE, PIC, VALUE);

  • optional words, which only improve readability and have no effect (IS, ARE);

  • figurative constants (see below);

  • special-character words: arithmetic and relational operators, *>, == and >>;

  • special object identifiers SELF and SUPER in methods; and

  • special registers such as RETURN-CODE, LENGTH OF, ADDRESS OF, SORT-RETURN, whose names the program may not redefine.

The reserved-word table of the manual marks each word as reserved, as reserved only in the standard, or as a potential reserved word. The practical consequence for a reader of old code is that a name which compiled yesterday can fail after a compiler upgrade, because the new release reserved it. The remedy is a naming convention (a prefix such as WS-, BOOK-, LOAN- on every data name) rather than memorizing lists.

Context-sensitive words

Some words are reserved only in the formats where the language needs them. The manual calls them context-sensitive words: a context-sensitive word is reserved only in the general formats in which it is specified, and may be a user-defined word elsewhere. The standard introduced them so that new features could be added without breaking programs that already used those names; 3-D and ACTION in the listing below are examples. GnuCOBOL’s list shows how many there are: cobc --list-reserved of 3.2.0 lists about a thousand words for the default dialect, and 419 of them are marked "Context sensitive" (the same words are ordinary names in programs that never use the features they belong to).

cobc --list-reserved | sed -n '1,8p'
cobc --list-reserved | grep -c "Context sensitive"
Reserved Words                  Implemented
3-D                             Yes (Context sensitive)
ABSENT                          Yes
ACCEPT                          Yes
ACCESS                          Yes
ACTION                          Yes (Context sensitive)
ACTIVATING                      No (Context sensitive)
419

The reserved set of GnuCOBOL depends on the dialect too. A dialect file includes a word file (ibm.conf includes ibm.words, and the config directory of the compiler holds one .words file per dialect); -fnot-reserved=<word> takes a word out of the list and -freserved=<word> adds one (the options are in cobc --help). That is how a program written for another compiler that uses DATE or TABLE as a data name can still be compiled: free the word instead of renaming it.

What a reserved word looks like in a diagnostic

Using a reserved word as a data name is an error that names the word (this program is deliberately wrong):

       IDENTIFICATION DIVISION.
       PROGRAM-ID. BADWORDS.
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01  COPY-COUNT          PIC 9(3)  VALUE 7.
       01  DATE                PIC X(8)  VALUE "20261020".
       01  TABLE               PIC 9(3)  VALUE 1.
       01  THE-NUMBER-OF-AVAILABLE-COPIES PIC 9(3) VALUE 2.
       PROCEDURE DIVISION.
           DISPLAY COPY-COUNT
           STOP RUN.
badwords.cob:6: error: syntax error, unexpected DATE
    4 |        WORKING-STORAGE SECTION.
    5 |        01  COPY-COUNT          PIC 9(3)  VALUE 7.
    6 >        01  DATE                PIC X(8)  VALUE "20261020".
    7 |        01  TABLE               PIC 9(3)  VALUE 1.
    8 |        01  THE-NUMBER-OF-AVAILABLE-COPIES PIC 9(3) VALUE 2.
badwords.cob:7: error: syntax error, unexpected TABLE
    5 |        01  COPY-COUNT          PIC 9(3)  VALUE 7.
    6 |        01  DATE                PIC X(8)  VALUE "20261020".
    7 >        01  TABLE               PIC 9(3)  VALUE 1.
    8 |        01  THE-NUMBER-OF-AVAILABLE-COPIES PIC 9(3) VALUE 2.
    9 |        PROCEDURE DIVISION.

COPY-COUNT is accepted because COPY is only a prefix of that word: reserved words matter when a word is the whole character-string. The two rejected lines are DATE and TABLE; rename them (LOAN-DATE-TEXT, FINE-TABLE). The same error under -std=ibm is identical.

Hyphens at the wrong end of a name give a similar message. Compiling 01 COPIES- PIC 9(3). and 01 -COPIES PIC 9(3). gave syntax error, unexpected - for both lines.

Literals

A literal is a character-string whose value is given by the characters it contains, or by a figurative constant. COBOL has numeric, alphanumeric, DBCS, national and (in Enterprise COBOL) UTF-8 literals, each with a hexadecimal form.

Alphanumeric literals

An alphanumeric literal is enclosed in matching quotation marks ("...") or apostrophes ('...'). The delimiters are not part of the value. Enterprise COBOL allows 1 to 160 bytes and accepts either delimiter regardless of the QUOTE/APOST compiler option (the option only decides which character the figurative constant QUOTE stands for). To put the delimiter character into the value, double it. A literal of the other delimiter needs no doubling.

GnuCOBOL’s literal-length is 8191 in its default dialect, 160 in cobol85.conf and ibm-strict.conf. Longer values on IBM are built by continuing the literal (below), by STRING, or by a table of shorter pieces.

Numeric literals

A numeric literal has the digits 0 to 9, at most one sign (+ or -, which must be the leftmost character; no sign means positive) and at most one decimal point, which is assumed (it takes no storage) and cannot be the last character.

  • A fixed-point literal has 1 to 18 digits with ARITH(COMPAT) and 1 to 31 digits with ARITH(EXTEND) in Enterprise COBOL. GnuCOBOL’s numeric-literal-length is 38 in the default dialect, 31 in cobol2014.conf and ibm-strict.conf, and 18 in cobol85.conf.

  • A floating-point literal is a mantissa with a decimal point, an E, an optional sign and one or two exponent digits: -1.5E+2. The mantissa has 1 to 16 digits; the magnitude lies between about 0.54E-78 and 0.72E+76 (smaller becomes zero, larger becomes 0.72E+76 with a diagnostic). I did not exercise floating-point literals: a trial DISPLAY 1.5E2 with GnuCOBOL 3.2.0 printed 50, so the claim is limited to what the IBM manual states.

A numeric literal is never written with quotation marks. "100" is an alphanumeric literal; 100 is a number, and the two are not interchangeable in arithmetic. See MOVE and Data Movement for what a move does with each.

Hexadecimal alphanumeric literals

X"4A4B4C4D" or X'4A4B4C4D' gives the bytes directly: the digits are 0 to 9 and A to F, an even number of them (each pair is one byte), up to 320 hex digits in Enterprise COBOL (160 bytes). The result is an ordinary alphanumeric literal. It is how a program writes a byte that has no keyboard key (X"00", X"0A") and how the bytes are stated independently of the code page; X"C1" is A on z/OS but not under ASCII.

The first program of this page puts the quotes, apostrophes, doubled delimiters, a signed decimal and a hexadecimal literal together. It uses FUNCTION HEX-OF, new in GnuCOBOL 3.2, to show the stored bytes; I did not find a function of that name in the Enterprise COBOL function list, so on z/OS the bytes are inspected with a debugger or a hex display (see Intrinsic Functions).

       IDENTIFICATION DIVISION.
       PROGRAM-ID. LITERALS.
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01  WS-TEXT             PIC X(40).
       01  WS-AMOUNT           PIC S9(5)V99.
       01  WS-AMOUNT-OUT       PIC -(5)9.99.
       01  WS-HEX              PIC X(4).
       PROCEDURE DIVISION.
       MAIN-PARAGRAPH.
           MOVE "Library's catalogue" TO WS-TEXT
           DISPLAY WS-TEXT
           MOVE 'Say "hello"' TO WS-TEXT
           DISPLAY WS-TEXT
           MOVE "She said ""hi""" TO WS-TEXT
           DISPLAY WS-TEXT
           MOVE 'It''s here' TO WS-TEXT
           DISPLAY WS-TEXT
           MOVE -12.50 TO WS-AMOUNT
           MOVE WS-AMOUNT TO WS-AMOUNT-OUT
           DISPLAY "FINE: " WS-AMOUNT-OUT
           MOVE X"4A4B4C4D" TO WS-HEX
           DISPLAY "HEX: " WS-HEX
           DISPLAY "HEX BYTES: " FUNCTION HEX-OF(WS-HEX)
           STOP RUN.

The real output of cobc -x -Wall literals.cob (also with -std=ibm) is:

Library's catalogue
Say "hello"
She said "hi"
It's here
FINE:    -12.50
HEX: JKLM
HEX BYTES: 4A4B4C4D

The fifth line shows an editing picture applied to a numeric literal; the value of -12.50 was stored with two decimals first. The PIC characters are explained in PICTURE Clause.

Null-terminated literals

Enterprise COBOL also has Z"text" (and Z'text'), an alphanumeric literal with a null byte X"00" appended, for passing strings to C functions through CALL. It holds 0 to 159 bytes of content (160 with the terminator), cannot contain X"00" itself, and is not allowed in an ALL literal. FUNCTION LENGTH returns the length without the terminator. It is not exercised here; see Subprograms CALL and Linkage for the calls.

National, boolean and UTF-8 literals

  • National literals are written N"text" or N'text' and NX"hhhh..." for the hexadecimal form. In Enterprise COBOL 6.5 an N"..." literal is national under NSYMBOL(NATIONAL) and a DBCS literal under NSYMBOL(DBCS); the opening N and quote cannot be split over lines; the content is up to 80 character positions; a doubled quote includes the quote. GnuCOBOL 3.2 accepts N"..." and NX"..." (national-literals: ok) but still labels the support unfinished, as the real warning shows (this program is not clean on purpose; it is the case the verification rule excludes from the portable examples):

           IDENTIFICATION DIVISION.
           PROGRAM-ID. NATIONAL1.
           DATA DIVISION.
           WORKING-STORAGE SECTION.
           01  WS-NAT              PIC N(4).
           PROCEDURE DIVISION.
               MOVE N"ABCD" TO WS-NAT
               DISPLAY "NATIONAL LENGTH: " FUNCTION LENGTH(WS-NAT)
               STOP RUN.
    national.cob:5: warning: handling of USAGE NATIONAL is unfinished; implementation is likely to be changed [-Wunfinished]
        3 |        DATA DIVISION.
        4 |        WORKING-STORAGE SECTION.
        5 >        01  WS-NAT              PIC N(4).
        6 |        PROCEDURE DIVISION.
        7 |            MOVE N"ABCD" TO WS-NAT
    national.cob:7: warning: handling of national literal is unfinished; implementation is likely to be changed [-Wunfinished]
        5 |        01  WS-NAT              PIC N(4).
        6 |        PROCEDURE DIVISION.
        7 >            MOVE N"ABCD" TO WS-NAT
        8 |            DISPLAY "NATIONAL LENGTH: " FUNCTION LENGTH(WS-NAT)
        9 |            STOP RUN.

    The national data model is in National UTF-8 and Code Pages.

  • Boolean literals are B"10100101" and BX"A5" (ISO/IEC 1989:2002 and later; GnuCOBOL numeric-boolean: ok). I compiled MOVE B"10100101" TO WS-FLAGS with a PIC 1(8) item in GnuCOBOL 3.2.0 without warnings, but its DISPLAY printed 00000165, a decimal value and not the eight bits, so boolean data are best treated as a standard feature that this compiler implements only partly. Enterprise COBOL 6.5 documents no boolean literals in the pages read for this section, so they are not portable to z/OS.

  • UTF-8 literals (Enterprise COBOL 6.5) are U"text" or U'text', with a hexadecimal form UX"hh...". They may contain Unicode escapes \uhhhh and \U00hhhhh (not the surrogate range), a backslash is written \\, and up to 160 bytes after conversion are kept. A literal with DBCS characters cannot be continued. GnuCOBOL 3.2 does not have a stable UTF-8 data type; its support is experimental and out of scope for the portable examples.

Continuation of literals

A literal that does not fit on one line is continued in fixed format as follows (Enterprise COBOL Language Reference, Continuation lines):

  1. Fill the first line through column 72. Trailing spaces up to column 72 are part of the literal, so do not stop earlier.

  2. Put a hyphen in the indicator area (column 7) of the next line.

  3. Start the continuation with a quotation mark (or apostrophe, if that was the delimiter) in Area B; the content resumes immediately after it.

  4. Close the literal only on the last line.

  5. If a continued line ends with a quote character in column 72, begin the next line with two quotes, to produce one.

Hexadecimal alphanumeric and national literals can be continued, but the opening delimiter, a literal with DBCS characters and the N/U prefix cannot be split. The program below breaks one 112-character message after rep, with the first line ending exactly in column 72; the data item is PIC X(120) so nothing is truncated.

       IDENTIFICATION DIVISION.
       PROGRAM-ID. CONTINUED.
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01  WS-MESSAGE          PIC X(120).
       PROCEDURE DIVISION.
       MAIN-PARAGRAPH.
           MOVE "Overdue loans are listed on the nightly circulation rep
      -    "ort and every member with a fine above 10.00 is flagged"
               TO WS-MESSAGE
           DISPLAY WS-MESSAGE
           STOP RUN.
Overdue loans are listed on the nightly circulation report and every member with a fine above 10.00 is flagged

The unbroken text is printed, padded to 120 columns by the PIC X(120) item. A common beginner’s error is to continue a literal without the opening quote on the next line, or to forget the closing quote; both give the same family of messages. This deliberately wrong program leaves out the closing quote:

       IDENTIFICATION DIVISION.
       PROGRAM-ID. BADLIT.
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01  WS-TEXT             PIC X(40).
       PROCEDURE DIVISION.
           MOVE "Member's card TO WS-TEXT
           STOP RUN.
badliteral.cob:8: error: continuation character expected
    6 |        PROCEDURE DIVISION.
    7 |            MOVE "Member's card TO WS-TEXT
    8 >            STOP RUN.
    9 | <EOF>
badliteral.cob:7: error: invalid literal: 'Member's card TO WS-TEXT  ...'
    5 |        01  WS-TEXT             PIC X(40).
    6 |        PROCEDURE DIVISION.
    7 >            MOVE "Member's card TO WS-TEXT
    8 |            STOP RUN.
    9 | <EOF>
badliteral.cob:7: note: missing terminating " character
badliteral.cob:7: error: syntax error, unexpected end of file, expecting TO

Free format has no column 7 and its own continuation rules; see Reference Format Fixed and Free. In practice a long message is better built from named constants or with STRING, which keeps each source line short.

Figurative constants

A figurative constant is a reserved word that names a value: the compiler supplies as many characters as the context needs. It can appear wherever a literal can, unless the syntax forbids it. Singular and plural forms are interchangeable (SPACE and SPACES, ZERO, ZEROS, ZEROES), and for a five-character receiving field MOVE SPACE, MOVE SPACES and MOVE ALL SPACES all produce five blanks.

Constant Meaning Representations in Enterprise COBOL 6.5

ZERO, ZEROS, ZEROES

numeric zero, or one or more zero characters

alphanumeric zero characters by default; national zero when the context is national. The only figurative constant allowed where a numeric literal is required.

SPACE, SPACES

one or more blanks

alphanumeric, DBCS, national or UTF-8 space as the context requires.

HIGH-VALUE, HIGH-VALUES

the character with the highest collating position

alphanumeric X"FF" in EBCDIC; national NX"FFFF"; UTF-8 U+10FFFF. Do not convert it between data representations: conversion yields a substitution character.

LOW-VALUE, LOW-VALUES

the character with the lowest collating position

alphanumeric X"00" in EBCDIC; national NX"0000"; UTF-8 UX"00".

QUOTE, QUOTES

a quotation mark (option QUOTE) or an apostrophe (option APOST)

the same in national and UTF-8 contexts. It cannot replace the delimiters of a literal.

ALL literal

repeats the characters of the literal to fill the receiving item

the literal may be alphanumeric, DBCS, national, UTF-8, or another figurative constant (then ALL is only readability).

NULL, NULLS

a pointer, procedure-pointer, function-pointer, object reference or ADDRESS OF item holding no valid address

value zero; usable only where the syntax allows it.

symbolic character

a character defined in the SYMBOLIC CHARACTERS clause of SPECIAL-NAMES

always alphanumeric; usable in national or UTF-8 contexts where an implicit conversion is defined (a MOVE).

The length of a figurative constant is one character in contexts such as CALL, STOP, STRING and UNSTRING, and the size of the associated data item (or 1, whichever is greater) when it is associated with one, for example in a VALUE clause or a MOVE. It cannot be a function argument, except inside an arithmetic expression that is itself an argument. ALL literal cannot be used in CALL, INSPECT, INVOKE, STOP or STRING.

The program below exercises each of them on the Circulation book record from BOOKREC (the copybook is in Copybooks and REPLACE). Note that BAR-CHAR and TAB-CHAR come from the next section.

       IDENTIFICATION DIVISION.
       PROGRAM-ID. FIGURATIVE.
       ENVIRONMENT DIVISION.
       CONFIGURATION SECTION.
       SPECIAL-NAMES.
           SYMBOLIC CHARACTERS TAB-CHAR BAR-CHAR ARE 10 125.
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       COPY BOOKREC.
       01  WS-LINE             PIC X(30).
       01  WS-RULE             PIC X(12).
       01  WS-BYTES            PIC X(4).
       01  WS-PTR              USAGE POINTER.
       PROCEDURE DIVISION.
       MAIN-PARAGRAPH.
           MOVE SPACES TO BOOK-TITLE
           MOVE ZERO TO BOOK-COPIES BOOK-PRICE
           MOVE ALL "=-" TO WS-RULE
           DISPLAY "RULE:  " WS-RULE
           MOVE ALL "*" TO WS-LINE
           DISPLAY "STARS: " WS-LINE
           MOVE QUOTE TO WS-BYTES
           DISPLAY "QUOTE: " WS-BYTES
           DISPLAY "ZERO:  " BOOK-COPIES " " BOOK-PRICE
           MOVE HIGH-VALUES TO WS-BYTES
           DISPLAY "HIGH:  " FUNCTION HEX-OF(WS-BYTES)
           MOVE LOW-VALUES TO WS-BYTES
           DISPLAY "LOW:   " FUNCTION HEX-OF(WS-BYTES)
           MOVE BAR-CHAR TO WS-BYTES
           DISPLAY "BAR:   " WS-BYTES "|" TAB-CHAR "|"
           SET WS-PTR TO NULL
           IF WS-PTR = NULL
               DISPLAY "POINTER IS NULL"
           END-IF
           IF BOOK-TITLE = SPACES
               DISPLAY "TITLE IS BLANK"
           END-IF
           STOP RUN.
RULE:  =-=-=-=-=-=-
STARS: ******************************
QUOTE: """"
ZERO:  000 0000.00
HIGH:  FFFFFFFF
LOW:   00000000
BAR:   |||||    |
POINTER IS NULL
TITLE IS BLANK

Reading the output (the tab printed by TAB-CHAR is shown here as four spaces): ALL "=-" repeats the pair across the twelve-byte field, ALL "*" fills thirty positions, and QUOTE fills four bytes with the quotation mark. ZERO moved to BOOK-COPIES and BOOK-PRICE prints as 000 and 0000.00 (the decimal point is shown because GnuCOBOL’s DISPLAY edits the implied point of the price). HIGH-VALUES is FF and LOW-VALUES is 00 in every byte of an alphanumeric receiver, here displayed through HEX-OF. Comparing with SPACES and NULL is the idiomatic way to test for a blank field or an unset pointer.

Two notes about the values. HIGH-VALUES is the highest byte of the collating sequence, so on z/OS it is X"FF" and in an ASCII build it is also FF, but the comparison order of the other characters differs: in EBCDIC a digit sorts after a letter, in ASCII before it. A MOVE HIGH-VALUES TO key to mark end-of-file in a merge step therefore works in both, but sorted output may differ. And ZERO moved to an alphanumeric field gives the character "0", not the binary value zero, which is why MOVE ZERO TO WS-TEXT followed by an arithmetic use of that text is a pitfall that MOVE and Data Movement explains.

SPECIAL-NAMES symbolic characters

The SYMBOLIC CHARACTERS clause of the SPECIAL-NAMES paragraph (in the Environment Division’s CONFIGURATION SECTION) gives a name to a character by its ordinal position in the collating sequence. The name then behaves like a one-character figurative constant. The paragraph is introduced in Program Structure and Divisions.

       SPECIAL-NAMES.
           SYMBOLIC CHARACTERS TAB-CHAR BAR-CHAR ARE 10 125.

The number is a position counted from 1, not the character code. The output above shows it: TAB-CHAR (position 10) printed a tab, which is character code 9, and BAR-CHAR (position 125) printed |, which is character code 124. The same declaration with IN alphabet-name takes the position from a different collating sequence. The names are user-defined words, are always alphanumeric, and can be used in a VALUE clause, a MOVE, a comparison, or inside a literal list in EVALUATE. Using a symbolic character instead of X"09" documents intent and is portable to any code page.

Where the book is outdated

The book consulted for this section (Taulli, Modern Mainframe Development, 2022) treats figurative constants and the fixed-format rules as basics; nothing is copied from it. Where it, or any text written for compilers of the 1985 era, is read today, three points need a current reading:

  • The 30-character name limit is the 1985 value. It is still the Enterprise COBOL 6.5 limit, but COBOL 2023 allows 63 characters and GnuCOBOL’s default dialect uses 63, so a name that is rejected on z/OS may be accepted elsewhere, and the converse does not hold.

  • A fixed list of reserved words is only a snapshot. IBM and GnuCOBOL both have context-sensitive words and (in GnuCOBOL) options for changing the list, so whether a word is reserved depends on the compiler release, the dialect and the options.

  • Literals are not only quotation-mark strings. Enterprise COBOL 6.5 also has the Z, N, NX, U and UX forms with the limits quoted above, and the 2002 and later standards add boolean and national literals. Continuation with a hyphen in column 7 remains valid, but free format and STRING are the usual modern ways to build a long text.