ocdoc.cob usage guide

Author:Brian Tiffin
Date:30-Sep-2008
Rights:Copyright (c) 2008, Brian Tiffin. GNU FDL License.
Purpose:Extract usage document lines from COBOL sources. Using OpenCOBOL 1.1pr. OpenCOBOL is tasty.
Tectonics:cobc -x ocdoc.cob

Command line

ocdoc runs in two forms.

Without arguments, ocdoc will act as a pipe filter. Reading from standard in and writing the extract to standard out.

The ocdoc command also takes an input file, an extract filename, an optional result file (with optional stylesheet) and a verbosity option -v or a special -fixed flag (to force skipping sequence numbers). If a result file is given, ocdoc will automatically run an rst2html command using the SYSTEM service.

Due to an overly simplistic argument handler, you can only turn on verbosity or -fixed when using all four filenames.

Examples:

$ cat ocdoc.cob | ocdoc >ocdoc.rst
$ ./ocdoc ocdoc.cob ocdoc.rst
$ ./ocdoc ocdoc.cob ocdoc.rst ocdoc.html skin.css -fixed
...
Input  : ocdoc.cob
Output : ocdoc.rst
Command: rst2html --stylesheet=skin.css ocdoc.rst ocdoc.html

What is extracted

Source code

Download ocdocseq.cob

identification division

008500 identification division.
008600 program-id. OCDOC.
008700
008800 environment division.
008900 input-output section.
009000 file-control.
009100     select standard-input assign to KEYBOARD.
009200     select standard-output assign to DISPLAY.
009300
009400     select source-input
009500     assign to source-name
009600     organization is line sequential
009700     .
009800     select doc-output
009900     assign to doc-name
010000     organization is line sequential
010100     .

data division

011100 data division.
011200 file section.
011300 fd standard-input.
011400    01 stdin-record      pic x(256).
011500 fd standard-output.
011600    01 stdout-record     pic x(256).
011700
011800 fd source-input.
011900    01 source-record     pic x(256).
012000 fd doc-output.
012100    01 doc-record        pic x(256).
012200
012300 working-storage section.
012400 01 arguments            pic x(256).
012500 01 source-name          pic x(256).
012600 01 doc-name             pic x(256).
012700 01 result-name          pic x(256).
012800 01 style-name           pic x(256).
012900 01 verbosity            pic x(9).
013000    88 verbose           values "-v" "--v" "-verbose" "--verbose".
013100    88 skipseqnum        values "-fix" "-fixed" "--fix" "--fixed".
013200 01 usagehelp            pic x(6).
013300    88 helping           values "-h" "--h" "-help" "--help".
013400 01 filter-flag          pic x value low-value.
013500    88 filtering         value high-value.
013600
013700 01 line-count           usage binary-long.
013800 01 line-display         pic z(8)9.
013900

Note the conditional test for end of here doc

014700 01 trimmed              pic x(256).
014800    88 herestart         value "*><[".
014900    88 hereend           value "*><]".
015000
015100 01 hereflag             pic x value low-value.
015200    88 heredoc           value high-value.
015300    88 herenone          value low-value.
015400

Note the here-record adds an ocdoc extract to lines that follow.

016300 01 here-record.
016400    02 filler            pic x(5) value "*><* ".
016500    02 here-data         pic x(251).
016600
016700 01 seq-record.
016800    02 filler            pic x(7) value "       ".
016900    02 seq-data          pic x(249).
017000
017100 01 doc-buffer           pic x(256).
017200 01 buffer-offset        pic 999 usage comp-5 value 1.
017300 01 buffer-flag          pic x value low-value.
017400    88 buffer-empty      value low-value.
017500    88 buffered-output   value high-value.
017600
017700 01 counter              pic 999 usage comp-5.
017800 01 len-of-comment       pic 999 usage comp-5.
017900
018000 01 first-part           pic x(8).
018100    88 special           values "*><*" "*><+".
018200    88 autodoc           value "*><*".
018300    88 autoappend        value "*><+".
018400
018500 01 rst-command          pic x(256).
018600 01 result               usage binary-long.

procedure division

019600*> ***************************************************************
019700 procedure division.
019800

Accept command line arguments. See if help requested.

020600 accept arguments from command-line end-accept
020700
020800 move arguments to usagehelp
020900 if helping
021000     display
021100         "$ ./ocdoc source markover [output [skin]] --verbose"
021200     end-display
021300     display "$ ./ocdoc" end-display
021400     display "    without arguments extracts stdin to stdout"
021500     end-display
021600     goback
021700 end-if
021800

Either run as filter or open given files. Two filenames will generate an extract. Three will run the extract through rst2html using an optional fourth filename as a stylesheet.

022900*> Determine if this is running as a filter
023000 if arguments not equal spaces
023100     unstring arguments delimited by all spaces
023200         into source-name doc-name
023300              result-name style-name
023400              verbosity
023500     end-unstring
023600
023700     open input source-input
023800     open output doc-output
023900 else
024000     set filtering to true
024100
024200     open input standard-input
024300     open output standard-output
024400 end-if
024500

Initialize the output buffer, and line count.

025300 set buffer-empty to true
025400 move 1 to buffer-offset
025500 move spaces to doc-record
025600 move 0 to line-count
025700

The read is either from file or stdin. Start with the first record.

026600*> filtering requires different reader loop
026700 if filtering
026800     read standard-input
026900         at end move high-values to stdin-record
027000     end-read
027100     move stdin-record to source-record
027200 else
027300     read source-input
027400         at end move high-values to source-record
027500     end-read
027600 end-if
027700

The main loop starts here, having done a pre-read to start things off.

028600 perform until source-record = high-values
028700     add 1 to line-count
028800

Small wrinkle if processing fixed form with sequence numbers, as the heredoc end marker needs to be recognized but we still want the sequence numbers in the heredoc.

So files processed --fixed play some data shuffling games.

030000     if skipseqnum
030100         if heredoc
030200             move source-record(7 : 248) to trimmed
030300             move source-record to seq-data
030400             move seq-record to source-record
030500         else
030600             move source-record(7 : 248) to source-record
030700             move source-record to trimmed
030800         end-if
030900     else
031000         move function trim(source-record leading) to trimmed
031100     end-if
031200

First to check for here doc start and end, setting flag if trimmed conditional the heredoc start or heredoc end strings.

032200     if herestart
032300         set heredoc to true
032400     end-if
032500
032600     if hereend
032700         set herenone to true
032800     end-if
032900

Inside the loop, we skip over heredoc entries. If it is normal, than check for heredoc and include source lines that follow, by prepending the extract tag

033900     if (not herestart) and (not hereend)
034000         if heredoc
034100             move source-record to here-data
034200             move here-record to trimmed
034300         end-if
034400

Unstring the line, looking for special tags in the first part.

035300         unstring trimmed delimited by all spaces
035400             into first-part
035500                 count in counter
035600         end-unstring
035700

If special, we either buffer or append to buffer

036500         evaluate true when special
036600             if autoappend and buffer-empty
036700                 move spaces to doc-record
036800                 move 1 to buffer-offset
036900             end-if
037000
037100             if autodoc and buffered-output
037200                 if filtering
037300                     move doc-record to stdout-record
037400                     write stdout-record end-write
037500                 else
037600                     write doc-record end-write
037700                 end-if
037800                 if verbose
037900                     display
038000                         function trim(doc-record trailing)
038100                     end-display
038200                 end-if
038300                 move spaces to doc-record
038400                 set buffer-empty to true
038500                 move 1 to buffer-offset
038600             end-if
038700

Skip over where the tag was found plus an extra space. Adding 2 skips over the assumed space after a special tag

039600             add 2 to counter
039700             compute len-of-comment =
039800                 function length(trimmed) - counter
039900             end-compute
040000
040100             if len-of-comment > 0
040200                 move trimmed(counter : len-of-comment)
040300                     to doc-buffer
040400             else
040500                 move spaces to doc-buffer
040600             end-if
040700

Buffer the line, either to position 1 or appending to last.

041500             string
041600                 function trim(doc-buffer trailing)
041700                     delimited by size
041800                 into doc-record
041900                 with pointer buffer-offset
042000                 on overflow
042100                     move line-count to line-display
042200                     display
042300                         "*** truncation *** reading line "
042400                         line-display
042500                     end-display
042600             end-string
042700             set buffered-output to true
042800         end-evaluate
042900     end-if
043000

Again, we either read the next record from file or stdin.

043800     if filtering
043900         read standard-input
044000             at end move high-values to stdin-record
044100         end-read
044200         move stdin-record to source-record
044300     else
044400         read source-input
044500             at end move high-values to source-record
044600         end-read
044700     end-if
044800 end-perform
044900

We may or may not end up with buffered data

045700 if buffered-output
045800     set buffer-empty to true
045900     move 1 to buffer-offset
046000     if filtering
046100         move doc-record to stdout-record
046200         write stdout-record end-write
046300     else
046400         write doc-record end-write
046500     end-if
046600     if verbose
046700          display
046800             function trim(doc-record trailing)
046900          end-display
047000     end-if
047100     move spaces to doc-record
047200 end-if
047300

Close the OpenCOBOL files

048100 if filtering
048200     close standard-output
048300     close standard-input
048400 else
048500     close doc-output
048600     close source-input
048700 end-if
048800
048900 if verbose
049000     display "Input  : " function trim(source-name) end-display
049100     display "Output : " function trim(doc-name) end-display
049200 end-if
049300

An if we have a result file, use the SYSTEM service to generate an HTML file, possibly with stylesheet.

050200*> pass the extract through a markover, in this case ReST
050300 move spaces to rst-command
050400 if result-name not equal spaces
050500     if style-name equal spaces
050600         string
050700             "rst2html " delimited by size
050800             doc-name delimited by space
050900             " " delimited by size
051000             result-name delimited by space
051100             into rst-command
051200         end-string
051300     else
051400         string
051500             "rst2html --stylesheet=" delimited by size
051600             style-name delimited by space
051700             " " delimited by size
051800             doc-name delimited by space
051900             " " delimited by size
052000             result-name delimited by space
052100             into rst-command
052200         end-string
052300     end-if
052400
052500     if verbose
052600         display
052700             "Command: "
052800             function trim(rst-command trailing)
052900         end-display
053000     end-if
053100
053200     call "SYSTEM"
053300         using rst-command
053400         returning result
053500     end-call
053600
053700     if result not equal zero
053800         display "HTML generate failed: " result end-display
053900     end-if
054000 end-if
054100

And before you know it, we are done.

054900 goback.
055000
055100 end program OCDOC.

Don't forget to visit http://opencobol.org

Cheers

Last edit: 03-Oct-2008