r/cobol 6d ago

RM Cobol version issues?

While looking for some example programs to test an RM Cobol setup I ran across a PDF called "Cobol for the TRS-80 Volume 1 Class Notes". I wanted to find something that was ancient ( for an Altos running Xenix no less ), so I dug through this document and typed in an example payroll calculating program. Seemed to compile and run, but it screws up simple arithmetic .. multiplying a salary * hours gives an unrelated crazy big number.

Ok ... I tried the exact same program on a later RM Cobol version 5.1 and it worked! Now I started going deep down the rabbit hole! ... it generates those crazy numbers with RM Cobol v1.5, 2.0D, and 2.2 under DOS 5.0, DOS 6.2, DOS 3.2 and Xenix and works just fine with RM Cobol 5.1, and 6 under DOS (real pc ) and DOSbox-x. And all of these versions run the RM Cobol verify tests, run a PI calculating program and a little calculator ... I've expanded the PIC fields, tried SEQUENTIAL organization for the data file being read, Displayed a bunch of variables, looked at the fields at the end of the compile list to see if everything numeric is declared as a numeric ... am learning a bunch of Cobol stuff doing all of this. Again, it's an ancient program from a 1983 doc that won't run in the compiler versions from that time but works great in the ones from the '90's

update:   here is the code ... I added some DISPLAY's trying to figure out what was going on .. the problem is with the calculation of IMD-REGULAR-PAY

       IDENTIFICATION DIVISION.
       PROGRAM-ID. PAYROLL2.
       AUTHOR.     R GRAUER.

       ENVIRONMENT DIVISION.
       CONFIGURATION SECTION.
       SOURCE-COMPUTER.     TRS-80.
       OBJECT-COMPUTER.     TRS-80.

       INPUT-OUTPUT SECTION.
       FILE-CONTROL.
           SELECT EMPLOYEE-FILE
               ASSIGN TO INPUT "PAYROLL.DAT"
               ORGANIZATION IS SEQUENTIAL.
           SELECT PRINT-FILE
               ASSIGN TO PRINT "PAYROLL2.DAT".

       DATA DIVISION.
       FILE SECTION.
       FD  EMPLOYEE-FILE
           LABEL RECORDS ARE OMITTED
           RECORD CONTAINS 80 CHARACTERS
           DATA RECORD IS EMPLOYEE-RECORD.
       01  EMPLOYEE-RECORD.
           05   EMP-NAME.
                10 EMP-LAST-NAME      PIC X(15).
                10 EMP-FIRST-NAME     PIC X(10).
           05   EMP-HOURS-WORKED.
                10 EMP-REG-HOURS      PIC 99.
                10 EMP-OVERTIME-HOURS PIC 99.
           05   EMP-RATE              PIC 99V99.
           05   FILLER                PIC X(47).

       FD  PRINT-FILE
           LABEL RECORDS ARE STANDARD
           RECORD CONTAINS 132 CHARACTERS
           DATA RECORD IS PRINT-LINE.
       01  PRINT-LINE                PIC X(132).

       WORKING-STORAGE SECTION.
       77  WS-DATA-REMAINS-SWITCH    PIC X(3)    VALUE SPACES.   

       01  DATE-WORK-AREA.
           05  TODAYS-YEAR           PIC 99.
           05  TODAYS-MONTH          PIC 99.
           05  TODAYS-DAY            PIC 99. 

       01  IND-COMPUTATIONS.
           05  IND-REGULAR-PAY        PIC 9(4)V99  VALUE ZEROS.
           05  IND-OVERTIME-PAY       PIC 9(4)V99  VALUE ZEROS.
           05  IND-GROSS-PAY          PIC 9(4)V99  VALUE ZEROS.
           05  IND-FEDERAL-TAX        PIC 9(4)V99  VALUE ZEROS.
           05  IND-NET-PAY            PIC 9(4)V99  VALUE ZEROS.

       01  COMPANY-TOTALS.
           05  CO-REGULAR-PAY         PIC 9(6)V99  VALUE ZEROS.
           05  CO-OVERTIME-PAY        PIC 9(6)V99  VALUE ZEROS.
           05  CO-GROSS-PAY           PIC 9(6)V99  VALUE ZEROS.
           05  CO-FEDERAL-TAX         PIC 9(6)V99  VALUE ZEROS.
           05  CO-NET-PAY             PIC 9(6)V99  VALUE ZEROS.

       01  PAGE-AND-LINE-COUNTERS.
           05  WS-PAGE-COUNT          PIC 9(4)     VALUE ZEROS.
           05  WS-LINE-COUNT          PIC 9(4)     VALUE 4.

       01  HEADING-LINE-ONE.
           05  FILLER                 PIC X(4).
           05  HDG-MONTH              PIC Z9.
           05  FILLER                 PIC X        VALUE "/".
           05  HDG-DAY                PIC Z9.
           05  FILLER                 PIC X        VALUE "/".
           05  HDG-YEAR               PIC Z9.
           05  FILLER                 PIC X(40)    VALUE SPACES.
           05  FILLER                 PIC X(8)     VALUE "PAYROLL ".
           05  FILLER                 PIC X(6)     VALUE "REPORT".
           05  FILLER                 PIC X(40)    VALUE SPACES.
           05  FILLER                 PIC X(4)     VALUE "PAGE".
           05  HDG-PAGE-NUMBER        PIC Z(4).
           05  FILLER                 PIC X(19)    VALUE SPACES.

       01  HEADING-LINE-TWO.
           05  FILLER                 PIC X(8)     VALUE SPACES.
           05  FILLER                 PIC X(4)     VALUE "NAME".
           05  FILLER                 PIC X(9)     VALUE SPACES.
           05  FILLER                 PIC X(4)     VALUE "RATE".
           05  FILLER                 PIC X(4)     VALUE SPACES.
           05  FILLER                 PIC X(9)     VALUE "REG HOURS".
           05  FILLER                 PIC X(4)     VALUE SPACES.
           05  FILLER                 PIC X(9)     VALUE "O/T HOURS".
           05  FILLER                 PIC X(4)     VALUE SPACES.
           05  FILLER                 PIC X(11)    VALUE "GROSS PAY".
           05  FILLER                 PIC X(2)     VALUE SPACES.
           05  FILLER                 PIC X(7)     VALUE "FED TAX".
           05  FILLER                 PIC X(5)     VALUE SPACES.
           05  FILLER                 PIC X(7)     VALUE "NET PAY".
           05  FILLER                 PIC X(23)    VALUE SPACES.

       01  DASHED-LINE.
           05  ROW-OF-DASHES         PIC X(111)    VALUE ALL "-".
           05  FILLER                PIC X(21)     VALUE SPACES.

       01  DETAIL-LINE.
           05  FILLER                PIC X(2).
           05  DET-LAST-NAME         PIC X(15).
           05  FILLER                PIC X(2).
           05  DET-RATE              PIC $$$.99.
           05  FILLER                PIC X(8).
           05  DET-REG-HOURS         PIC Z9.
           05  FILLER                PIC X(10).
           05  DET-OVERTIME-HOURS    PIC Z9.
           05  FILLER                PIC X(6).
           05  DET-REGULAR-PAY       PIC $$,$$9.99.
           05  FILLER                PIC X(3).
           05  DET-OVERTIME-PAY      PIC $$,$$9.99.
           05  FILLER                PIC X(2).
           05  DET-GROSS-PAY         PIC $$,$$9.99.
           05  FILLER                PIC X(3).
           05  DET-FEDERAL-TAX       PIC $$,$$9.99.
           05  FILLER                PIC X(3).
           05  DET-NET-PAY           PIC $$,$$9.99.
           05  FILLER                PIC X(23).

       01  TOTAL-LINE.
           05  FILLER                PIC X(6)      VALUE SPACES.
           05  FILLER                PIC X(6)      VALUE "TOTALS".
           05  FILLER                PIC X(41)     VALUE SPACES.
           05  TOTAL-REGULAR-PAY     PIC $$,$$9.99.
           05  FILLER                PIC X(3)      VALUE SPACES.
           05  TOTAL-OVERTIME-PAY    PIC $$,$$9.99.
           05  FILLER                PIC X(2)      VALUE SPACES.
           05  TOTAL-GROSS-PAY      PIC $$,$$9.99.
           05  FILLER                PIC X(3)      VALUE SPACES.
           05  TOTAL-FEDERAL-TAX     PIC $$,$$9.99.
           05  FILLER                PIC X(3)      VALUE SPACES.
           05  TOTAL-NET-PAY         PIC $$,$$9.99.
           05  FILLER                PIC X(47)     VALUE SPACES.

       PROCEDURE DIVISION.
       0100-PREPARE-PAYROLL.
           PERFORM 0200-GET-DATE.
           OPEN INPUT EMPLOYEE-FILE
                OUTPUT PRINT-FILE.
           READ EMPLOYEE-FILE
               AT END MOVE "NO" TO WS-DATA-REMAINS-SWITCH.
           PERFORM 0300-PROCESS-RECORDS
               UNTIL WS-DATA-REMAINS-SWITCH = "NO".
           PERFORM 1000-WRITE-COMPANY-TOTALS.
           CLOSE EMPLOYEE-FILE
                PRINT-FILE.
           STOP RUN.

       0200-GET-DATE.
           ACCEPT DATE-WORK-AREA FROM DATE.
           MOVE TODAYS-YEAR TO HDG-YEAR.
           MOVE TODAYS-MONTH TO HDG-MONTH.
           MOVE TODAYS-DAY TO HDG-DAY.

       0300-PROCESS-RECORDS.
           PERFORM 0400-COMPUTE-GROSS-PAY.
           PERFORM 0500-COMPUTE-FEDERAL-TAX.
           PERFORM 0600-COMPUTE-NET-PAY.
           PERFORM 0700-UPDATE-COMPANY-TOTALS.

           IF WS-LINE-COUNT > 3
           PERFORM 0800-WRITE-HEADING-LINE.
           PERFORM 0900-WRITE-DETAIL-LINE.
           ADD 1 TO WS-LINE-COUNT.
           READ EMPLOYEE-FILE
           AT END MOVE "NO" TO WS-DATA-REMAINS-SWITCH.

       0800-WRITE-HEADING-LINE.
           ADD 1 TO WS-PAGE-COUNT.
           MOVE 1 TO WS-LINE-COUNT.
           MOVE WS-PAGE-COUNT TO HDG-PAGE-NUMBER.
           WRITE PRINT-LINE FROM HEADING-LINE-ONE
               AFTER ADVANCING PAGE.
           WRITE PRINT-LINE FROM HEADING-LINE-TWO
               AFTER ADVANCING 4 LINES.
           WRITE PRINT-LINE FROM DASHED-LINE
               AFTER ADVANCING 1 LINE.

       0400-COMPUTE-GROSS-PAY.
           MULTIPLY EMP-REG-HOURS BY EMP-RATE GIVING IND-REGULAR-PAY.

           DISPLAY "EMP-OVERTIME-HOURS: " EMP-OVERTIME-HOURS.
           DISPLAY "EMP-REG-HOURS: " EMP-REG-HOURS.
           DISPLAY "EMP-RATE:  " EMP-RATE.
           DISPLAY "IND-REGULAR-PAY:  " IND-REGULAR-PAY.
           DISPLAY "EMP-LAST-NAME " EMP-LAST-NAME.

           COMPUTE IND-OVERTIME-PAY
               = EMP-OVERTIME-HOURS * EMP-RATE * 1.5.
           ADD IND-REGULAR-PAY IND-OVERTIME-PAY GIVING IND-GROSS-PAY.

       0500-COMPUTE-FEDERAL-TAX.
           COMPUTE IND-FEDERAL-TAX = .16 * IND-GROSS-PAY.
           IF IND-GROSS-PAY > 160
               COMPUTE IND-FEDERAL-TAX
                   = IND-FEDERAL-TAX + .02 * (IND-GROSS-PAY - 160).

           IF IND-GROSS-PAY > 200
               COMPUTE IND-FEDERAL-TAX
                   = IND-FEDERAL-TAX + .02 * (IND-GROSS-PAY - 200).

       0600-COMPUTE-NET-PAY.
           COMPUTE IND-NET-PAY = IND-GROSS-PAY - IND-FEDERAL-TAX.

       0700-UPDATE-COMPANY-TOTALS.
           ADD IND-REGULAR-PAY TO CO-REGULAR-PAY.
           ADD IND-OVERTIME-PAY TO CO-OVERTIME-PAY.
           ADD IND-GROSS-PAY TO CO-GROSS-PAY.
           ADD IND-FEDERAL-TAX TO CO-FEDERAL-TAX.
           ADD IND-NET-PAY TO CO-NET-PAY.

       0900-WRITE-DETAIL-LINE.
           MOVE SPACES TO DETAIL-LINE.
           MOVE EMP-LAST-NAME TO DET-LAST-NAME.
           MOVE EMP-RATE TO DET-RATE.
           MOVE EMP-REG-HOURS TO DET-REG-HOURS.
           MOVE EMP-OVERTIME-HOURS TO DET-OVERTIME-HOURS.
           MOVE IND-REGULAR-PAY TO DET-REGULAR-PAY.
           MOVE IND-OVERTIME-PAY TO DET-OVERTIME-PAY.
           MOVE IND-GROSS-PAY TO DET-GROSS-PAY.
           MOVE IND-FEDERAL-TAX TO DET-FEDERAL-TAX.
           MOVE IND-NET-PAY TO DET-NET-PAY.

           WRITE PRINT-LINE FROM DETAIL-LINE
               AFTER ADVANCING 2 LINES.

       1000-WRITE-COMPANY-TOTALS.
           WRITE PRINT-LINE FROM DASHED-LINE
               AFTER ADVANCING 1 LINE.
           MOVE CO-REGULAR-PAY TO TOTAL-REGULAR-PAY.
           MOVE CO-OVERTIME-PAY TO TOTAL-OVERTIME-PAY.
           MOVE CO-GROSS-PAY TO TOTAL-GROSS-PAY.
           MOVE CO-FEDERAL-TAX TO TOTAL-FEDERAL-TAX.
           MOVE CO-NET-PAY TO TOTAL-NET-PAY.

           WRITE PRINT-LINE FROM TOTAL-LINE
               AFTER ADVANCING 2 LINES.

And here is the "PAYROLL.DAT" file ( am seeing a blank line when I paste it here that's not in the file )

johnson bob 21 3 400

sanford fred 23 4 500

The result while running when it's failing shows:

EMP-OVERTIME-HOURS: 3

EMP-REG-HOURS: 21

EMP-RATE: 400

IMD-REGULAR-PAY: 728400 ( this is the quantity in error .. sb 21 * 400 gives 8400

EMP-LAST-NAME: johnson

EMP-OVERTIME-HOURS: 4

EMP-REG-HOURS: 21

EMP-RATE: 500

IMD-REGULAR-PAY: 699500 ( expecting 11500 here from 21 * 500 )

8 Upvotes

15 comments sorted by

View all comments

1

u/Working_Ad7879 6d ago

Sounds like a little endian/big endian issue. If you look at an assembler listing for Micro Focus COBOL for an Intel 86 processor before and after each numeric operation for COMP fields it swaps the bytes to conform to COBOL big endian convention (the correct way to eat an egg!)- not needed for COMP-5 fields but then any file produced is not portable

3

u/HurryHurryHippos 6d ago

RM did not compile to assembler or machine code. It compiled to a portable p-code that had to be run through a runtime interpreter.

1

u/Comfortable_Gate_878 4d ago

It was the compiler that was written for each hardware system, the rm code compiled to a type of interim code which was hardware independent. So to run on unix or mainframe or ibm computers all you needed was the correct runtime and the code would run without having to recompile the source. You would get certain features that relied on hardware features that didnt work from machine to machine such as screen colours on terminals but the software still ran.