Cobol Products
  
Home
Download
Buy
About
Contact Us
 

Summary
Technical White Paper
Try Cobol Transformer
License CobolTransformer
Success Stories
Contact Us

CobolTransformer . ToolKit .
Technical White Paper
In this white paper we describe CobolTransformer in more detail.

Also we provide a concrete example of CobolTransformer use:
(1) Specification for program transformation,
(2) C++ code that performs this transformation,
(3) Program and its expression tree before the transformation.
(4) Program and its source tree after the transformation.

Introduction

Language-wise, CobolTransformer is a C++ library. This is because C++ is so far the most convenient language for writing compilers, converters and related tools. Let us know if you need interface to other languages, and we will be glad to develop it.

As we said earlier, there are 3 major components in the CobolTransformer library: (1) Cobol Parser, (2) C++ library to manipulate the tree-based internal representation, (3) PrettyPrinter that transforms tree-based Internal Representation back into Cobol program.

For most Cobol projects you would need all 3 components: you need to parse, you need to transform, and you need to generate code. However, for some other projects you would need only 1 or 2 components. Examples:

  • A tool that computes program metrics such as McCabe or Halstead metrics would need only parser -- no transformation and no code generation is required.
  • A tool that generates Cobol code from some non-Cobol source (for instance, from object code) would build a CobolTransformer tree and will hand it over to the Code Generator. Here only tree builder and Code Generator are required, and Cobol parser is not necessary.

Program Representation: Expression Tree

To represent Cobol program, we use expression trees that are more or less a standard way of representing programs in compilers.

Semantically, our expression trees are midway between the original Cobol program and the low level assembly code or its varieties. The design goals for CobolTransformer expression trees were:

  • Make it easy to get to any given part of the Cobol program. For instance, finding whether Special-Names paragraph is present in the program does not involve searching thru the multitude of trees. This paragraph has a known position in the Program Tree.
  • Preserve as much of original program as possible. For instance, we keep comments attached to the program tree. Comments do not affect semantics of the program, but since the user would like to see her comments preserved in the converted program, we keep the comments intact.

These goals are somewhat contradictory. For instance, in SCT data item description is represented by a big node in which there is a slot for every possible data description clause. This makes getting to the desired clause easy. But it violates original ordering of clauses in the source program. We think that original ordering of the clauses is not that important, but being able to get to the desired clause easily is important.

A different example: we think that preserving exact image of Cobol values that appear in the program is important. If Cobol programmer wrote H'80' in his MicroFocus program instead of 128 then he did it for a reason (for instance, he wanted to underscore that this value is a string of bits) and he would like to see hexadecimal format of a constant preserved.

We think that we were able to achieve a right balance of syntax and semantics in the design of our Program Tree.

You can get a better idea about CobolTransformer internals by ordering CobolTransformer manual.

Without getting too deep into intricacies of Cobol tree representation, we give an example of trees that we use.

Example: Cobol Source. Consider the following MicroFocus Cobol program.

IDENTIFICATION DIVISION. PROGRAM-ID. CV-TIME. * === Data Division starts here === DATA DIVISION. WORKING-STORAGE SECTION. 01 LOCALS. 05 WS-TIME PIC X(6) COMP-X. 05 WS-HRS PIC X(2) COMP-X. 05 WS-MINS PIC X(2) COMP-X. 78 CS-ONE VALUE 1. 78 CS-TWO VALUE 2. 05 WS-SECS PIC X(2) COMP-X VALUE CS-ONE. 05 ST-HRS PIC X(5). * === Procedure Division starts here === PROCEDURE DIVISION. TIME-CONV. MOVE 100 to WS-TIME DIVIDE 60 INTO WS-TIME GIVING WS-MINS REMAINDER WS-SECS. * ++ At the critical juncture ++ IF WS-HRS = 1 MOVE " HR " TO ST-HRS ELSE MOVE " HRS" TO ST-HRS.

Example: CobolTransformer Expression Tree. This Cobol program is represented by the following expression tree (first two numbers at every node line represent depth of the node and its position as a child of its parent):

COBOL_FILE 1. 0. (NULL) 1. 1. (NULL) 1. 2. (NULL) 1. 3. (NULL) 1. 4. COBOL_PROGRAM_LIST 2. 0. . COBOL_PROGRAM 3. 0. . . DIVISION_IDENTIFICATION 4. 0. . . . PARA_PROGRAM_ID 5. 0. . . . . EX_NAMED_OBJ_DEF CV-TIME cat=program-name 5. 1. . . . . (NULL) 3. 1. . . (NULL) 3. 2. . . DIVISION_DATA Comments { . . . . . . . . * === Data Division starts here === . . . . } Comments 4. 0. . . . (NULL) 4. 1. . . . (NULL) 4. 2. . . . SECTION_WORKING_STORAGE 5. 0. . . . . DECL_DD_ENTRY_LIST 6. 0. . . . . . DECL_DD_ENTRY 7. 0. . . . . . . EX_INT_NUM_CONST image=01 value=1 7. 1. . . . . . . EX_NAMED_OBJ_DEF LOCALS cat=data-name 7. 2. . . . . . . (NULL) 7. 3. . . . . . . (NULL) children 3 to 14 are all NULL 7.15. . . . . . . EX_DD_CHILDREN 8. 0. . . . . . . . DECL_DD_ENTRY 9. 0. . . . . . . . . EX_INT_NUM_CONST image=05 value=5 9. 1. . . . . . . . . EX_NAMED_OBJ_DEF WS-TIME cat=data-name 9. 2. . . . . . . . . EX_DD_PICTURE 10. 0. . . . . . . . . . EX_CHAR_STRING X(6) 9. 3. . . . . . . . . EX_DD_USAGE 10. 0. . . . . . . . . . EX_DU_COMP_X 9. 4. . . . . . . . . (NULL) 9. 5. . . . . . . . . (NULL) children 5 to 15 are all NULL 8. 1. . . . . . . . DECL_DD_ENTRY 9. 0. . . . . . . . . EX_INT_NUM_CONST image=05 value=5 9. 1. . . . . . . . . EX_NAMED_OBJ_DEF WS-HRS cat=data-name 9. 2. . . . . . . . . EX_DD_PICTURE 10. 0. . . . . . . . . . EX_CHAR_STRING X(2) 9. 3. . . . . . . . . EX_DD_USAGE 10. 0. . . . . . . . . . EX_DU_COMP_X 9. 4. . . . . . . . . (NULL) 9. 5. . . . . . . . . (NULL) children 5 to 15 are all NULL 8. 2. . . . . . . . DECL_DD_ENTRY 9. 0. . . . . . . . . EX_INT_NUM_CONST image=05 value=5 9. 1. . . . . . . . . EX_NAMED_OBJ_DEF WS-MINS cat=data-name 9. 2. . . . . . . . . EX_DD_PICTURE 10. 0. . . . . . . . . . EX_CHAR_STRING X(2) 9. 3. . . . . . . . . EX_DD_USAGE 10. 0. . . . . . . . . . EX_DU_COMP_X 9. 4. . . . . . . . . (NULL) 9. 5. . . . . . . . . (NULL) children 5 to 14 are all NULL 9.15. . . . . . . . . EX_DD_CHILDREN 10. 0. . . . . . . . . . DECL_DD_ENTRY 11. 0. . . . . . . . . . . EX_INT_NUM_CONST image=78 value=78 11. 1. . . . . . . . . . . EX_NAMED_OBJ_DEF CS-ONE cat=data-name 11. 2. . . . . . . . . . . (NULL) 11. 3. . . . . . . . . . . (NULL) children 3 to 12 are all NULL 11.13. . . . . . . . . . . EX_DD_VALUE 12. 0. . . . . . . . . . . . EX_DD_VALUE_LIST 13. 0. . . . . . . . . . . . . EX_INT_NUM_CONST image=1 value=1 12. 1. . . . . . . . . . . . (NULL) 11.14. . . . . . . . . . . (NULL) 11.15. . . . . . . . . . . (NULL) 10. 1. . . . . . . . . . DECL_DD_ENTRY 11. 0. . . . . . . . . . . EX_INT_NUM_CONST image=78 value=78 11. 1. . . . . . . . . . . EX_NAMED_OBJ_DEF CS-TWO cat=data-name 11. 2. . . . . . . . . . . (NULL) 11. 3. . . . . . . . . . . (NULL) children 3 to 12 are all NULL 11.13. . . . . . . . . . . EX_DD_VALUE 12. 0. . . . . . . . . . . . EX_DD_VALUE_LIST 13. 0. . . . . . . . . . . . . EX_INT_NUM_CONST image=2 value=2 12. 1. . . . . . . . . . . . (NULL) 11.14. . . . . . . . . . . (NULL) 11.15. . . . . . . . . . . (NULL) 8. 3. . . . . . . . DECL_DD_ENTRY 9. 0. . . . . . . . . EX_INT_NUM_CONST image=05 value=5 9. 1. . . . . . . . . EX_NAMED_OBJ_DEF WS-SECS cat=data-name 9. 2. . . . . . . . . EX_DD_PICTURE 10. 0. . . . . . . . . . EX_CHAR_STRING X(2) 9. 3. . . . . . . . . EX_DD_USAGE 10. 0. . . . . . . . . . EX_DU_COMP_X 9. 4. . . . . . . . . (NULL) 9. 5. . . . . . . . . (NULL) children 5 to 12 are all NULL 9.13. . . . . . . . . EX_DD_VALUE 10. 0. . . . . . . . . . EX_DD_VALUE_LIST 11. 0. . . . . . . . . . . EX_NAMED_OBJ_USE cat=constant-name 12. 0. . . . . . . . . . . . EX_OF_IN 13. 0. . . . . . . . . . . . . EX_NAME_USE CS-ONE 10. 1. . . . . . . . . . (NULL) 9.14. . . . . . . . . (NULL) 9.15. . . . . . . . . (NULL) 8. 4. . . . . . . . DECL_DD_ENTRY 9. 0. . . . . . . . . EX_INT_NUM_CONST image=05 value=5 9. 1. . . . . . . . . EX_NAMED_OBJ_DEF ST-HRS cat=data-name 9. 2. . . . . . . . . EX_DD_PICTURE 10. 0. . . . . . . . . . EX_CHAR_STRING X(5) 9. 3. . . . . . . . . (NULL) 9. 4. . . . . . . . . (NULL) children 4 to 15 are all NULL 4. 3. . . . (NULL) 4. 4. . . . (NULL) 4. 5. . . . (NULL) 4. 6. . . . (NULL) 4. 7. . . . (NULL) 3. 3. . . DIVISION_PROCEDURE Comments { . . . . . . . . * === Procedure Division starts here === . . . . } Comments 4. 0. . . . (NULL) 4. 1. . . . (NULL) 4. 2. . . . (NULL) 4. 3. . . . SECTION_PROC_LIST 5. 0. . . . . SECTION_PROC 6. 0. . . . . . (NULL) 6. 1. . . . . . (NULL) 6. 2. . . . . . PARA_PROC_LIST 7. 0. . . . . . . PARA_PROC Comments { . . . . . . . . . . . . . . . . } Comments 8. 0. . . . . . . . EX_NAMED_OBJ_DEF TIME-CONV cat=para-name 8. 1. . . . . . . . SENTENCE_LIST 9. 0. . . . . . . . . SENTENCE 10. 0. . . . . . . . . . STMT_LIST 11. 0. . . . . . . . . . . STMT_MOVE 12. 0. . . . . . . . . . . . EX_INT_NUM_CONST image=100 value=100 12. 1. . . . . . . . . . . . EX_LIST_IDENTIFIERS 13. 0. . . . . . . . . . . . . EX_NAMED_OBJ_USE cat=data-name 14. 0. . . . . . . . . . . . . . EX_OF_IN 15. 0. . . . . . . . . . . . . . . EX_NAME_USE WS-TIME 11. 1. . . . . . . . . . . STMT_DIVIDE 12. 0. . . . . . . . . . . . EX_ARITH_DIV_INTO_GIVING 13. 0. . . . . . . . . . . . . EX_INT_NUM_CONST image=60 value=60 13. 1. . . . . . . . . . . . . EX_NAMED_OBJ_USE cat=data-name 14. 0. . . . . . . . . . . . . . EX_OF_IN 15. 0. . . . . . . . . . . . . . . EX_NAME_USE WS-TIME 13. 2. . . . . . . . . . . . . EX_LIST 14. 0. . . . . . . . . . . . . . EX_NAMED_OBJ_USE cat=data-name 15. 0. . . . . . . . . . . . . . . EX_OF_IN 16. 0. . . . . . . . . . . . . . . . EX_NAME_USE WS-MINS 13. 3. . . . . . . . . . . . . EX_NAMED_OBJ_USE cat=data-name 14. 0. . . . . . . . . . . . . . EX_OF_IN 15. 0. . . . . . . . . . . . . . . EX_NAME_USE WS-SECS 12. 1. . . . . . . . . . . . (NULL) 12. 2. . . . . . . . . . . . (NULL) 12. 3. . . . . . . . . . . . (NULL) 9. 1. . . . . . . . . SENTENCE 10. 0. . . . . . . . . . STMT_LIST 11. 0. . . . . . . . . . . STMT_IF Comments { . . . . . . . . . . . . * ++ At the critical juncture ++ . . . . . . . . . . . . } Comments 12. 0. . . . . . . . . . . . EX_CMP_EQ 13. 0. . . . . . . . . . . . . EX_NAMED_OBJ_USE cat=data-name 14. 0. . . . . . . . . . . . . . EX_OF_IN 15. 0. . . . . . . . . . . . . . . EX_NAME_USE WS-HRS 13. 1. . . . . . . . . . . . . EX_INT_NUM_CONST image=1 value=1 12. 1. . . . . . . . . . . . STMT_LIST 13. 0. . . . . . . . . . . . . STMT_MOVE 14. 0. . . . . . . . . . . . . . EX_STR_CONST " HR " 14. 1. . . . . . . . . . . . . . EX_LIST_IDENTIFIERS 15. 0. . . . . . . . . . . . . . . EX_NAMED_OBJ_USE cat=data-name 16. 0. . . . . . . . . . . . . . . . EX_OF_IN 17. 0. . . . . . . . . . . . . . . . . EX_NAME_USE ST-HRS 12. 2. . . . . . . . . . . . EX_ELSE 13. 0. . . . . . . . . . . . . STMT_LIST 14. 0. . . . . . . . . . . . . . STMT_MOVE 15. 0. . . . . . . . . . . . . . . EX_STR_CONST " HRS" 15. 1. . . . . . . . . . . . . . . EX_LIST_IDENTIFIERS 16. 0. . . . . . . . . . . . . . . . EX_NAMED_OBJ_USE cat=data-name 17. 0. . . . . . . . . . . . . . . . . EX_OF_IN 18. 0. . . . . . . . . . . . . . . . . . EX_NAME_USE ST-HRS 12. 3. . . . . . . . . . . . (NULL) 3. 4. . . (NULL) 3. 5. . . (NULL) 3. 6. . . SYMBOL_TABLE_ELT_LIST 4. 0. . . . EX_SYMBOL_TABLE_ELT DEBUG-CONTENTS cat=special-register 4. 1. . . . special registers skipped 4.10. . . . EX_SYMBOL_TABLE_ELT CV-TIME cat=program-name 4.11. . . . EX_SYMBOL_TABLE_ELT LOCALS cat=data-name 4.12. . . . EX_SYMBOL_TABLE_ELT WS-TIME cat=data-name 4.13. . . . EX_SYMBOL_TABLE_ELT WS-HRS cat=data-name 4.14. . . . EX_SYMBOL_TABLE_ELT WS-MINS cat=data-name 4.15. . . . EX_SYMBOL_TABLE_ELT CS-ONE cat=constant-name 4.16. . . . EX_SYMBOL_TABLE_ELT CS-TWO cat=constant-name 4.17. . . . EX_SYMBOL_TABLE_ELT WS-SECS cat=data-name 4.18. . . . EX_SYMBOL_TABLE_ELT ST-HRS cat=data-name 4.19. . . . EX_SYMBOL_TABLE_ELT TIME-CONV cat=para-name 1. 5. END_OF_COBOL_FILE 1. 6. SYMBOL_TABLE_ELT_LIST 2. 0. . EX_SYMBOL_TABLE_ELT DEBUG-CONTENTS cat=special-register 2. 1. . special registers skipped

Browsing and Transforming Expression Trees

There is a number of functions available in CobolTransformer that let you browse and transform expression tree:
  • Constructors and Destructors.
  • Tree browsing: children, parent; set, add, delete, insert, find a child.
  • Print indented view of a tree for debugging (like the one shown above).
  • Tree flattening (marshaling) and unflattening: output tree to a file, or send it across the network.
  • Comments attached to tree nodes.
  • User-defined objects attached to the tree nodes.
  • Symbol Table for every Program.
    List of all Definitions for a given Name.
  • Links from Use to Definition and from Definition to all Uses for every Named Object.
  • Generate Fully Qualified Name for a given Definition, or Shortest Unique Qualified Name for a given Definition.
  • Rename Named Object Definition and all its Uses.

With this seemingly simple set of functions you can perform complicated transformations, as demonstrated in the following example (this is a fragment of the actual working code that you can download from the Free Evaluation Page).

Sample Transformation Spec. Perform the following transformations (these conversions are a part of MicroFocus to Fujitsu converter):

  • Move 78-level MF constant definitions to Symbolic Constant clause of Special-Names paragraph (Fujitsu Cobol feature).
    If Special-Names paragraph is not present, create it.
    If Configuration section is not present, create it.
    If Environment division is not present, create it.
  • Convert USAGE COMP-4 data items into USAGE BINARY data items,
  • Convert USAGE COMP-X data items into USAGE COMP-5 data items,
  • In USAGE COMP-5 data items convert PIC X(n) to PIC 9(2*n). To be more exact, number of 9-s is computed from number of X-s based on the following table: conv_x_to_9[] = {0,2,4,7,9,12,14,16,18}

Example: Transformation in C++. The following C++ program performs the above transformations (not bad! : these non-trivial transformations are expressed in only 130 lines of C++, including comments):

void ProcessProgram(SctExpr *const e, SctExpr *const) { if(e->Oper()==COBOL_PROGRAM) { psym_consts = NULL; SctExpr *e1 = e; void ProcessNode(SctExpr *&e, SctExpr *base); WalkTheTreeModRoot(e1, e1, ProcessNode); } } void ProcessNode(SctExpr *&e, SctExpr *base) { if(e->Oper()==DECL_DD_ENTRY && e->Args(DD_LEVEL)->Value()=="78" && e->Args(DD_VALUE)!=NULL) { if(conv_warn) { PWarning(parser.curr_posn, "Moved 78-level constant to Symbolic Constants"); } SctExpr *ne = new SctExprOper(EX_SN_SYMB_CONST, e->DelArg(DD_DATA_NAME,FALSE), e->Args(DD_VALUE)->DelArg(0,FALSE)); ne->comments.merge_last(e->comments); delete e; e = NULL; if(psym_consts==NULL) { SctExpr *be; if(base->Args(1)==NULL) { base->SetArg(1, new SctExprOper(DIVISION_ENVIRONMENT, ENULL,ENULL)); } be = base->Args(1); if(be->Args(0)==NULL) { be->SetArg(0, new SctExprOper(SECTION_CONFIGURATION, ENULL,ENULL,ENULL,ENULL)); } be = be->Args(0); if(be->Args(2)==NULL) { be->SetArg(2, new SctExprOper(PARA_SPECIAL_NAMES, 0, SN_ARG_NO)); } SctExpr *re = be->Args(2); be = new SctExprOper(EX_SN_SYMBOLIC_CONSTANT, ENULL); re->SetArgToList(SN_SYMBOLIC_CONSTANT, EX_LIST, be); psym_consts = be; } psym_consts->SetArgToList(0, EX_SN_SYMB_CONST_LIST, ne); return; } if(e->Oper()==DECL_DD_ENTRY) { SctExpr *eusg = e->Args(DD_USAGE); if(eusg && eusg->Args(0)) { eusg = eusg->Args(0); switch(eusg->Oper()) { case EX_DU_COMP_4: eusg->SetOper(EX_DU_BINARY); break; case EX_DU_COMP_X: eusg->SetOper(EX_DU_COMP_5); if(conv_warn) { PWarning(parser.curr_posn, "Convert COMP-X to COMP-5"); } /* FALL THRU to COMP_5 here */ case EX_DU_COMP_5: { SctExpr *epic = e->Args(DD_PICTURE); if(epic==NULL) break; epic = epic->Args(0); int length = 0; PicCategory pcat = ParsePicString(epic->Image(), length); if(pcat==PIC_ALPHA_NUM && length>=1) { int conv_x_to_9[] = {0,2,4,7,9,12,14,16,18}; int no_9 = conv_x_to_9[length]; VString ns = vfmt("9(%d)", no_9); if(conv_warn) { PWarning(parser.curr_posn, vfmt("Convert COMP-5: PIC %s to PIC %s", epic->Image().pchar(), ns.pchar())); } epic->Image() = ns; } } break; default: break; } } } }

Externalizing Expression Trees

Sometimes you need to write expression trees to external media, such as files, streams, strings, or read them back into converter from external media.

For these purposes we have intermediate representation called Transformer Intermediate Code (TIC). TIC is a machine-readable platform-independent ASCII representation of a CobolTransformer Expression Tree. The TIC is based on postfix Polish notation.

Cobol Parser

CobolTransformer Parser is a fairly complicated function that parses your Cobol source into Expression Tree.

If you think that your Program Trees are going to be so big that they will not fit in memory, then you can define tree processing function that will be called every time when parser finished parsing a sizable fragment of a program (in procedure division this fragment would be a Section).
Your expression processing function is expected to save this tree fragment to a file for later processing and free memory that it occupies.

The combined Cobol grammar is 7,500 lines long and it is written in BtYacc -- Backtracking Yacc, developed by Chris Dodd from the regular Yacc and enhanced by Siber Systems to work in production environment. We decided to use BtYacc because Cobol grammar cannot be fully described with LALR(1) grammar used by plain vanilla Yacc.

The following Cobol dialects are currently supported:

  • ANSI-74 Cobol
  • ANSI-85 Cobol
  • IBM OSVS Cobol
  • IBM Cobol/II
  • IBM Cobol SAA
  • Unix Cobol X/Open
  • MicroFocus Cobol
  • Microsoft Cobol
  • Ryan McFarland RM/COBOL
  • Ryan McFarland RM/COBOL-85
  • DOSVS Cobol
  • Wang (licensed separately).

We use the following documents as a source of Cobol definition:

  • ANSI X.23-1985 standard "Programming Language Cobol".
  • MicroFocus Cobol Language Reference. Issue 13, 1993.
  • IBM VS COBOL II Language Reference Manual.
  • Wang VS COBOL 85 Reference Manual.
  • Fujitsu Cobol 85 Reference Manual.

CobolTransformer and Cobol Compilers

CobolTransformer is based on compiler technology. That is, techniques that we use in CobolTransformer are generally accepted in compiler community.

However, CobolTransformer has several important features that usually are not available in the standard compilers:

Preserve Comments
Since CobolTransformer can be used for Cobol to Cobol transformation, it is important to preserve comments present in the original program. It is achieved by attaching comments to the expression tree representing the program.

Preserve COPY statements
Standard compiler needs to visit all the COPYLIB files mentioned in COPY statements in your Cobol program. If one of the COPYLIBs cannot be found, standard compiler gets confused and no object code is generated. CobolTransformer can recover from un-inlined COPY statements. Even more, it can preserve COPY statements on a program tree, so that you can perform program transformation even if not all COPYLIBs are available.

Keep Token Text Positions
Every token in a Cobol program has a position in the text file. Text position is identified by [file name, line number, column number] triplet. CobolTransformer has these positions available for every token, which is convenient for error diagnostics and building syntax-aware Cobol browsers and editors.

Other parser highlights:

  • Parsers for embedded languages: DMS-80/1100 DML, EXEC SQL, EXEC CICS.
  • The parser is tested on millions of lines of Cobol code. Extensive regression testing daily.
  • Full implementation of COPY REPLACING and REPLACE statements.
  • -INC statement implemented.
  • User-defined error diagnostics routines.

Cobol PrettyPrinter

When you finish transforming Cobol program expression tree, you need to convert this tree back into Cobol source form. This is when you call PrettyPrint function.

PrettyPrint function uses Code Generation table to print out the expression tree. There is an entry for every Cobol tree operation in this table. The entry contains text that represents this operation. In this text you can embed special characters that control formatting and printing of operation and its arguments.

We supply default Cobol Code Generation table. For your particular project you can override some entries in this table with your own entries that print certain operations differently.

Sample Converted Cobol program. Once transformations described in the previous section are applied to the program tree, and the resulting tree is PrettyPrinted, we get the following Cobol program:

@OPTIONS BINARY(BYTE) IDENTIFICATION DIVISION. PROGRAM-ID. CV-TIME. ENVIRONMENT DIVISION. CONFIGURATION SECTION. SPECIAL-NAMES. SYMBOLIC CONSTANT CS-ONE IS 1 CS-TWO IS 2. * === Data Division starts here === DATA DIVISION. WORKING-STORAGE SECTION. 01 LOCALS. 05 WS-TIME PIC 9(14) COMP-5. 05 WS-HRS PIC 9(4) COMP-5. 05 WS-MINS PIC 9(4) COMP-5. 05 WS-SECS PIC 9(4) COMP-5 VALUE CS-ONE. 05 ST-HRS PIC X(5). * === Procedure Division starts here === PROCEDURE DIVISION. TIME-CONV. MOVE 100 TO WS-TIME DIVIDE 60 INTO WS-TIME GIVING WS-MINS REMAINDER WS-SECS. * ++ At the critical juncture ++ IF WS-HRS = 1 MOVE " HR " TO ST-HRS ELSE MOVE " HRS" TO ST-HRS END-IF.

Some of the code generation table entries that were used in printing this program are:

_e(COBOL_PROGRAM, NULL, "{$1?$1}{$2?$2}{$3?$3}{$4?$4}{$5?$5}{$6?$6}"), _e(DIVISION_PROCEDURE, NULL, "PROCEDURE DIVISION{$1? $1}{$2? $2}.\n\r$3$4"), _e(SECTION_PROC_LIST, NULL, "\r@"), _e(SECTION_PROC, NULL, "$1 SECTION{$2?|$2}.\n\r$3"), _e(PARA_PROC_LIST, NULL, "\r@"), _e(PARA_PROC, NULL, "$1.\n\r$2"), _e(SENTENCE_LIST, NULL, "\r@"), _e(SENTENCE, NULL, "\r\t$1.\b\n"), _e(STMT_LIST, NULL, "\r@\n"), _e(STMT_MOVE, ManyMoveArgs, "MOVE $1\n TO $2"), _e(STMT_MOVE, NULL, "MOVE $1|TO $2"), _e(STMT_MOVE_CORR, NULL, "MOVE CORRESPONDING $1|TO $2"), _e(STMT_MULTIPLY, NULL, "MULTIPLY $1{$2?\n$2}{$3?\n$3}{$4?\n$4}"), _e(EX_ARITH_MUL_BY, NULL, "$1|BY $2"), _e(EX_ARITH_MUL_BY_GIVING, NULL, "$1|BY $2|GIVING $3"), _e(EX_END_MULTIPLY, NULL, "END-MULTIPLY"), _e(STMT_IF, NULL, "IF $1{$2?\n\t$2\b}{$3?\n$3}{$4?\n$4}"), _e(EX_ELSE, isElseIf, "ELSE \r$1"), _e(EX_ELSE, NULL, "ELSE\n\t$1"), _e(EX_END_IF, NULL, "END-IF"), int ManyArgs(Expr *e) { e = e->Args(0); return e->Oper()==EX_LIST_IDENTIFIERS && e->ArgNo()>=2; }

Proceed To

Siber Systems
Copyright © 1997-2010 by Siber Systems Inc.