Reading Acucobol program using another program

Good Afternoon All,

 

Can you please help me here i have been given a task to read a Cobol Program which contains several CALLING statements. these Calling statements include statements that call other programs since its a mainmenu it also calls other MENUs. now i am required to write a program that READS this program and print out all program CALLS for other programs and print them in an INDEXED file starting with MAINMENU (which is the program containing other programs).

 

now i have converted MAINMENU.cbl as text input file, please help me i cant get the program.

 

Best Regards

Zux

  • Hi Zux, do you know if the COBOL CALL statements occur in the same position. Let's say they all start in column 12. Then your FD would be 01 my-rec. 05 first-eleven pic x 11. 05 the-call-i-need pic x 60. You do a read for each line in the input file and then see if the-call-i-need is spaces .. if not, move the data in the-call-i-need to a different FD that is set up to be an Indexed file.

    If the calls are not in the same position in the input file, then you have a whole lot of more work to do, and for that type of string parsing, it might be best to use a different programming language, you could do it in COBOL, but it would be a lot of brute force trying to figure out where each call statement starts and where it ends.
  • Hi Shjerpe,

    Thanks for the suggestion yes these CALL statements are placed in different locations in the mainmenu. but let me try read those in the same sequence i will get back to you
  • If you are on linux it would be best to use bash. On windows use the dos find command or other string command. Since the calls may be in copybook too it would probably be best to use the listing instead. Likewise, the called program may
    be a variable name, so you'll have to determine if that is the case and handle it if it is. Call format may be
    CALL "[pgmname]" or CALL '[pgmname]' since cobol supports both single and double quotes. You will want to ignore all
    CALL "C$..." calls and any other microfocus supplied rtns.
  • If you are on linux it would be best to use bash. On windows use the dos find command or other string command. Since the calls may be in copybook too it would probably be best to use the listing instead. Likewise, the called program may
    be a variable name, so you'll have to determine if that is the case and handle it if it is. Call format may be
    CALL "[pgmname]" or CALL '[pgmname]' since cobol supports both single and double quotes. You will want to ignore all
    CALL "C$..." calls and any other microfocus supplied rtns.
  • While it's possible to do something like this using bash, it would be much more appropriate to use grep, awk, or perl, or another scripting language. There's little point in reinventing grep in bash.

    However, part of the OP's original question was to put the information into a COBOL indexed file. For that he'll need COBOL, so doing the scan with another language doesn't save much effort.

    And that said, this looks suspiciously like a homework assignment, so I suspect the question is not so much the best way to solve the problem, as how to solve it at all within what are probably rather arbitrary constraints.

    We don't have enough information to provide a very detailed answer (and if it's homework we shouldn't), but depending on the input I'd either approach this with UNSTRING or treat the input as line-sequential and write a simple lexer and parser. A bottom-up expect/accept parser is not a lot of work, even in traditional procedural COBOL. (My experience is with MF COBOL, but I assume ACU has UNSTRING and line-sequential files.)
  • Here is the basics of a program I have from a long, long time ago that does what you are looking to do. this is frm an OLD program, and is not the best. But it should give you some ideas.

    * read through the ProgramFile file and searcg the programs for
    * other calls to programs

    * you can just put mainmenu here, and

    FIND-PROG.
    FIND-PROG-CONT.

    MOVE 1 TO PRG-SUB.
    MOVE SPACES TO W-PRG-TABLE.
    MOVE "MAINMENU" TO W-PRG-NAME (PRG-SUB).

    PERFORM FIND-CALL THRU FIND-CALL-EXIT.

    FIND-PROG-EXIT.
    EXIT.



    FIND-CALL.
    IF PRG-SUB > 900 OR W-PRG-NAME (PRG-SUB) = SPACES
    GO TO FIND-CALL-END.

    * Look for program in source path. If not there, look in copy path.
    SET ENVIRONMENT "FILE-PREFIX" TO W-source-PATH.
    MOVE W-PRG-NAME (PRG-SUB) TO W-TEST-FILE-NAME.
    MOVE ZEROES TO INV-KEY-FLAG.
    MOVE SPACES TO OPEN-FILE-FLAG.
    CALL "p3ytest" USING W-TEST-FILE-NAME, INV-KEY-FLAG,
    OPEN-FILE-FLAG.
    IF INV-KEY-FLAG = 1
    SET ENVIRONMENT "FILE-PREFIX" TO CopyBook-PATH
    CALL "p3ytest" USING W-TEST-FILE-NAME, INV-KEY-FLAG
    OPEN-FILE-FLAG
    END-IF.

    * if program not found, skip it completey.
    IF INV-KEY-FLAG = 1
    GO TO FIND-CALL-NEXT.

    * Has the program already been searched (already in index file?
    MOVE W-PRG-NAME (PRG-SUB) TO JCLFLE-KEY.
    PERFORM READ-JCLFLE THRU READ-JCLFLE-EXIT.
    IF INV-KEY-FLAG = ZEROS
    GO TO FIND-CALL-NEXT.

    * Open the program source as ASCII sequential file
    MOVE W-PRG-NAME (PRG-SUB) TO W-SOURCE-NAME.
    OPEN INPUT PAYPRG.

    FIND-CALL-LINE.
    MOVE SPACES TO PAYPRG-REC.
    PERFORM READ-PAYPRG THRU READ-PAYPRG-EXIT.
    IF INV-KEY-FLAG = 1
    CLOSE PAYPRG
    GO TO FIND-CALL-NEXT.

    * Skip all coment lines. Only do if col 73 - 78 are blank
    IF PAYPRG-REC (7:1) = "*" AND
    PAYPRG-REC (73:3) = SPACES
    GO TO FIND-CALL-LINE.

    * Unstring line into 3 fields (CALL will be in one of 1st 3 fields)
    MOVE SPACES TO SUBFIELD1, SUBFIELD2, SUBFIELD3.
    UNSTRING PAYPRG-DATA DELIMITED BY ALL SPACES
    INTO SUBFIELD1, SUBFIELD2, SUBFIELD3.

    * Is the first data a COPY? (Need to search these also)
    IF (SUBFIELD1 = "COPY" OR "copy")
    MOVE SUBFIELD2 TO SUBPROG
    MOVE "C" TO W-TYPE
    ELSE
    * Is the first data a call? Item 2 is program name.
    IF (SUBFIELD1 = "CALL" OR "call")
    MOVE SUBFIELD2 TO SUBPROG
    MOVE "P" TO W-TYPE
    ELSE
    * Is 2nd field a Call? 3rd field is progam name
    IF (SUBFIELD2 = "CALL" OR "call")
    MOVE SUBFIELD3 TO SUBPROG
    MOVE "P" TO W-TYPE
    ELSE
    GO TO FIND-CALL-LINE.

    * Line is not a copybook nor a call statement. Get next line.
    IF SUBPROG = SPACES
    GO TO FIND-CALL-LINE.

    MOVE SPACES TO SUBFIELD1, SUBFIELD2.

    * Get rid of quotes
    INSPECT SUBPROG REPLACING ALL '"' BY " ".
    UNSTRING SUBPROG DELIMITED BY ALL SPACES
    INTO SUBFIELD1, SUBFIELD2.
    IF SUBFIELD1 NOT = SPACES
    MOVE SUBFIELD1 TO SUBPROG
    ELSE
    IF SUBFIELD2 NOT = SPACES
    MOVE SUBFIELD2 TO SUBPROG
    ELSE
    GO TO FIND-CALL-LINE.

    * Skip SYSTEM utility calls
    IF SUBPROG = "SYSTEM"
    GO TO FIND-CALL-LINE
    END-IF.

    * load the program name into the program table
    PERFORM, VARYING SUB FROM 1 BY 1 UNTIL SUB > 900 OR
    W-PRG-NAME (SUB) = SPACES OR
    W-PRG-NAME (SUB) = SUBPROG
    CONTINUE
    END-PERFORM

    IF SUB > 900 OR
    W-PRG-NAME (SUB) = SUBPROG
    CONTINUE
    ELSE
    MOVE SUBPROG TO W-PRG-NAME (SUB)
    MOVE W-TYPE TO W-PRG-TYPE (SUB)
    END-IF.

    * And get next program line.
    GO TO FIND-CALL-LINE.

    * Do same for the items we just loaded
    FIND-CALL-NEXT.
    ADD 1 TO PRG-SUB.
    GO TO FIND-CALL.

    * We have them all now. Write them to indexed work file
    FIND-CALL-END.
    PERFORM, VARYING SUB FROM 2 BY 1 UNTIL SUB > 900 OR
    W-PRG-NAME (SUB) = SPACES
    * We only want programs (skip copybooks)
    IF W-PRG-TYPE (SUB) = "P"
    MOVE W-PRG-NAME (SUB) TO JCLFLE-KEY
    PERFORM WRITE-JCLFLE THRU WRITE-JCLFLE-EXIT
    END-IF
    END-PERFORM.

    FIND-CALL-EXIT.
    EXIT.
  • Hi.

    I don't know if you alredy tried it, but for me you can do anything with a COBOL program:
    - Read the source as line sequential file
    - For each readed row, exclude anything that has an * on the 7th char. For this purpouse you can use something like that: IF MY-ROW(7:1) NOT = "*"
    - For each row see if you meet a call statement. For do that you can simply check for any " CALL " occurs or if the end of the row contains " CALL" (no spaces after it). It's quite simple using the mix of "INSPECT TALLYNG" COBOL statement (for the CALL inside the row) and justifying the row to the right and see if last 5 chars correspond to " CALL"
    - When you find where CALL is, you can move char by char and see what follows...


    I hope you understand what I mean
  • Hello Dale,

    thank you with this sample i managed to complete the program and its working fine.

    here below is how i managed to complete it.However its not complete enough i am struggling with the format of showing the output indexed file alphabetic.

    i am trying to use sort technic but it gives me errors.

    select NOT optional Main-ProgCall
    assign disk "CalledProgs"
    organization indexed
    access mode is dynamic
    file status cdmStatus
    record key cdmKey
    with no Duplicates.
    this is my declaration part.




    a100-Main.
    *----------

    open output Main-ProgCall.

    open input MainMenu-Input.

    if mmStatus > "02"
    move "Open input error on Mainmenu" to cdmRecord
    move mmStatus to cdmRecord
    write cdmRecord.
    move zeroes to countRec.
    perform a100-read thru a100-exit.

    a100-close.
    *-----------
    close
    Mainmenu-Input
    Main-ProgCall.


    a100-read.
    *----------
    move zeroes to CAll-COUNT.
    move zeroes to QouteMM.
    move zeroes to wsInvalidCall.

    read Mainmenu-Input next at end go to a100-close.
    if mmStatus > "02"
    go to a100-close.

    add 1 to countRec.

    * Skip commented parts.
    IF mmRecord(7:1)= "*"
    go to a100-read.

    * validate calls for menus
    INSPECT mmRecord Tallying wsInvalidCall for all
    wsMenu.

    if wsInvalidCall >= 1
    go to a100-read.


    *//// THIS IS WHERE YOU WILL FIND THE PROG THAT HAS BEEN CALLED
    INSPECT mmRecord TALLYING
    CALL-COUNT FOR ALL " call ".

    IF CALL-COUNT >= 1
    PERFORM a100-Search
    ELSE
    go to a100-read.

    a100-exit.
    exit.

    a100-Search.
    *------------
    INSPECT mmRecord Tallying
    QouteMM for all wsQoute.

    if QouteMM >= 1
    * Checking names in Double qoutes
    Perform get-Progname
    else
    go to a100-read.

    get-progname.
    *--------------
    * Retrieve program names and move to indexed file.
    unstring mmRecord delimited by wsQoute
    into wspart1,wspart2,wspart3.

    move wspart2 to cdmProgName.
    move "MAINMENU" TO cdmCallingProg.
    write cdmRecord.
    go to a100-read.


    **==============================================================*
  • Hello Dale,

    thank you with this sample i managed to complete the program and its working fine.

    here below is how i managed to complete it.However its not complete enough i am struggling with the format of showing the output indexed file alphabetic.

    i am trying to use sort technic but it gives me errors.

    select NOT optional Main-ProgCall
    assign disk "CalledProgs"
    organization indexed
    access mode is dynamic
    file status cdmStatus
    record key cdmKey
    with no Duplicates.
    this is my declaration part.




    a100-Main.
    *----------

    open output Main-ProgCall.

    open input MainMenu-Input.

    if mmStatus > "02"
    move "Open input error on Mainmenu" to cdmRecord
    move mmStatus to cdmRecord
    write cdmRecord.
    move zeroes to countRec.
    perform a100-read thru a100-exit.

    a100-close.
    *-----------
    close
    Mainmenu-Input
    Main-ProgCall.


    a100-read.
    *----------
    move zeroes to CAll-COUNT.
    move zeroes to QouteMM.
    move zeroes to wsInvalidCall.

    read Mainmenu-Input next at end go to a100-close.
    if mmStatus > "02"
    go to a100-close.

    add 1 to countRec.

    * Skip commented parts.
    IF mmRecord(7:1)= "*"
    go to a100-read.

    * validate calls for menus
    INSPECT mmRecord Tallying wsInvalidCall for all
    wsMenu.

    if wsInvalidCall >= 1
    go to a100-read.


    *//// THIS IS WHERE YOU WILL FIND THE PROG THAT HAS BEEN CALLED
    INSPECT mmRecord TALLYING
    CALL-COUNT FOR ALL " call ".

    IF CALL-COUNT >= 1
    PERFORM a100-Search
    ELSE
    go to a100-read.

    a100-exit.
    exit.

    a100-Search.
    *------------
    INSPECT mmRecord Tallying
    QouteMM for all wsQoute.

    if QouteMM >= 1
    * Checking names in Double qoutes
    Perform get-Progname
    else
    go to a100-read.

    get-progname.
    *--------------
    * Retrieve program names and move to indexed file.
    unstring mmRecord delimited by wsQoute
    into wspart1,wspart2,wspart3.

    move wspart2 to cdmProgName.
    move "MAINMENU" TO cdmCallingProg.
    write cdmRecord.
    go to a100-read.


    **==============================================================*