      ******************************************************************
      * Author:
      * Date:
      * Purpose:
      * Tectonics: cobc
      ******************************************************************
       IDENTIFICATION DIVISION.
       PROGRAM-ID. RECURSION.
       ENVIRONMENT DIVISION.
       INPUT-OUTPUT SECTION.
       FILE-CONTROL.
       SELECT OPTIONAL CALL-STACK ASSIGN TO "stack.dat"
         ORGANIZATION IS INDEXED
         ACCESS IS RANDOM
         RECORD KEY IS COMMAND-ID.
       DATA DIVISION.
       FILE SECTION.
       FD CALL-STACK.
       01 CALL-STACK-FILE.
           02 COMMAND-ID PIC 9(5).
           02 COMMAND-NAME PIC X(20).
           02 COMMAND-RESULT PIC X(20).
           02 COMMAND-RESULT-NUMERIC
             REDEFINES COMMAND-RESULT PIC 9(20).
           02 COMMAND-RETURN-ID PIC 9(5).
           02 COMMAND-RETURNS-RESULT PIC X.
             88 COMMAND-RETURNS-RESULT-YES VALUE 'Y', FALSE 'N'.
       WORKING-STORAGE SECTION.
       01 WS-CALL-STACK-FILE-STATUS PIC X.
           88 WS-CALL-STACK-FILE-STATUS-OPEN VALUE 'Y', FALSE 'N'.
       01 WS-CALL-STACK.
           02 WS-COMMAND-ID PIC 9(5).
           02 WS-COMMAND-NAME PIC X(20).
           02 WS-COMMAND-RESULT PIC X(20).
           02 WS-COMMAND-RESULT-NUMERIC
             REDEFINES WS-COMMAND-RESULT PIC 9(20).
           02 WS-COMMAND-RETURN-ID PIC 9(5).
           02 WS-COMMAND-RETURN-VALUE PIC X(20).
           02 WS-COMMAND-RETURNS-RESULT PIC X.
               88 WS-COMMAND-RETURNS-RESULT-YES VALUE 'Y', FALSE 'N'.
       01 WS-CALL-STACK-EOF PIC A(1).
       01 WS-CALL-STACK-NEXT-ID PIC 9(5).
       01 WS-IS-LAST-EXPRESSION PIC X.
           88 WS-IS-LAST-EXPRESSION-YES VALUE 'Y', FALSE 'N'.
       01 WS-RETURN.
           02 WS-RETURN-VALUE PIC X(20).
           02 WS-RETURN-VALUE-NUMERIC PIC 9(20).
       01 WS-STACK-STATUS.
           02 WS-LAST-ID PIC 9(5).
           02 WS-OLDEST-ID PIC 9(5).
           02 WS-STACK-IS-EMPTY PIC X.
               88 WS-STACK-IS-EMPTY-YES VALUE 'Y', FALSE 'N'.
      *****************************************
      *    WS Shared with LOGGER SubRoutine
      *****************************************
           01 WS-LOG-OPERATION-FLAG PIC X(5).
           01 WS-LOG-RECORD.
               02 WS-LOG-RECORD-FUNCTION-NAME PIC X(40).
               02 WS-LOG-RECORD-MESSAGE PIC X(100).
       LINKAGE SECTION.
       01 LS-RECURSION-FLAG PIC X(30).
       01 LS-RECURSION-OBJECT.
          02 LS-COMMAND-NAME PIC X(20).
          02 LS-COMMAND-RESULT PIC X(20).
          02 LS-COMMAND-RESULT-NUMERIC
          REDEFINES LS-COMMAND-RESULT PIC 9(20).
          02 LS-COMMAND-RETURNS-RESULT PIC X.
             88 LS-COMMAND-RETURNS-RESULT-YES VALUE 'Y', FALSE 'N'.
       PROCEDURE DIVISION USING LS-RECURSION-FLAG, LS-RECURSION-OBJECT.
       MAIN-PROCEDURE.
           EVALUATE LS-RECURSION-FLAG
           WHEN "INIT"
               PERFORM INIT-CALL-STACK-PROCEDURE
               PERFORM LOG-INIT-CALL-STACK
           WHEN "ADD-TO-CALL-STACK"
               PERFORM CALL-STACK-ADD-PROCEDURE
               PERFORM LOG-ADD-TO-CALL-STACK
           WHEN "PEEK"
               PERFORM CALL-STACK-GET-TOP-PROCEDURE
               PERFORM LOG-PEEK-CALL-STACK
           WHEN "POP-CALL-STACK"
               PERFORM LOG-POP-FROM-CALL-STACK
               PERFORM POP-CALL-STACK-PROCEDURE
           WHEN "IS-EMPTY"
               PERFORM IS-STACK-EMPTY-PROCEDURE
               PERFORM LOG-IS-EMPTY-CALL-STACK
           WHEN "PRINT-CALL-STACK"
               PERFORM PRINT-CALL-STACK-PROCEDURE
           WHEN "CLOSE"
               PERFORM CLOSE-CALL-STACK-PROCEDURE
               PERFORM LOG-CLOSE-CALL-STACK
           WHEN "STACK-FILE-STATUS"
               PERFORM CHECK-FILE-STATUS-PROCEDURE.
           GOBACK.
       LOG-INIT-CALL-STACK.
           MOVE "ADD" TO WS-LOG-OPERATION-FLAG.
           MOVE "RECURSION:INIT" TO WS-LOG-RECORD-FUNCTION-NAME.
           MOVE "Initialized Call Stack" TO WS-LOG-RECORD-MESSAGE.
           CALL 'LOGGER' USING WS-LOG-OPERATION-FLAG, WS-LOG-RECORD.
       LOG-ADD-TO-CALL-STACK.
      *******logging Adding to CALL-STACK
           MOVE 'RECURSION:ADD-TO-CALL-STACK'
           TO WS-LOG-RECORD-FUNCTION-NAME.
           STRING COMMAND-ID DELIMITED BY SIZE
           COMMAND-NAME DELIMITED BY SIZE
           COMMAND-RETURN-ID DELIMITED BY SIZE
           INTO WS-LOG-RECORD-MESSAGE.
           MOVE "ADD" TO WS-LOG-OPERATION-FLAG.
           CALL 'LOGGER' USING WS-LOG-OPERATION-FLAG, WS-LOG-RECORD.
       LOG-PEEK-CALL-STACK.
      *******logging Adding to CALL-STACK
           MOVE 'RECURSION:GET-TOP-CALL-STACK'
           TO WS-LOG-RECORD-FUNCTION-NAME.
           STRING COMMAND-ID DELIMITED BY SIZE
           COMMAND-NAME DELIMITED BY SIZE
           COMMAND-RETURN-ID DELIMITED BY SIZE
           INTO WS-LOG-RECORD-MESSAGE.
           MOVE "ADD" TO WS-LOG-OPERATION-FLAG.
           CALL 'LOGGER' USING WS-LOG-OPERATION-FLAG, WS-LOG-RECORD.
       LOG-POP-FROM-CALL-STACK.
           MOVE 'RECURSION:POP-CALL-STACK'
           TO WS-LOG-RECORD-FUNCTION-NAME.
           STRING COMMAND-ID DELIMITED BY SIZE
           COMMAND-NAME DELIMITED BY SIZE
           COMMAND-RETURN-ID DELIMITED BY SIZE
           INTO WS-LOG-RECORD-MESSAGE.
           MOVE "ADD" TO WS-LOG-OPERATION-FLAG.
           CALL 'LOGGER' USING WS-LOG-OPERATION-FLAG, WS-LOG-RECORD.
       LOG-IS-EMPTY-CALL-STACK.
           MOVE 'RECURSION:IS-EMPTY-CALL-STACK'
           TO WS-LOG-RECORD-FUNCTION-NAME.
           MOVE WS-STACK-IS-EMPTY TO WS-LOG-RECORD-MESSAGE.
           MOVE "ADD" TO WS-LOG-OPERATION-FLAG.
           CALL 'LOGGER' USING WS-LOG-OPERATION-FLAG, WS-LOG-RECORD.
       LOG-CLOSE-CALL-STACK.
      *******logging Adding to CALL-STACK
           MOVE 'RECURSION:CLOSE-CALL-STACK'
           TO WS-LOG-RECORD-FUNCTION-NAME.
           MOVE "Closed call-stack file" TO WS-LOG-RECORD-MESSAGE.
           MOVE "ADD" TO WS-LOG-OPERATION-FLAG.
           CALL 'LOGGER' USING WS-LOG-OPERATION-FLAG, WS-LOG-RECORD.
       LOG-DELETE-FROM-CALL-STACK.
      *******logging Deleting from CALL-STACK
           MOVE 'RECURSION:DELETE-FROM-CALL-STACK'
           TO WS-LOG-RECORD-FUNCTION-NAME.
           STRING COMMAND-ID DELIMITED BY SIZE
           COMMAND-NAME DELIMITED BY SIZE
           COMMAND-RETURN-ID DELIMITED BY SIZE
           INTO WS-LOG-RECORD-MESSAGE.
           MOVE "ADD" TO WS-LOG-OPERATION-FLAG.
           CALL 'LOGGER' USING WS-LOG-OPERATION-FLAG, WS-LOG-RECORD.
       INIT-CALL-STACK-PROCEDURE.
      * Preventing the error of something already being in the
      * stack file after a system crash
           OPEN OUTPUT CALL-STACK.
           CLOSE CALL-STACK.

      * Actually opening the call-stack for writing.
           OPEN I-O CALL-STACK.
           MOVE 1 TO WS-CALL-STACK-NEXT-ID.
           MOVE 1 TO WS-OLDEST-ID.
           MOVE 1 TO WS-LAST-ID.
           SET WS-STACK-IS-EMPTY-YES TO TRUE.
           SET WS-CALL-STACK-FILE-STATUS-OPEN TO TRUE.
       CLOSE-CALL-STACK-PROCEDURE.
           CLOSE CALL-STACK.
           DELETE FILE CALL-STACK.
           SET WS-CALL-STACK-FILE-STATUS-OPEN TO FALSE.
       CALL-STACK-ADD-PROCEDURE.
           MOVE WS-CALL-STACK-NEXT-ID TO COMMAND-ID.
           MOVE LS-COMMAND-NAME TO COMMAND-NAME.
           MOVE LS-COMMAND-RESULT TO COMMAND-RESULT.
           MOVE LS-COMMAND-RETURNS-RESULT TO COMMAND-RETURNS-RESULT.
           MOVE WS-LAST-ID TO COMMAND-RETURN-ID.
           WRITE CALL-STACK-FILE.
           IF WS-STACK-IS-EMPTY-YES THEN
               MOVE WS-CALL-STACK-NEXT-ID TO WS-OLDEST-ID
               SET WS-STACK-IS-EMPTY-YES TO FALSE
           END-IF.
           MOVE WS-CALL-STACK-NEXT-ID TO WS-LAST-ID.
           ADD 1 TO WS-CALL-STACK-NEXT-ID.
       PRINT-CALL-STACK-PROCEDURE.
           DISPLAY "PRINT-CALL-STACK-PROCEDURE".
           DISPLAY "ID    "
           "NAME                  "
           "RESULT              " "RESULT (NUMERIC)    "
           " RETURN ID    ".
           PERFORM VARYING COMMAND-ID FROM 1 BY 1
           UNTIL COMMAND-ID = WS-CALL-STACK-NEXT-ID
               READ CALL-STACK RECORD INTO WS-CALL-STACK
                   KEY IS COMMAND-ID
                   INVALID KEY DISPLAY "DELETED"
               END-READ
               DISPLAY WS-COMMAND-ID " " WS-COMMAND-NAME
               " " WS-COMMAND-RESULT " " WS-COMMAND-RESULT-NUMERIC " "
               WS-COMMAND-RETURN-ID " " WS-COMMAND-RETURN-VALUE " "
               WS-COMMAND-RETURNS-RESULT
           END-PERFORM.
       CALL-STACK-GET-TOP-PROCEDURE.
           MOVE WS-LAST-ID TO COMMAND-ID.
           READ CALL-STACK RECORD
               KEY IS COMMAND-ID
           END-READ.
           MOVE COMMAND-NAME TO LS-COMMAND-NAME.
           MOVE COMMAND-RESULT TO LS-COMMAND-RESULT.
       POP-CALL-STACK-PROCEDURE.
           MOVE WS-LAST-ID TO COMMAND-ID.
      D     DISPLAY "FROM POP-CALL-STACK-PROCEDURE:" COMMAND-ID.

           READ CALL-STACK RECORD.
           MOVE COMMAND-NAME TO LS-COMMAND-NAME.
           MOVE COMMAND-RESULT TO LS-COMMAND-RESULT.
           MOVE COMMAND-RETURN-ID TO WS-LAST-ID.
           DELETE CALL-STACK RECORD.
           IF COMMAND-ID = WS-OLDEST-ID THEN
               SET WS-STACK-IS-EMPTY-YES TO TRUE
           END-IF.
      D     DISPLAY "DELETED:" COMMAND-ID " GOTO:" WS-LAST-ID.
           DISPLAY " ".
       IS-STACK-EMPTY-PROCEDURE.
           IF WS-STACK-IS-EMPTY-YES THEN
               MOVE "STACK-EMPTY" TO LS-RECURSION-FLAG
           ELSE
               MOVE "NOT-EMPTY" TO LS-RECURSION-FLAG
           END-IF.
       CHECK-FILE-STATUS-PROCEDURE.
           MOVE WS-CALL-STACK-FILE-STATUS TO LS-RECURSION-FLAG.
       END PROGRAM RECURSION.
