Command Line Subcommands in COBOL

Here’s the translation of the Go code to COBOL, presented in Markdown format suitable for Hugo:

Our first program demonstrates how to handle command-line subcommands. Here’s the full source code:

IDENTIFICATION DIVISION.
PROGRAM-ID. COMMAND-LINE-SUBCOMMANDS.

ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
    SELECT STANDARD-INPUT ASSIGN TO KEYBOARD.
    SELECT STANDARD-OUTPUT ASSIGN TO DISPLAY.

DATA DIVISION.
FILE SECTION.
FD STANDARD-INPUT.
01 STDIN-RECORD.
    05 STDIN-CHAR PIC X OCCURS 80 TIMES.

FD STANDARD-OUTPUT.
01 STDOUT-RECORD.
    05 STDOUT-CHAR PIC X OCCURS 80 TIMES.

WORKING-STORAGE SECTION.
01 WS-ARGS.
    05 WS-ARG-COUNT PIC 9(2) VALUE 0.
    05 WS-ARG-VALUES PIC X(20) OCCURS 10 TIMES.
01 WS-SUBCOMMAND PIC X(10).
01 WS-FOO-ENABLE PIC X VALUE 'N'.
01 WS-FOO-NAME PIC X(20).
01 WS-BAR-LEVEL PIC 9(3).

PROCEDURE DIVISION.
MAIN-PROCEDURE.
    PERFORM GET-COMMAND-LINE-ARGS
    IF WS-ARG-COUNT < 2 THEN
        DISPLAY "expected 'foo' or 'bar' subcommands"
        STOP RUN
    END-IF

    MOVE WS-ARG-VALUES(2) TO WS-SUBCOMMAND
    EVALUATE WS-SUBCOMMAND
        WHEN "foo"
            PERFORM HANDLE-FOO-SUBCOMMAND
        WHEN "bar"
            PERFORM HANDLE-BAR-SUBCOMMAND
        WHEN OTHER
            DISPLAY "expected 'foo' or 'bar' subcommands"
            STOP RUN
    END-EVALUATE
    
    STOP RUN.

GET-COMMAND-LINE-ARGS.
    ACCEPT WS-ARG-COUNT FROM ARGUMENT-NUMBER
    PERFORM VARYING WS-ARG-COUNT FROM 1 BY 1 
            UNTIL WS-ARG-COUNT > 10
        ACCEPT WS-ARG-VALUES(WS-ARG-COUNT) FROM ARGUMENT-VALUE
    END-PERFORM.

HANDLE-FOO-SUBCOMMAND.
    PERFORM PARSE-FOO-ARGS
    DISPLAY "subcommand 'foo'"
    DISPLAY "  enable: " WS-FOO-ENABLE
    DISPLAY "  name: " WS-FOO-NAME.

HANDLE-BAR-SUBCOMMAND.
    PERFORM PARSE-BAR-ARGS
    DISPLAY "subcommand 'bar'"
    DISPLAY "  level: " WS-BAR-LEVEL.

PARSE-FOO-ARGS.
    PERFORM VARYING WS-ARG-COUNT FROM 3 BY 1 
            UNTIL WS-ARG-COUNT > 10
        EVALUATE WS-ARG-VALUES(WS-ARG-COUNT)
            WHEN "--enable"
                MOVE 'Y' TO WS-FOO-ENABLE
            WHEN "--name"
                ADD 1 TO WS-ARG-COUNT
                MOVE WS-ARG-VALUES(WS-ARG-COUNT) TO WS-FOO-NAME
        END-EVALUATE
    END-PERFORM.

PARSE-BAR-ARGS.
    PERFORM VARYING WS-ARG-COUNT FROM 3 BY 1 
            UNTIL WS-ARG-COUNT > 10
        IF WS-ARG-VALUES(WS-ARG-COUNT) = "--level"
            ADD 1 TO WS-ARG-COUNT
            MOVE WS-ARG-VALUES(WS-ARG-COUNT) TO WS-BAR-LEVEL
        END-IF
    END-PERFORM.

In this COBOL program, we simulate the concept of subcommands by parsing command-line arguments manually. The program expects the first argument to be either “foo” or “bar”, which determines which subcommand to execute.

To compile and run the program:

$ cobc -x command-line-subcommands.cob
$ ./command-line-subcommands foo --enable --name=joe
subcommand 'foo'
  enable: Y
  name: joe

$ ./command-line-subcommands bar --level 8
subcommand 'bar'
  level: 008

Note that COBOL doesn’t have built-in support for command-line argument parsing like Go’s flag package. Instead, we manually parse the arguments in the PARSE-FOO-ARGS and PARSE-BAR-ARGS procedures.

Also, COBOL doesn’t have a direct equivalent to Go’s flag.NewFlagSet. Instead, we use separate procedures to handle different subcommands and their respective arguments.

COBOL’s syntax and structure are quite different from Go, but the core logic of handling different subcommands based on the first argument remains the same.