RFREE.DOC -- RPG/free (tm) and RPG/pretty (tm) documentation Version 1.0 April 1990 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - by Paul Conte (Copyright 1990) Please note: This document can be reproduced for any purpose, as long as the following notice is included on the first page: *************************************************************************** *** RPG/free and RPG/pretty are trademarks of Paul Conte. *** *** *** *** RPG/free and RPG/pretty programs are Software copyright 1990 *** *** by Paul Conte. *** *************************************************************************** INTRODUCTION. RPG/free is a free format version of RPG. The RPG/free precompiler translates RPG/free input into standard RPG, which can be compiled by one of the RPG compilers. The RPG/pretty translator translates standard RPG input into "pretty" RPG/free code. Both RPG/free and RPG/pretty run under MS-DOS or the DOS compatability box of OS/2. The executable versions of RPG/free and RPG/pretty covered by this documentation can be freely copied and distributed. They are commercial quality programs intended for production use; however, because they are free, no warranty or support is offerred. Please use normal care in backing up files as you use these programs. If you find errors or have suggestions for improvements, please share your knowledge. By filling out the form in file FREENEWS, you can receive a free RPG/free newsletter that contains tips-and-techniques and error reports. The newsletter also contains the latest information on new releases of RPG/free and RPG/pretty. The latest releases of the programs are available on the NEWSLINK bulletin board of NEWS 3X/400 magazine. (Other bulletin boards are free to copy the latest releases from NEWSLINK to their own system for distribution. My only request is that you also provide the latest version of this RFREE.DOC file along with the programs.) INSTALLATION. To install, just copy RF.EXE (for RPG/free) and RP.EXE (for RPG/pretty) to your PC hard disk. (After you copy the two progams to your hard disk, you may want to rename the programs to avoid accidentally typing "RP" instead of "RF" when you execute them. For example, you might rename RF.EXE to RFREE.EXE.) You can test the programs by executing: rf /listopt tstin1.rpf tstin2.rpf out.rpg rp tstin.rpg out.rpf Then compare the generated file OUT.RPG with the supplied file TSTOUT.RPG, and compare the generated file OUT.RPF with the supplied file TSTOUT.RPF. These aren't comprehensive tests, but they will at least let you know you have functioning versions of the programs. EXECUTION. For RPG/free, enter: rf [options] input-file1 input-file2 ... input-filen output-file For RPG/pretty, enter: rp [options] input-file output-file For both programs: [options] is a list of options, each beginning with / (e.g., /noform) At least one input file and one output file are required, the last file listed is the output file. RPG/pretty can have up to 20 input files (or your current DOS maximum open file limit). *** Be sure to include your output file when you use more than one *** RPG/free input file. The command: rf inp1.rpf inp2.rpf *** treats inp2.rpf as the output file and replaces its contents. Use standard DOS file specifications for the input and output files. Recommended file extensions are .RPG for standard RPG files and .RPF for RPG/free files. For included macro files (discussed below), the standard extension is .RPM. You must include the extension when you specify a file. RPG/free options: /help List option switches. /listopt List the option settings for current execution. /nocmt Do not output RPG/free comment lines. Default is to output all comment lines. /nocvttab Do not convert tabs in input to spaces. Default is to convert tabs using tab stops [9, 17, 25, 33, ...] /numbers Output RPG source line numbers in positions 1-5. Default is to output blanks in 1-5. /asna Output source is Amalgamated Software of North America 400 RPG. /bps Output is BPS Information Services RPG II 1/2. /cspi Output is California Software Products Inc. RPG II. /cspi400 Output is California Software Products Inc. RPG 400. /lattice Output is Lattice, Inc. RPG II. /native Output is Native Software RPG 400. /rpgii Output is IBM RPG II (or 100% compatible). /rpgiii Output is IBM RPG III (or 100% compatible). /rpg400 Output is IBM RPG/400 (or 100% compatible). /softwest Output is Software West RPG II. /trident Output is Trident Software, Inc. RPG III. Default is RPG III. RPG/pretty options: /idcap Output identifiers with initial letter in upper case and other letters in lower case. /idupper Output identifiers in upper case. Default is lower case. /indentNb Use N blanks for each indent. /indentNt Use N tabs for each indent. Default is 1 tab. /isn Don't output warning for truncation of non-blank data in positions 1-5. Default is to output warning. /kwdlower Output keywords in lower case. Default is upper case. /maxindentN Maximum indent is N levels. Default is 5. /noform Begin H, F, E, I, T, L, and O spec output in position 7. Default is position 6 (form type character). /sepNb Use N blanks between operands. /sepNt Use N tabs between operands. Default is 1 tab. /symind Output indicators in symbolic form (*INxx). Default is nonsymbolic form (xx). /bps Output is BPS Information Services RPG II 1/2. /lattice Output is Lattice, Inc. RPG II. /rpgii Output is IBM RPG II (or 100% compatible). /rpgiii Output is IBM RPG III (or 100% compatible). /rpg400 Output is IBM RPG/400 (or 100% compatible). Default is RPG III. (Note: All vendors' versions of RPG are supported. Use /rpgii for RPG II from CSPI and Software West; use /rpgiii for RPG III from Trident Software; use /rpg400 for RPG/400 from ASNA, CSPI, and Native Software.) RPG II NOTES: Most RPG II opcodes are handled fine with the default /rpgiii compiler type. The following opcodes may require /rpgii or one of the third-party RPG II compiler options (depending on which operands you use for Factor1, Factor2, and Result): DEBUG DEFN POST VENDOR OPCODE EXTENSIONS: ASNA 400 RPG: Vendor RPG/free Indicator Keywords Opcode Synonym Factor1 Factor2 Result 54-55 56-57 58-59 ------ ----------- ------- ------- ------ ----- ----- ----- CKDT Blank Rqd Rqd CVDT Rqd Rqd Rqd EDIT Rqd Rqd Rqd WAIT Blank Rqd Blank Lattice RPG II: Vendor RPG/free Indicator Keywords Opcode Synonym Factor1 Factor2 Result 54-55 56-57 58-59 ------ ----------- ------- ------- ------ ----- ----- ----- blank ENDSS or Blank Rqd Rqd ENDSUBSTR CATST CATSTR Rqd Rqd Rqd SUBST SUBSTR Rqd Rqd Blank Native Software RPG 400: Vendor RPG/free Indicator Keywords Opcode Synonym Factor1 Factor2 Result 54-55 56-57 58-59 ------ ----------- ------- ------- ------ ----- ----- ----- MODE Blank Rqd Blank RI3 RDCOM Blank Blank Rqd RI1 RI2 RI3 WRCOM Blank Rqd Blank RI2 RI3 Other vendor extensions: If you encounter a vendor extension that is not properly handled by RPG/free's translation, the ultimate "work-around" is to use a /FIX directive, followed by the exact format of the standard RPG statement, followed by a /FREE directive. RPG/free notes: The only effect of the compiler options are: /lattice Required to translate X'FFFF....' into X'FFFF.... Required to translate ENDSS to blank opcode. /rpgii Required to properly handle some DEFN, DEBUG, and POST opcodes. RPG/free does not translate non-C-spec input to uppercase. You should use uppercase wherever standard RPG requires it in non-C-specs. Tabs are converted to blanks on input using DOS default tabstops (9, 17, ...). The /nocvttab option eliminates conversion. The only place where you might encounter problems are in non-C-specs or quoted literals, if you are using different tab stops than the defaults. Just replace any problem tabs with appropriate spaces. RPG/free writes error messages to the STDERR output stream. Unfortunately. DOS will not redirect STDERR to a file. (This may be changed in future versions.) Most syntax error messages are prefixed by a number. This number appears in the generated standard RPG code for reference purposes. Some error messages list the current token as seen by the parser. You may see the following "strange" symbols: EOS End of string (the end of the input statement) U+ Unary plus (as in X = + Y) U- Unary minus (as in X = - Y) In some cases, the translator pushes the current token back on the input stream and re-parses it. This may cause you to see two or more error messages for the same token (for example when there is an unclosed string in the input). The following tables shows how RPG/free treats operation arguments: Logical Operation Factor1 Factor2 Result Operator Notes --------- -------- -------- -------- -------- -------------- ACQ Required Required ADD Optional Required Required AND Required Optional Optional Extended op ANDxx Required Required BEGSR Required BITOF Required Required BITON Required Required CABxx Required Required Optional CALL Required Optional CAS Optional Optional Required CASE Optional Optional Required Optional Extended op CASxx Optional Optional Required CATST Required Required Required Lattice CHAIN Required Required Optional CKDT Required Required ASNA CLOSE Required COMIT Optional COMP Required Required CVDT Required Required Required ASNA DCL Optional Required Extended op DEBUG Optional Optional Optional RPG III/400 DEBUG Optional Required Optional RPG II DEFN Required Optional Required RPG III/400 DEFN Required Required Required RPG II DELET Optional Required DIV Optional Required Required DO Optional Optional Optional DOUxx Required Required DOWxx Required Required DSPLY Optional Optional Optional DUMP Optional EDIT Required Required Required ASNA ELSE END Optional ENDSR Optional Optional ENDSS Required Required Lattice EXCPT Optional EXFMT Required EXIT Required RPG II EXSR Required FEOD Required FOR Required Required Required Required Extended op FORCE Required FREE Required GOTO Required IF Required Optional Optional Extended op IFxx Required Required IN Optional Required KEYxx Optional Optional RPG II KFLD Required KLIST Required LOKUP Required Required Optional MHHZO Required Required MHLZO Required Required MLHZO Required Required MLLZO Required Required MODE Required Native Software MOVEx Required Required MULT Optional Required Required MVR Required NEXT Required Required OCUR Optional Required Optional OPEN Required OR Required Optional Optional Extended op ORxx Required Required OUT Optional Required PARM Optional Optional Required PLIST Required POST Optional Optional Optional RPG III/400 POST Required Required RPG II RDCOM Required Native Software READ Required Optional READC Required READE Required Required Optional READP Required Optional REDPE Required Required Optional REL Required Required RETRN RLABL Required RPG II ROLBK SETGT Required Required SETLL Required Required SETOF SETON SETxx Optional Optional Optional RPG II SHTDN SORTA Required SQRT Required Required SUB Optional Required Required SUBST Required Required Lattice TAG Required TESTB Required Required TESTN Required TESTZ Required TIME Required UNLCK Required UNTIL Required Optional Optional Extended op UPDAT Required Optional WAIT Required ASNA WHILE Required Optional Optional Extended op WRCOM Required Native Software WRITE Required Optional XFOOT Required Required Z-ADD Required Required Z-SUB Required Required RPG/pretty notes: The only effect of the compiler options are: /bps Required to recognize *? in positions 1-2 as beginning of data /lattice Required to translate X'FFFF.... into X'FFFF....' Required to translate blank opcode following SUBST to ENDSUBSTR. /rpgii Required to recognize ** in positions 1-2 with non-blank in 3 as beginning of data. (Default /rpgiii requires position 3 to be blank.) Required to recognize /* in positions 1-2 as end-of-file RPG/pretty determines where position 1 of the standard RPG specification is in the DOS file by examining the first input record to see if there are S/38 or AS/400 SEU-style source numbers or dates (not the RPG statement numbers in RPG positions 1-5). These source numbers and dates are normally stripped when you use PC Support on the S/38 or AS/400 to download a source file member. But if they are included, RPG/pretty can normally figure out how to skip them. The rules RPG/pretty uses are: IF characters 1-8 contain xxxxx.nn AND characters 9-15 contain xxxxxxn The RPG statement starts in 16 ELSE IF characters 1-7 contain xxxxxxn AND characters 8-15 contain xxxxx.nn The RPG statement starts in 16 ELSE IF characters 1-8 contain xxxxx.nn The RPG statement starts in 9 ELSE IF characters 1-7 contain xxxxxxn The RPG statement starts in 8 ELSE The RPG statement starts in 1 (Where each n is a digit and each x is a digit or blank.) If you have problems, just strip off any non-RPG line numbers. (Do NOT strip off RPG statement numbers in positions 1-5; use the /isn option to ignore them.) RPG/pretty does not convert tabs to blanks on input. Some invalid specifications do not cause a warning; for example, an indicator like UX is considered valid. RPG/free will catch many of these. All opcode lookups are done in UPPERCASE (as standard RPG requires). Comment lines that are not C-specs are output as the formtype followed by an asterisk (with /noform, just an asterisk). For example, F* comment... You may want to use a PC editor to search and replace this pattern (e.g., F*) with -- which is the standard RPG/free comment. The current RPG/pretty approach maintains better alignment for commented non-C-specs in existing code. IMPLEMENTATION NOTES: RPG/pretty was implemented using POLYTRON PolyAWK Plus 1.0 compiler. RPG/free was implemented using Microsoft C version 5.01 under IBM PC-DOS 4.01. RPG/free has the following maxima: Input files 20 File name length 90 Number of command line arguments 20 Command argument length 90 Number of continuation lines 19 Input line length 250 Statement length 1000 Keyword length 20 Token length 80 Macro replacement text length 100 Number of macros 100 THE RPG/free LANGUAGE: A full description of RPG/free is published in the article "RPG/free -- The Golden Age of RPG Programming", Paul Conte, NEWS 3X/400, April 1990. Copies of this article are available as a back issue order from NEWS 3X/400, P.O. Box 3438, Loveland, CO 80539-9916 (800) 373-3853. PROGRAM STRUCTURE RPG/free programs have the same structure as standard RPG programs. You specify the form type with a directive. A complete program might contain: /CONTROL or /HEADER (optional) Control specifications /FILE File specifications /EXTENSION or /EXT Extension specifications /LINE Line counter specifications /TELCOM Telecommunications specifications /INPUT Input specifications /CALC Calculation specifications /OUTPUT Output specifications /DATA ** File translation records ** Alternate collating sequence records ** Compile-time array and table data The precompiler starts with form type as H, so a beginning /CONTROL is optional. You do not have to include directives for unused form types. The form types must be in the standard RPG order, the precompiler does not sort them. NON-C-SPECS H, F, E, L, T, I, and O specifications are output without translation, except for proper column alignment based on the /FIRSTCOL directive setting. With the standard /FIRSTCOL setting (6), you begin each statement with the form character in position 1. (This is redundant, but aids readability.) To eliminate form characters, use the /FIRSTCOL 7 directive. To add characters in positions 1-5, use /FIRSTCOL n where n is 1 to 5 and specifies where position 1 of the input will be placed in the output. You can use multiple /FIRSTCOL directives, so you can bracket a statement that you want to mark and leave the others as the default: FAFILE1 .... /FIRSTCOL 4 >>FAFILE2 ... /FIRSTCOL 6 FAFILE3 ... C-SPECIFICATION STATEMENTS C-specs are free format, you can use blanks and tabs freely for alignment. You can also use upper or lower case for all keywords, identifiers, and special values. Lower case is converted to upper case except within string constants (e.g., 'Name' is unchanged) and figurative constants (e.g., *all'x' becomes *ALL'x'). A complete C-spec has the following parts: Control (or level) indicator Conditioning indicators Operation Declaration Half-adjust Resulting indicators Rules for combining these parts are the same as in standard RPG. CONTROL INDICATOR You can specify any one of the following control indicator keywords: L0() L1() L2() L3() L4() L5() L6() L7() L8() L9() LR() You must use the parentheses. The left parenthesis must immediately follow the keyword. You can use blanks or tabs anywhere within the parentheses. CONDITIONING INDICATORS You can specify up to three conditioning indicators for each statement as: (01 02 03) or First or only conditioning indicators COND(01 02 03) for statement AND(01 02 03) AND'd indicators OR(01 02 03) OR'd indicators You can specify negated indicators as (n01 n02 n03). You can use symbolic indicators as (*in01 *in02 *in03) or (*inn01 *inn02 *inn03). OPERATION Allowable operands are: Operand type Example Fact1 Fact2 Result ------------------------------ ------- ----- ----- ------ Identifier custid Y Y Y Subscripted identifier ary,2 Y Y Y Non-negated symbolic indicator *IN01 Y Y Y Subscripted indicator array *IN,i Y Y Y Null placeholder *N Y Y Y Special value *zero Y Y Y Numeric constant -1.2 Y Y N String constant 'Name' Y Y N Figurative constant *all'X' Y Y N Hexadecimal constant x'f0' Y Y N Within operations, array references have the same form as in standard RPG; for example: X,3 There are two forms of operation: arithmetic assignment and keyword operations. Arithmetic assignments have the form: a = b or a = b + c You can use +, *, -, or /. You can't use parentheses or compound expressions such as a = (b + c) * d. Standard keyword operations have an operation-operand form: operation factor1 factor2 result If an operation has blank or optional Factor1 or Factor2, you usually do not have to specify it. RPG/free looks up the operation and places operands where they belong. You can use the placeholder *n or *N to explicitly place blanks in an operand field. For example, DELETE cusrcd generates DELETCUSRCD DELETE *n cusrcd generates DELETCUSRCD DELETE custid cusrcd generates CUSTID DELETCUSRCD UPDATE cusfil generates UPDATCUSFIL UPDATE cusfil cusds generates UPDATCUSFIL CUSDS Note that RPG II and RPG III have different rules for the following opcodes: CHAIN, DEBUG, DEFN, POST, READ, READE, and READP. RPG/free default placement will correctly handle all versions of CHAIN, READ, READE, and READP. You can use either the /rpgii option or explicit *n placeholders for the RPG II versions of DEBUG, DEFN, and POST. You can use the following correctly spelled synonyms instead of standard RPG opcodes: RPG/free synonym Standard RPG opcode ---------------- ------------------- CASE CAS COMMIT COMIT DELETE DELET DISPLAY DSPLY ENDCASE END ENDDO END ENDFOR END ENDIF END ENDUNTIL END ENDWHILE END LOOKUP LOKUP OCCUR OCUR READPE REDPE RETURN RETRN ROLLBACK ROLBK SETOFF SETOF UNLOCK UNLCK UPDATE UPDAT If you think of C-spec operands as Factor1, Factor2, Result instead of first, second, and third operands, you can use RPG/free keywords as in the examples (operands can be in any order when you use keywords): UPDATE F2(cusfil) R(cusds) add f1(x) f2(y) r(z) add r(z) f2(y) f1(x) You can mix the keyword and positional forms, but be careful because the default placement of operands does not work the same as in S/38 and OS/400 CL. RPG/free first places operands specified with keywords, then fills in vacant operands using its default rules. RPG/free has a set of extended operations for control structures: RPG/free Standard RPG --------------------- --------------------------------------- AND f1 = f2 F1 ANDEQF2 AND f1 F1 ANDEQ'1' CASE f1 < f2 r F1 CASLTF2 R CASE f1 r F1 CASEQ'1' R CASE r CAS R FOR r = f1 f2 F1 DO F2 R ENDFOR f2 END F2 IF f1 <= f2 F1 IFLE F2 IF f1 F1 IFEQ '1' OR f1 > f2 F1 ORGT F2 OR f1 F1 OREQ '1' UNTIL f1 <> f2 F1 DOUNEF2 UNTIL f1 F1 DOUEQ'1' WHILE f1 >= f2 F1 DOWGEF2 WHILE f1 F1 DOWEQ'1' The logical operators are: Operator Meaning -------- -------------- < Less than <= Less than or equal = Equal <> Not equal >= Greater than or equal > Greater than You can also use keywords with extended operations (although it isn't very readable): IF f1(x) op(<=) f2(y) FOR r(idx) op(=) f1(bgn) f2(end) DECLARATIONS After an operation and its operands, you can declare the result field: ADD x y z LEN(7 0) Declares numeric field Z a = b * c LEN(7 2) Declares numeric field A MOVE 'Name' outfld LEN(8) Declares character field OUTFLD You can use relative sizes on the DEFN operation DEFN *LIKE x z LEN(+2) Declares numeric field Z as 2 positions larger than X. The RPG/free DCL extended operation allows independent field declarations. RPG/free operation Standard RPG ------------------ --------------------------- DCL r LEN(5) MOVELR R 5 DCL r LEN(5 0) Z-ADDR R 50 DCL f2 r LEN(5) MOVE *BLANK R 5 MOVELF2 R DCL f2 r LEN(5 0) Z-ADDF2 r 50 Note that the DCL does generate executable statements. You may want to put these in an initialization subroutine that is executed only once; or put under a conditional statement: IF pgminz = false DCL inpcid LEN(5 0) ... MOVE true pgminz ENDIF HALF-ADJUST On arithmetic operations, you can code H() to specify half-adjust. RESULTING INDICATORS You can specify up to three resulting indicators in two ways: as a list enclosed within RESULT(...) or with resulting indicator keywords. The three relative positions within a RESULT(...) list correspond to positions 54-55, 56-57, and 58-59. For example: 555555 RPG/free 456789 ---------------- ------ RESULT(01 *n 02) generates 01 02 You can use symbolic indicators as in RESULT(*in01 *in02). You cannot use negated indicators (e.g., N01). Instead of a RESULT(...) list, you can use the following keywords: 54-55 56-57 58-59 Notes ---------- ---------- ---------- ----------- RI1 RI2 RI3 e.g., SETON POS NEG ZER e.g., ADD ZERO ZERBLK e.g., MOVE BLANK BLK HI LO EQ e.g., LOKUP NR ER EOF e.g., CHAIN, READ ERR BOF e.g., READP OFF MIX ON TESTB ALLNUM LEADBLK ALLBLK TESTN ZONEA ZONEJ ZONEX TESTZ SHTDN SHTDN You don't have to use the matching keywords for each operation. For example, you can use: MOVE x y HI(01) LO(02) EQ(03) You can place keywords in any order, but you cannot specify the same standard RPG positions more than once. You can use symbolic indicators, but not negated indicators. You cannot use *n with resulting indicator keywords. COMMENTS You can add a trailing comment to any RPG/free statement, except the /DEFINE and /TITLE directives. Comments can be added to other directives and non-C-specs as well as C-specs. You cannot add comments to lines that follow the /DATA directive, lines between /FIX and /FREE directives, or lines in a file included with the /INCLUDEF directive. (You can place comments on lines in a file included with the /INCLUDE directive.) Use -- to begin a comment. For example: add a b -- This is a comment The comment ends at the end of the input line or at the last character before a plus sign (+) indicates a continued statement. The first unquoted -- in a line marks the beginning of the comment. Although you can generally leave blanks out of assignment operations (e.g., a=b-c), don't code "b minus -3" as b--3 because the --3 will be treated as a comment. To code a comment line, just begin with -- anywhere in the line. CONTINUATIONS You can continue an RPG/free statement across multiple lines by coding a + as the last nonblank, nontab character on a line: MOVE 'Name' + outfld When the RPG/free precompiler reads an input line, the precompiler first checks for, and removes, a trailing + specifying a continued statement. The precompiler than scans the line for an unquoted -- marking the beginning of a comment. Any comment is removed from the input line and output as C*-- Comment The precompiler reads the next line and removes all leading blanks before the line is concatenated to the end of the continued line. The precompiler repeats this process until the end of a statement (i.e., no continuation or end-of-input). The precompiler then parses the input statement according to RPG/free syntax rules. DIRECTIVES RPG/free supports the following standard RPG compiler directives: /COPY host-file-member-spec /EJECT /EXEC SQL sql-statement sql-statement ... /END-EXEC /SKIP n /SPACE n /TITLE title You can use blanks and tabs between a directive keyword and its argument, the precompiler realigns the argument to meet standard RPG requirements. SQL statements between the /EXEC SQL and /END-EXEC directives must not have the leading + used in standard RPG/400; the + is added by the precompiler. RPG/free includes the following precompiler directives: /DEFINE identifier replacement-text Define a macro /UNDEFINE identifier Remove macro definition /FIRSTCOL n Set output position for non-C-specs /FIX Begin fixed input /FREE Resume free format input /INCLUDE pc-file-spec Include free format file /INCLUDEF pc-file-spec Include fixed format file SETTING FIRST COLUMN (/FIRSTCOL) The /FIRSTCOL directive has an argument from 1 to 7 that specifies the position in the standard RPG output where the first position in a non-C-spec input line will be placed. The default is 6 which requires you to begin non-C-specs with the proper form type character. /FIRSTCOL does not effect lines between /FIX and /FREE directives, within an /INCLUDEF file, or following the /DATA directive. SOURCE MACROS (/DEFINE and /UNDEFINE) An RPG/free source macro is an identifier for a string of replacement text. Although RPG/free macros are fairly simple, they provide great flexibility in creating highly readable programs. To define a macro, code /DEFINE followed by one or more blanks and tabs and the macro name. Follow the macro name with one or more blanks or tabs and then code the replacement text. The replacement text begins with the first nonblank, nontab after the macro name and ends with the last nonblank, nontab character on the same line. The macro name must begin with a letter or national character ($, #, @) and can include letters, national characters, numbers, and the _ (underscore) readability character. Upper and lower case letters are considered identical in matching macro names. A macro name can be up to 80 characters long. The replacement text can include any characters, except leading or trailing blanks and tabs, which are always trimmed. Remember not to code comments or continuations on a macro because they are not processed and become part of the replacement text. As the precompiler encounters tokens during its parse of an RPG/free C-spec, it replaces every occurrence of a macro identifier with the corresponding replacement text. The precompiler then restarts its parse at the beginning of the replacement text, thus allowing nested macros. For example: /DEFINE customer_id csid /DEFINE exit_key *in03 /DEFINE true '1' /DEFINE IFNOT IF true <> IFNOT exit_key becomes IF '1' <> *in03 The precompiler does not replace a macro in any input line until it encounters the macro's definition on a /DEFINE. When another /DEFINE for the same macro is encountered, the replacement text is changed for subsequent input lines. As some examples: /DEFINE customer_id csid MOVE customer_id outfld becomes MOVE csid outfld /DEFINE customer_id custid MOVE customer_id outfld becomes MOVE custid outfld If you code a /DEFINE with a macro name and replacement text that is nothing but blanks and tabs, the precompiler replaces the macro name with the null string (i.e., deletes it) when the macro is encountered in subsequent input lines. You can use this to add readability words to your statements: /DEFINE TO /DEFINE FROM ADD x TO y becomes ADD x y SUB x FROM y becomes SUB x y Be careful not to code recursive macros, which will cause a syntax error: /DEFINE x y /DEFINE y x a = x causes syntax error To remove a macro definition, use /UNDEFINE with the macro name: /DEFINE x csid a = x becomes a = csid /UNDEFINE x a = x remains a = x FIXED FORMAT INPUT (/FIX and /FREE) You can included standard, fixed-format RPG in an RPG/free source file by placing it after a /FIX directive. All records following a /FIX directive are moved without any modification to the output. Fixed format lines end when a /FREE directive or end-of-file is encountered. You cannot span multiple input files with a /FIX; you must code a /FIX at the beginning of each one. (This approach prevents "runaway" /FIX directives.) INCLUDING SOURCE FILES (/INCLUDE and /INCLUDEF) You can include RPG/free source at any point in the input by coding an /INCLUDE directive with a PC file specification: /INCLUDE include1.rpf You can nest /INCLUDEs up to 20 deep (or the current DOS limit on open files), but you cannot use recursive /INCLUDEs. With /INCLUDE, all input is treated as RPG/free code (unless the included file contains a /FIX or /DATA directive). To include standard, fixed-format RPG, use /INCLUDEF. All input lines from a file specified on an /INCLUDEF are treated the same as if they followed a /FIX directive. The RPG/free precompiler does not recognize any directives within a file included using /INCLUDEF. COMBINING MACROS AND INCLUDE FILES A powerful technique is to use /INCLUDEs to "reuse" standard macros. Consider the following file as SYSMAC.RPM: /DEFINE true '1' /DEFINE false '0' /DEFINE IFNOT IF true <> ... Then in any RPG/free program, you can simply code: /INCLUDE sysmac.rpm to get the standard definitions. You can create /INCLUDE files for indicator definitions, standard variable declarations, etc. Another technique is to define standard long names for database file fields. Consider the following file as CUSFLD.RPM: -- Customer file (CUSMST) /DEFINE Cust_ID csid /DEFINE Cust_name csnam /DEFINE Cust_discount csdsc ... In any program that references the CUSMST file, you can simply code: /INCLUDE cusfld.rpm to make available the standard long names. On the S/38 and AS/400, you can automatically generate files like CUSFLD.RPM by using the DSPFFD (Display File Field Description) command. An article describing this technique and the necessary CL and RPG/400 code is scheduled for publication in NEWS 3X/400 in the summer of 1990. -- End of RFREE.DOC --