home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 18 REXX / 18-REXX.zip / rc321.zip / upckrexx.cmd < prev   
OS/2 REXX Batch file  |  1997-09-10  |  161KB  |  3,554 lines

  1. /* ------------------------------------------------------------------ */
  2. /* UPCKREXX.CMD - unpack packed or "compressed" REXX programs         */
  3. /*                                                                    */
  4. /* (c) Copyright Bernd Schemmer 1995 - 1997                           */
  5. /*                                                                    */
  6. /*-Author:                                                            */
  7. /*   Bernd Schemmer                                                   */
  8. /*   Baeckerweg 48                                                    */
  9. /*   D-60316 Frankfurt am Main                                        */
  10. /*   Germany                                                          */
  11. /*   Compuserve: 100104,613                                           */
  12. /*   Internet:   100104.613@compuserve.com                            */
  13. /*                                                                    */
  14. /*-History:                                                           */
  15. /*   25.10.1995 /bs v1.00                                             */
  16. /*     - initial release                                              */
  17. /*                                                                    */
  18. /*                                                                    */
  19. /*-Distribution:                                                      */
  20. /*   UPCKREXX.CMD is part of the REXXCC package. Please see the file  */
  21. /*   REXXCC.CMD for my distribution policy.                           */
  22. /*                                                                    */
  23. /*-Usage:                                                             */
  24. /*                                                                    */
  25. /*   UPCKREXX sourceFile                                              */
  26. /*            {/LL:n} {/SI:n} {/BI:n}                                 */
  27. /*            {/FH{:n}} {/CM{:n}} {/NL{:n}} {/DL{:n}}                 */
  28. /*            {/IE{xt}{:n}}                                           */
  29. /*            {/L:logfile} {/H} {/Silent} {/NoSound} {/NoAnsi}        */
  30. /*            {/Trace}                                                */
  31. /*                                                                    */
  32. /*-where:                                                             */
  33. /*   sourcefile - name of the sourcefile                              */
  34. /*                                                                    */
  35. /*   /LL:n      - n is the line length for the output file            */
  36. /*                (def.: 72, n >= 60)                                 */
  37. /*                                                                    */
  38. /*   /SI:n      - n is the indent for the lines of the output file    */
  39. /*                (def.: 2, n >= 0)                                   */
  40. /*                                                                    */
  41. /*   /BI:n      - n is the indent for code blocks (like DO ... END)   */
  42. /*                (def.: 2, n >= 0)                                   */
  43. /*                                                                    */
  44. /*   /FH:n      - insert file and function headers if n is 1          */
  45. /*                (def.: 1, range: 0-1, default for n: 1)             */
  46. /*                                                                    */
  47. /*   /CM{:n}    - insert comments after END statements if n is 1      */
  48. /*                (def.: 1, range: 0-1, default for n: 1)             */
  49. /*                                                                    */
  50. /*   /NL{:n}    - insert empty lines to format the file if n is 1     */
  51. /*                (def.: 1, range: 0-1, default for n: 1)             */
  52. /*                                                                    */
  53. /*   /DL{:n}    - delete all comments from the sourcefile before      */
  54. /*                processing the file if n is 1                       */
  55. /*                (def.: 0, range: 0-1, default for n: 1)             */
  56. /*                                                                    */
  57. /*   /IE{xt}{:n}- don't check the file extension and don't check the  */
  58. /*                file format if n is 1                               */
  59. /*                (def.: 0, range: 0-1, default for n: 1)             */
  60. /*                                                                    */
  61. /*   /L:logFile - logfile is the name of the logfile :-)              */
  62. /*                This parameter is case-sensitive!                   */
  63. /*                def.: do not use a logfile                          */
  64. /*                                                                    */
  65. /*   /H         - show usage, you may also use                        */
  66. /*                /h, /?, /HELP, -h, -H, -HELP or -?                  */
  67. /*                (MAIN is not called!)                               */
  68. /*                                                                    */
  69. /*   /Silent    - suppress all messages (except error messages)       */
  70. /*                You should also use the parameter /L:logfile if you */
  71. /*                use this parameter!                                 */
  72. /*                You may also set the environment variable SILENT to */
  73. /*                "1" to suppress all messages.                       */
  74. /*                                                                    */
  75. /*   /NoSound   - suppress all sounds. You may also set the           */
  76. /*                environment variable SOUND to "0" to suppress the   */
  77. /*                sounds.                                             */
  78. /*                                                                    */
  79. /*   /NoAnsi    - do not use ANSI codes. You may also set the         */
  80. /*                environment variable ANSI to "0" to suppress the    */
  81. /*                use of ANSI codes.                                  */
  82. /*                                                                    */
  83. /*   /Trace     - turn TRACE on before calling MAIN. You may also     */
  84. /*                set the environment variable RXTTRACE to ON to      */
  85. /*                turn the TRACE mode for MAIN on.                    */
  86. /*                                                                    */
  87. /*-notes:                                                             */
  88. /*   You may also set the default values for the option parameters    */
  89. /*   (parameter in the format "/xx:n") in the environment variable    */
  90. /*   "UPCKREXX".                                                      */
  91. /*   Parameter for UPCKREXX.CMD overwrite the values from the         */
  92. /*   environment variable.                                            */
  93. /*   All parameter, except the parameter "sourceFile", are optional.  */
  94. /*   All parameter parts shown in {} are optional.                    */
  95. /*   You may use the parameter in any sequence.                       */
  96. /*                                                                    */
  97. /*   UPCKREXX _always_ creates a backup of the source file with the   */
  98. /*   extension "nnn" where nnn is a unique number.                    */
  99. /*                                                                    */
  100. /*-Warning: Check the target file carefully if using UPCKREXX for     */
  101. /*          unpacked REXX programs which include comments!!!          */
  102. /*                                                                    */
  103. /*-Limitations:                                                       */
  104. /*                                                                    */
  105. /* UPCKREXX can NOT handle files with one of the ASCII codes 01, 02,  */
  106. /* 03 or 04. These codes are used internally by UPCKREXX.             */
  107. /*                                                                    */
  108. /* UPCKREXX does NOT parse the source code like the REXX interpreter. */
  109. /* Therefore it handles a few constructs incorrect.                   */
  110. /* If there are string constants without leading and trailing quotes  */
  111. /* or double quotes in the sourcefile, the unpacked file may be       */
  112. /* invalid.                                                           */
  113. /*                                                                    */
  114. /* see also 'Limitations for compressing" in REXXCC.CMD.              */
  115. /*                                                                    */
  116. /* ------------------------------------------------------------------ */
  117. /* Planed future Enhancements:                                        */
  118. /*   - correct bugs if any exist                                      */
  119. /*   - delete the limitation for files with ASCII codes 01 to 04      */
  120. /*   - enhance performance                                            */
  121. /*   - split lines longer than n (/LL:n) into multiple lines          */
  122. /*   - add further logic for additional comments                      */
  123. /*   - add support for file masks (like *.cmd)                        */
  124. /*   - add support for OO REXX programs (I have NOT tested this       */
  125. /*     version with OO REXX programs)                                 */
  126. /*                                                                    */
  127. /* ------------------------------------------------------------------ */
  128. /* Based on TEMPLATE.CMD v3.02ß, TEMPLATE is (c) 1995 Bernd Schemmer, */
  129. /* Baeckerweg 48, D-60316 Frankfurt, Germany, Compuserve: 100104,613  */
  130. /*                                                                    */
  131. /* ------------------------------------------------------------------ */
  132.  
  133. /* ------------------------------------------------------------------ */
  134.  
  135.                         /* turn interactive trace off                 */
  136.   call trace 'off'
  137.  
  138.                   global. = ''  /* init the stem global. with ''      */
  139.  
  140.          global.__Version = 1.0          /* Version of UPCKREXX.CMD   */
  141.  
  142.        global.__SignOnMsg = 1   /* set to 0 if you do not want the    */
  143.                                 /* program start and end messages     */
  144.  
  145.          global.__NeedCID = 0   /* set to 1 if you need CID support   */
  146.  
  147.       global.__NeedColors = 1   /* set to 1 if you want colored msgs  */
  148.  
  149.   global.__NeedPatchCheck = 1   /* set to 1 if you want the program   */
  150.                                 /* to search for a patched version of */
  151.                                 /* this program                       */
  152.  
  153.                                 /* set default values for EXPOSELIST  */
  154.                                 /* if necessary                       */
  155. /*             exposeList = ''                                        */
  156.  
  157.                                 /* name of the routine for the        */
  158.                                 /* message handling.                  */
  159.                                 /* Note: Use '' if you want to use    */
  160.                                 /*       the hardcoded messages       */
  161. /*          global.__GetMsg = ''                                      */
  162.  
  163.                                 /* base number for the message        */
  164.                                 /* numbers (def.: 1000)               */
  165. /*          global.__BaseMsgNo = 1000                                 */
  166.              
  167.   prog.__STDOUT = 'STDOUT'        /* necessary for OO REXX            */
  168.   prog.__STDOUT = 'STDOUT'        /* necessary for OO REXX            */
  169.                                                                    /*!*/
  170. /***                End of variables to change                      ***/
  171. /*      HINT: The further program code is in the function MAIN        */
  172.  
  173. /***        End of Part 1 of the source code of TEMPLATE.CMD        ***/
  174.  
  175. /***       Start of Part 2 of the source code of TEMPLATE.CMD       ***/
  176.  
  177. /*************** DO NOT CHANGE THE FOLLOWING LINES ********************/
  178.  
  179.                         /* names of the global variables, which all   */
  180.                         /* procedures must know                       */
  181.   exposeList = 'prog. screen. I!. global. exposeList ' exposeList
  182.  
  183.                         /* check the type of the base message number  */
  184.                         /* SIGNAL on VALUE is off at this time!       */
  185.   if datatype( global.__BaseMsgNo, 'W' ) <> 1 then
  186.     global.__BaseMsgNo = 1000
  187.  
  188.                         /* init internal variables                    */
  189.   I!. = ''
  190.  
  191.                         /* save default STDOUT and STDERR             */
  192.   if symbol( 'prog.__STDOUT' ) = 'VAR' then
  193.     I!.__2 = prog.__STDOUT
  194.   if symbol( 'prog.__STDERR' ) = 'VAR' then
  195.     I!.__3 = prog.__STDERR
  196.  
  197.                         /* init the stems prog. & screen.             */
  198.   prog. = '' ; screen. = ''
  199.  
  200.                         /* reset the timer                            */
  201.   call time( 'R' )
  202.  
  203.                         /* restore default STDOUT and STDERR          */
  204.   prog.__STDOUT = I!.__2;    prog.__STDERR = I!.__3
  205.  
  206.  
  207.                         /* get the number of the first line with      */
  208.                         /* user code                                  */
  209.   call I!.__GetUserCode
  210.  
  211. /* ------------------------------------------------------------------ */
  212. /* install the error handler                                          */
  213.  
  214.                         /* break errors (CTRL-C)                      */
  215.   CALL ON HALT        NAME I!.__UserAbort
  216.                         /* syntax errors                              */
  217.   SIGNAL ON SYNTAX    NAME I!.__ErrorAbort
  218.                         /* using of not initialisized variables       */
  219.   SIGNAL ON NOVALUE   NAME I!.__ErrorAbort
  220.                         /*                                            */
  221.   SIGNAL ON FAILURE   NAME I!.__ErrorAbort
  222.                         /*                                            */
  223.   SIGNAL ON ERROR     NAME I!.__ErrorAbort
  224.                         /*                                            */
  225.   SIGNAL ON NOTREADY  NAME I!.__ErrorAbort
  226.  
  227. /* ------------------------------------------------------------------ */
  228. /* init the variables                                                 */
  229.  
  230.                         /* get & save the parameter                   */
  231.   parse arg I!.__RealParam 1 prog.__Param
  232.  
  233.                         /* init the variables                         */
  234.  
  235.                         /* define exit code values                    */
  236.   global.__ErrorExitCode = 255
  237.      global.__OKExitCode = 0
  238.  
  239.                         /* init the compound variable prog.           */
  240.   call I!.__InitProgStem
  241.  
  242.                         /* define the variables for CID programs      */
  243.   call I!.__InitCIDVars
  244.  
  245.                         /* init the program exit code                 */
  246.   prog.__ExitCode = global.__OKExitCode
  247.  
  248.                         /* check the parameter and env. variables     */
  249.                         /* This must run before I!.__InitColorVars!   */
  250.   call I!.__chkPandE
  251.  
  252.                         /* define the color variables                 */
  253.   call I!.__InitColorVars
  254.  
  255.                         /* check if there is a logfile parameter      */
  256.   call I!.__SetLogVars
  257.  
  258. /* ------------------------------------------------------------------ */
  259. /* show program start message                                         */
  260.  
  261.   call I!.__SignMsg
  262.  
  263. /* ------------------------------------------------------------------ */
  264.  
  265.                         /* check if there is a patched version of     */
  266.                         /* this program                               */
  267.   if global.__NeedPatchCheck <> 0 then
  268.     call I!.__CheckPatch
  269.  
  270. /* ------------------------------------------------------------------ */
  271.                         /* check for a help parameter                 */
  272.   if pos( translate( word( prog.__Param,1 ) ), ,
  273.           '/?/H/HELP/-?-H-HELP' ) <> 0 then
  274.   do
  275.     prog.__exitCode = 253
  276.  
  277.     call I!.__CallUserProc 1, 'ShowUsage'
  278.  
  279.     SIGNAL I!.__programEnd
  280.  
  281.   end /* pos( translate( ... */
  282.  
  283. /* ------------------------------------------------------------------ */
  284.  
  285.                         /* call the main procedure                    */
  286.   call I!.__CallUserProc 2, 'main' strip( prog.__Param )
  287.  
  288.                         /* set prog.__ExitCode to the return          */
  289.                         /* code of the function main, if any          */
  290.                         /* returned                                   */
  291.   if symbol( 'I!.__UserProcRC' ) == 'VAR' then
  292.     prog.__ExitCode = I!.__UserProcRC
  293.  
  294. /* ------------------------------------------------------------------ */
  295. /* house keeping                                                      */
  296.  
  297. I!.__ProgramEnd:
  298.  
  299.                                 /* call exit routines                 */
  300.   do while strip( prog.__exitRoutines ) <> ''
  301.     I!.__cer = word( prog.__ExitRoutines,1 )
  302.  
  303.                         /* delete the name of the routine from the    */
  304.                         /* list to avoid endless loops!               */
  305.     prog.__ExitRoutines = substr( prog.__ExitRoutines , ,
  306.                           Pos( I!.__cer, ,
  307.                                prog.__ExitRoutines ) + ,
  308.                           length( I!.__cer ) )
  309.  
  310.     call I!.__CallUserProc 1, I!.__cer
  311.  
  312.   end /* do while strip( prog.__ExitRoutines ) <> '' */
  313.  
  314.                                 /* restore the current directory      */
  315.   if symbol( 'prog.__CurDir' ) == 'VAR' then
  316.     call directory prog.__CurDir
  317.  
  318.                                 /* show sign off message              */
  319.   call I!.__SignMsg 'E'
  320.  
  321. EXIT prog.__ExitCode
  322.  
  323. /* ------------------------------------------------------------------ */
  324. /*-function: show the sign on or sign off message                     */
  325. /*                                                                    */
  326. /*-call:     I!.__SignMsg which                                       */
  327. /*                                                                    */
  328. /*-where:    which - 'E' - show the sign off message                  */
  329. /*                         else show the sign on message              */
  330. /*                                                                    */
  331. /*-returns:  nothing                                                  */
  332. /*                                                                    */
  333. I!.__SignMsg: PROCEDURE expose (exposeList)
  334.   if 1 == global.__SignOnMsg then
  335.   do
  336.  
  337.                         /* default: program start message             */
  338.     i = 12
  339.  
  340.     if arg(1) = 'E' then
  341.     do
  342.       i = 13
  343.                         /* program end message                        */
  344.       i!.__rc1 = prog.__ExitCode
  345.  
  346.                                 /* check if the exit code is decimal  */
  347.                                 /* and convert it to hexadecimal if   */
  348.                                 /* possible                           */
  349.       if dataType( prog.__ExitCode, 'W' ) then
  350.       do
  351.         if prog.__ExitCode < 0 then
  352.           prog.__ExitCode = 65536 + prog.__ExitCode
  353.         i!.__rc2 = D2X( prog.__ExitCode )
  354.       end /* if .. */
  355.  
  356.     end /* if arg(1) = 'E' then */
  357.  
  358.     screen.__CurColor = screen.__SignOnColor
  359.     call Log I!.__GetMsg( i, prog.__Name, global.__Version, date(),,
  360.                           time(), i!.__rc1, i!.__rc2 )
  361.     screen.__CurColor = screen.__NormalColor
  362.   end /* if 1 == global.__SignOnMsg then */
  363. RETURN
  364.  
  365. /* ------------------------------------------------------------------ */
  366. /*-function: call a user defined routine                              */
  367. /*           (avoid errors if the routine is not defined)             */
  368. /*                                                                    */
  369. /*-call:     I!.__CallUserProc errorAction, procName {procParameter}  */
  370. /*                                                                    */
  371. /*-where:    errorAction - action, if procName is not defined         */
  372. /*                         0: do nothing (only set the RC)            */
  373. /*                         1: show a warning and set the RC           */
  374. /*                         2: abort the program                       */
  375. /*           procName - name of the procedure                         */
  376. /*           procParameter - parameter for the procedure              */
  377. /*                                                                    */
  378. /*-returns:  1 - ok                                                   */
  379. /*           0 - procname not found                                   */
  380. /*                                                                    */
  381. /*-output:   I!.__UserProcRC - Returncode of the called procedure     */
  382. /*                             (dropped if the proedure don't         */
  383. /*                             return a value)                        */
  384. /*                                                                    */
  385. I!.__CallUserProc: PROCEDURE expose (exposeList) result rc sigl
  386.   parse arg I!.__ErrorAction , I!.__ProcN I!.__ProcP
  387.  
  388.   I!.__thisRC = 0
  389.   drop I!.__UserProcRC
  390.  
  391.   iLine = 'call ' I!.__ProcN
  392.   if prog.__Trace = 1 & I!.__ProcN = 'main' then
  393.     iLine = 'trace ?a;'|| iLine
  394.  
  395. /** DO NOT CHANGE, ADD OR DELETE ONE OF THE FOLLOWING SEVEN LINES!!! **/
  396.   I!.__ICmdLine = GetLineNo()+2+(I!.__ProcP <> '')*2               /*!*/
  397.   if I!.__ProcP = '' then                                          /*!*/
  398.     interpret iLine                                                /*!*/
  399.   else                                                             /*!*/
  400.     interpret iLine "I!.__ProcP"                                   /*!*/
  401. /** DO NOT CHANGE, ADD OR DELETE ONE OF THE PRECEEDING SEVEN LINES!! **/
  402.  
  403. /* Caution: The CALL statement changes the variable RESULT!           */
  404.   I!.__dummy = trace( 'off' )
  405.  
  406.   I!.__thisRC = 1
  407.   if symbol( 'RESULT' ) == 'VAR' then
  408.     I!.__UserProcRC = value( 'RESULT' )
  409.     
  410.                     /* this label is used if the interpret command    */
  411.                     /* ends with an error                             */
  412. I!.__CallUserProc2:
  413.  
  414.   if 0 == I!.__ThisRC then
  415.     select
  416.  
  417.       when 1 == I!.__ErrorAction then
  418.         call ShowWarning I!.__GetMsg( 1 , I!.__ProcN )
  419.  
  420.       when 2 == I!.__ErrorAction then
  421.         call ShowError global.__ErrorExitCode , ,
  422.                        I!.__GetMsg( 1, I!.__ProcN )
  423.       otherwise
  424.         nop
  425.  
  426.     end /* select */
  427.  
  428. RETURN I!.__thisRC
  429.  
  430. /* ------------------------------------------------------------------ */
  431. /*-function: set the variables for the logfile handling               */
  432. /*                                                                    */
  433. /*-call:     I!.__SetLogVars                                          */
  434. /*                                                                    */
  435. /*-input:    prog.__Param - parameter for the program                 */
  436. /*                                                                    */
  437. /*-output:   prog.__LogFile     - name of the logfile (or NUL)        */
  438. /*           prog.__LogSTDERR   - string to direct STDERR into the    */
  439. /*                                logfile                             */
  440. /*           prog.__LogSTDOUT   - string to direct STDOUT into the    */
  441. /*                                logfile                             */
  442. /*           prog.__LogAll      - string to direct STDOUT and STDERR  */
  443. /*                                into the logfile                    */
  444. /*           prog.__LogFileParm - string to inherit the logfile       */
  445. /*                                parameter to a child CMD            */
  446. /*           prog.__Param       - program parameter without the       */
  447. /*                                logfile parameter                   */
  448. /*                                                                    */
  449. /*-returns:  nothing                                                  */
  450. /*                                                                    */
  451. I!.__SetLogVars: PROCEDURE expose (exposeList)
  452.   parse var prog.__Param prog.__param '/L:' logFileName ' ' rest
  453.  
  454.   prog.__param = prog.__Param rest
  455.  
  456.                         /* avoid an error if the drive is not ready   */
  457.   SIGNAL OFF NOTREADY
  458.  
  459.                         /* default log device is the NUL device       */
  460.   prog.__LogFile = 'NUL'
  461.  
  462.   if logFileName <> '' then
  463.   do
  464.                         /* check if we can write to the logfile       */
  465.     logStatus = stream( logFileName, 'c', 'OPEN WRITE')
  466.     if logStatus <> 'READY:' then
  467.     do
  468.       prog.__LogFileParm = ''
  469.  
  470.       call ShowWarning I!.__GetMsg( 2, logFileName, logStatus )
  471.  
  472.     end /* if logStatus <> 'READY:' then */
  473.     else
  474.     do
  475.                         /* close the logfile                          */
  476.       call stream logFileName, 'c', 'CLOSE'
  477.  
  478.                         /* get the fully qualified name of the        */
  479.                         /* logfile                                    */
  480.       prog.__LogFile = translate( stream( logFileName, 'c', 'QUERY EXIST' ) )
  481.  
  482.       prog.__LogFileParm = '/L:' || prog.__LogFile
  483.     end /* else */
  484.   end /* if prog.__LogFile <> '' then */
  485.  
  486.                         /* variable to direct STDOUT of an OS/2       */
  487.                         /* program into the logfile                   */
  488.   prog.__LogSTDOUT = ' 1>>' || prog.__LogFile
  489.  
  490.                         /* variable to direct STDERR of an OS/2       */
  491.                         /* program into the logfile                   */
  492.   prog.__LogSTDERR = ' 2>>' || prog.__LogFile
  493.  
  494.                         /* variable to direct STDOUT and STDERR of    */
  495.                         /* an OS/2 program into the log file          */
  496.   prog.__LogALL = prog.__LogSTDERR || ' 1>>&2'
  497.  
  498. RETURN
  499.  
  500. /* ------------------------------------------------------------------ */
  501. /*-function: check the parameter and the environment variables for    */
  502. /*           the runtime system                                       */
  503. /*                                                                    */
  504. /*-call:     I!.__chkPandE                                            */
  505. /*                                                                    */
  506. /*-input:    prog.__Param - parameter for the program                 */
  507. /*           prog.__env - name of the environment                     */
  508. /*                                                                    */
  509. /*-output:   prog.__QuietMode - 1 if parameter '/Silent' found        */
  510. /*                              or environment variable SILENT set    */
  511. /*           prog.__NoSound   - 1 if parameter '/NoSound' found       */
  512. /*                              or environment variable SOUND set     */
  513. /*           screen.          - "" if parameter '/NoANSI' found       */
  514. /*                              or environment variable ANSI set      */
  515. /*           prog.__Param     - remaining parameter for the procedure */
  516. /*                              MAIN.                                 */
  517. /*           prog.__Trace     - 1 if parameter '/Trace' found         */
  518. /*                              or if the environment variable        */
  519. /*                              RXTTRACE is set to MAIN               */
  520. /*                                                                    */
  521. /*-returns:  nothing                                                  */
  522. /*                                                                    */
  523. I!.__chkPandE: PROCEDURE expose (exposeList)
  524.  
  525.   global.__verbose = value( 'VERBOSE' ,, prog.__env )
  526.  
  527.   o!.0 = 4                              /* no. of known parameters    */
  528.                                         /* and environment variables  */
  529.  
  530.   o!.1.parm = '/SILENT'                 /* parameter name             */
  531.   o!.1.env  = 'SILENT'                  /* name of the env. var       */
  532.   o!.1.vals = 'ON 1'                    /* possible values for the    */
  533.                                         /* environment variable       */
  534.   o!.1.stmt = 'prog.__QuietMode=1'      /* statement to execute       */
  535.                                         /* if this parameter was      */
  536.                                         /* entered or the environment */
  537.                                         /* variable is set            */
  538.  
  539.   o!.2.parm = '/NOSOUND'                /* turn sound off             */
  540.   o!.2.env  = 'SOUND'
  541.   o!.2.vals = 'OFF 0'
  542.   o!.2.stmt = 'prog.__NoSound=1'
  543.  
  544.   o!.3.parm = '/NOANSI'                 /* turn ANSI support off      */
  545.   o!.3.env  = 'ANSI'
  546.   o!.3.vals = 'OFF 0'
  547.   o!.3.stmt = 'global.__NeedColors=0'
  548.  
  549.   o!.4.parm = '/TRACE'          /* exeucte MAIN in single step mode   */
  550.   o!.4.env  = 'RXTTRACE'
  551.   o!.4.vals = 'MAIN'
  552.   o!.4.stmt = 'prog.__Trace=1'
  553.  
  554.   do i = 1 to o!.0
  555.                         /* check the parameter                        */
  556.     j = wordPos( o!.i.parm, translate( prog.__Param ) )
  557.     if j = 0 then       /* no parameter found, check the env. var     */
  558.       j = wordPos( translate( value( o!.i.env ,, prog.__env ) ) ,,
  559.                     o!.i.vals )
  560.     else                /* parameter found, delete the parameter      */
  561.       prog.__Param = strip( delWord( prog.__Param, j,1 ) )
  562.  
  563.                         /* if j is not zero either the parameter was  */
  564.                         /* found or the environment variable is set   */
  565.     if j <> 0 then
  566.       interpret o!.i.stmt
  567.   end /* do i = 1 to o!.0 */
  568.  
  569. RETURN
  570.  
  571. /* ------------------------------------------------------------------ */
  572. /*-function:  convert a file or directory name to OS conventions      */
  573. /*            by adding a leading and trailing quote or double quote  */
  574. /*                                                                    */
  575. /*-call:      convertNameToOS dir_or_file_name                        */
  576. /*                                                                    */
  577. /*-where:     dir_or_file_name = name to convert                      */
  578. /*                                                                    */
  579. /*-returns:   converted file or directory name                        */
  580. /*                                                                    */
  581. ConvertNameToOS: PROCEDURE expose (exposeList)
  582.   parse arg fn
  583.  
  584.   if pos( '"', fn ) == 0 then
  585.     fn = '"' || fn || '"'
  586.   else if pos( "'", fn ) == 0 then
  587.     fn = "'" || fn || "'"
  588.  
  589. RETURN fn
  590.  
  591. /* ------------------------------------------------------------------ */
  592. /*-function: flush the default REXX queue                             */
  593. /*                                                                    */
  594. /*-call:     FlushQueue                                               */
  595. /*                                                                    */
  596. /*-returns:  ''                                                       */
  597. /*                                                                    */
  598. FlushQueue: /* PROCEDURE expose (exposeList) */
  599.   do while QUEUED() <> 0
  600.     parse pull
  601.   end /* do while QUEUED() <> 0 */
  602. RETURN ''
  603.  
  604. /* ------------------------------------------------------------------ */
  605. /*-function: include a file if it exists                              */
  606. /*                                                                    */
  607. /*-call:     TryInclude( IncludeFile )                                */
  608. /*                                                                    */
  609. /*-where:    IncludeFile = name of the file to include                */
  610. /*                                                                    */
  611. /*-output:   prog.__rc = 0 - include file executed                    */
  612. /*           else: file not found                                     */
  613. /*                                                                    */
  614. /*-returns:  ''                                                       */
  615. /*                                                                    */
  616. TryInclude:
  617.   parse upper arg I!.__IncFileName
  618.   prog.__rc = 1
  619.  
  620.   if I!.__IncFileName = '' then
  621.     RETURN ''
  622.  
  623.   if stream( I!.__IncFileName,'c','QUERY EXIST' ) = '' then
  624.     RETURN ''
  625.  
  626.   prog.__rc = 0
  627.  
  628.   /* execute INCLUDE */
  629.  
  630. /* ------------------------------------------------------------------ */
  631. /*-function: include a file                                           */
  632. /*                                                                    */
  633. /*-call:     Include( IncludeFile )                                   */
  634. /*                                                                    */
  635. /*-where:    IncludeFile = name of the file to include                */
  636. /*                                                                    */
  637. /*-returns:  ''                                                       */
  638. /*                                                                    */
  639. Include:
  640.   parse upper arg I!.__IncFileName
  641.  
  642.                         /* check if the include file exists           */
  643.   if stream( I!.__IncFileName, 'c', 'QUERY EXIST' ) == '' then
  644.     call ShowError global.__ErrorExitCode, ,
  645.                    I!.__GetMsg( 3, I!.__IncFileName )
  646.  
  647.                         /* read and interpret the include file        */
  648.   do I!.__IncLineNO = 1 while lines( I!.__IncFileName ) <> 0
  649.     I!.__IncCurLine = ''
  650.                         /* save the absolute position of the start of */
  651.                         /* this line for the error handler            */
  652.     I!.__IncCurLinePos = stream(I!.__IncFileName,'c','SEEK +0')
  653.  
  654.                         /* handle multi line statements               */
  655.     do forever
  656.       I!.__IncCurLine = I!.__IncCurLine ,
  657.                         strip( lineIn( I!.__IncFileName ) )
  658.  
  659.       if right( I!.__IncCurLine,1 ) == ',' then
  660.       do
  661.                         /* statement continues on the next line       */
  662.         if lines( I!.__IncFileName ) == 0 then
  663.           call ShowError global.__ErrorExitCode ,,
  664.                I!.__GetMsg( 4, I!.__IncFileName )
  665.         else
  666.           I!.__IncCurLine = substr( I!.__IncCurLine,1, ,
  667.                                     length( I!.__IncCurLine )-1 )
  668.       end /* if right( ... */
  669.       else
  670.         leave
  671.     end /* do forever */
  672.  
  673.     I!.__IncActive = 1
  674.     interpret I!.__IncCurLine
  675.     I!.__IncActive = 0
  676.  
  677.   end /* do I!.__IncLineNO = 1 while lines( I!.__IncFileName ) <> 0 ) */
  678.  
  679.                         /* close the include file!                    */
  680.   call stream I!.__IncFileName, 'c', 'CLOSE'
  681.  
  682. RETURN ''
  683.  
  684. /* ------------------------------------------------------------------ */
  685. /*-function: init color variables                                     */
  686. /*                                                                    */
  687. /*-call:     I!.__InitColorVars                                       */
  688. /*                                                                    */
  689. /*-returns:  nothing                                                  */
  690. /*                                                                    */
  691. I!.__InitColorVars: /* PROCEDURE expose (exposeList) */
  692.  
  693.   if 1 == global.__NeedColors then
  694.   do
  695.  
  696.                         /* delete rest of the line                    */
  697.     screen.__DelEOL      = '1B'x || '[K'
  698.  
  699.                         /* save the cursor position                   */
  700.     screen.__SavePos     = '1B'x || '[s'
  701.  
  702.                         /* restore the cursor position                */
  703.     screen.__RestPos     = '1B'x || '[u'
  704.  
  705.                         /* define color attributes                    */
  706.     screen.__AttrOff     = '1B'x || '[0;m'
  707.     screen.__Highlight   = '1B'x || '[1;m'
  708.     screen.__normal      = '1B'x || '[2;m'
  709.     screen.__blink       = '1B'x || '[5;m'
  710.     screen.__invers      = '1B'x || '[7;m'
  711.     screen.__invisible   = '1B'x || '[8;m'
  712.  
  713.                         /* define foreground color variables          */
  714.     screen.__fgBlack     = '1B'x || '[30;m'
  715.     screen.__fgRed       = '1B'x || '[31;m'
  716.     screen.__fgGreen     = '1B'x || '[32;m'
  717.     screen.__fgYellow    = '1B'x || '[33;m'
  718.     screen.__fgBlue      = '1B'x || '[34;m'
  719.     screen.__fgMagnenta  = '1B'x || '[35;m'
  720.     screen.__fgCyan      = '1B'x || '[36;m'
  721.     screen.__fgWhite     = '1B'x || '[37;m'
  722.  
  723.                         /* define background color variables          */
  724.     screen.__bgBlack     = '1B'x || '[40;m'
  725.     screen.__bgRed       = '1B'x || '[41;m'
  726.     screen.__bgGreen     = '1B'x || '[42;m'
  727.     screen.__bgYellow    = '1B'x || '[43;m'
  728.     screen.__bgBlue      = '1B'x || '[44;m'
  729.     screen.__bgMagnenta  = '1B'x || '[45;m'
  730.     screen.__bgCyan      = '1B'x || '[46;m'
  731.     screen.__bgWhite     = '1B'x || '[47;m'
  732.  
  733.                         /* define color variables                     */
  734.     screen.__ErrorColor  = screen.__AttrOff || screen.__Highlight || ,
  735.                            screen.__FGYellow || screen.__bgRed
  736.     screen.__NormalColor = screen.__AttrOff ||                       ,
  737.                            screen.__fgWhite || screen.__bgBlack
  738.     screen.__DebugColor  = screen.__AttrOff || screen.__Highlight || ,
  739.                            screen.__fgBlue || screen.__bgWhite
  740.     screen.__PromptColor = screen.__AttrOff || screen.__Highlight || ,
  741.                            screen.__fgYellow || screen.__bgMagnenta
  742.  
  743. /* +++++++++++++++ DO NOT USE THE FOLLOWING COLORS! +++++++++++++++++ */
  744.     screen.__SignOnColor = screen.__AttrOff || screen.__Highlight || ,
  745.                            screen.__fggreen || screen.__bgBlack
  746.     screen.__PatchColor  = screen.__AttrOff || screen.__Highlight || ,
  747.                            screen.__fgcyan || screen.__bgRed
  748. /* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
  749.  
  750.                             /* set the default color                  */
  751.     screen.__CurColor    = screen.__NormalColor
  752.  
  753.                             /* turn ANSI word wrapping on             */
  754.     if prog.__QuietMode <> 1 then
  755.       call charout prog.__STDOUT, '1B'x || '[7h'
  756.  
  757.   end /* if 1 == global.__NeedColors then */
  758.  
  759. RETURN
  760.  
  761. /* ------------------------------------------------------------------ */
  762. /*-function: init the stem prog.                                      */
  763. /*                                                                    */
  764. /*-call:     I!.__InitProgStem                                        */
  765. /*                                                                    */
  766. /*-returns:  nothing                                                  */
  767. /*                                                                    */
  768. /*-Note:     DO NOT ADD ANY CODE TO THIS ROUTINE!                     */
  769. /*                                                                    */
  770. I!.__InitProgStem: /* PROCEDURE expose (exposeList) */
  771.   prog.__Defparms = ' {/L:logfile} {/H} {/Silent} {/NoAnsi} {/NoSound} {/Trace}'
  772.  
  773.                         /* get drive, path and name of this program   */
  774.   parse upper source . . prog.__FullName
  775.         prog.__Drive = filespec( 'D', prog.__FullName )
  776.          prog.__Path = filespec( 'P',  prog.__FullName )
  777.          prog.__Name = filespec( 'N',  prog.__FullName )
  778.           prog.__Env = 'OS2ENVIRONMENT'
  779.        prog.__CurDir = translate( directory() )
  780.                         /* version of TEMPLATE.CMD                    */
  781.       prog.__Version = 'V3.02'
  782.     prog.__UserAbort = 1        /* allow user aborts                  */
  783.  prog.__ExitRoutines = ''       /* list of routines to execute at     */
  784.                                 /* program end                        */
  785.  
  786.                                 /* init the variables for cols and    */
  787.                                 /* rows                               */
  788.   prog.__ScreenCols = 80
  789.   prog.__ScreenRows = 25
  790.  
  791.                                 /* install a local error handler      */
  792.   SIGNAL ON SYNTAX Name I!.__InitProgStem1
  793.                                 /* try to call SysTextScreenSize()    */
  794.   parse value SysTextScreenSize() with prog.__ScreenRows prog.__ScreenCols
  795.  
  796. I!.__InitProgStem1:
  797.  
  798. RETURN
  799.  
  800. /* ------------------------------------------------------------------ */
  801. /*-function: init the variables for CID programs (only if the value   */
  802. /*           of the variable global.__NeedCID is 1)                   */
  803. /*                                                                    */
  804. /*-call:     I!.__InitCIDVars                                         */
  805. /*                                                                    */
  806. /*-returns:  nothing                                                  */
  807. /*                                                                    */
  808. /*-Note:     DO NOT ADD ANY CODE TO THIS ROUTINE!                     */
  809. /*           Returncodes as defined by LCU 2.0                        */
  810. /*                                                                    */
  811. I!.__InitCIDVars: /* PROCEDURE expose (exposeList) exposeList CIDRC. */
  812.  
  813.   if 1 == global.__NeedCID then
  814.   do
  815.                         /* define return codes for CID programs       */
  816.     CIDRC.__successful_program_termination  = C2D('0000'x, 2);
  817.     CIDRC.__successful_log_warning_message  = C2D('0004'x, 2);
  818.     CIDRC.__successful_log_error_Message    = C2D('0008'x, 2);
  819.     CIDRC.__successful_log_severe_error     = C2D('0012'x, 2);
  820.  
  821.     CIDRC.__data_resource_not_found         = C2D('0800'x, 2);
  822.     CIDRC.__data_resource_already_in_use    = C2D('0804'x, 2);
  823.     CIDRC.__data_resource_Noauthorization   = C2D('0808'x, 2);
  824.     CIDRC.__data_path_not_found             = C2D('0812'x, 2);
  825.     CIDRC.__product_not_configured          = C2D('0816'x, 2);
  826.  
  827.     CIDRC.__storage_medium_exception        = C2D('1200'x, 2);
  828.     CIDRC.__device_Not_Ready                = C2D('1204'x, 2);
  829.     CIDRC.__not_enough_diskspace            = C2D('1208'x, 2);
  830.  
  831.     CIDRC.__incorrect_program_invocation    = C2D('1600'x, 2);
  832.     CIDRC.__unexpected_condition            = C2D('1604'x, 2);
  833.     CIDRC.__successfull_reboot              = C2D('FE00'x, 2);
  834.     CIDRC.__successfull_reboot_with_warning = C2D('FE04'x, 2);
  835.     CIDRC.__successfull_reboot_with_errmsg  = C2D('FE08'x, 2);
  836.     CIDRC.__successfull_reboot_with_server_errMsg = C2D('FE12'x, 2);
  837.  
  838.  
  839.                         /* xx = next state of the program             */
  840. /*    CIDRC.__successfull_reboot_with_callback = C2D('FFxx'x, 2);     */
  841.  
  842.                         /* define exit code values                    */
  843.     global.__ErrorExitCode = CIDRC.__unexpected_condition
  844.        global.__OKExitCode = CIDRC.__successful_program_termination
  845.  
  846.                         /* add the stem CIDRC. to the exposeList      */
  847.     exposeList = exposeList || ' CIDRC. '
  848.   end /* if 1 == global.__NeedCID then */
  849.  
  850. RETURN
  851.  
  852.  
  853. /***        End of Part 2 of the source code of TEMPLATE.CMD        ***/
  854.  
  855. /***       Start of Part 3 of the source code of TEMPLATE.CMD       ***/
  856.  
  857. /* ------------------------------------------------------------------ */
  858. /*-function:  load a dll                                              */
  859. /*                                                                    */
  860. /*-call:                                                              */
  861. /*   thisRC = LoadDll( registerFunction, dllName, entryPoint,         */
  862. /*                     ,{deRegisterFunction},{checkFunction}          */
  863. /*                     ,{IgnoreRxFuncAddRC},{RegisterErrorRC}         */
  864. /*                     ,{errorAction}                                 */
  865. /*                                                                    */
  866. /*-where:                                                             */
  867. /*         registerFunc = name of the dll init function               */
  868. /*                        (e.g. "SysLoadFuncs")                       */
  869. /*              dllName = name of the dll                             */
  870. /*                        (e.g. "REXXUTIL")                           */
  871. /*           entryPoint = entryPoint for the dll init function        */
  872. /*                        (e.g. "SysLoadFuncs")                       */
  873. /*       deRegisterFunc = name of the dll exit function               */
  874. /*                        (e.g. "SysDropFuncs")                       */
  875. /*                        If this parameter is entered, the           */
  876. /*                        deRegisterFunction is automaticly called    */
  877. /*                        at program end if the loading of the dll    */
  878. /*                        was successfull.                            */
  879. /*            checkFunc = function which must be loaded if the dll is */
  880. /*                        loaded (def.: none -> always load the dll)  */
  881. /*                        Note:                                       */
  882. /*                        Do not use the registerFunction for this    */
  883. /*                        parameter! A good candidate for this        */
  884. /*                        parameter is the deRegisterFunction.        */
  885. /*    IgnoreRxFuncAddRC = 1: ignore the rc from rxFuncAdd             */
  886. /*                        0: do not ignore the rc from rxFuncAdd      */
  887. /*                        (def.: 0)                                   */
  888. /*                        Note: Always set this parameter to 1 if     */
  889. /*                              using the program under WARP.         */
  890. /*       RegisterErroRC = returncode of the dll init function         */
  891. /*                        indicating a load error                     */
  892. /*                        (def. none, -> ignore the returncode of the */
  893. /*                         dll init function)                         */
  894. /*           actionCode = 1: abort program if loading failed          */
  895. /*                        0: do not abort program if loading failed   */
  896. /*                        (def.: 1)                                   */
  897. /*                                                                    */
  898. /*-returns:                                                           */
  899. /*   0 - loading failed                                               */
  900. /*   1 - dll loaded                                                   */
  901. /*   2 - dll already loaded                                           */
  902. /*                                                                    */
  903. /*-Note:                                                              */
  904. /*   See the routine MAIN for some examples for using LoadDLL.        */
  905. /*   LoadDLL can only handle dlls with an init function to register   */
  906. /*   the further routines in the dll (like the function SysLoadFuncs  */
  907. /*   in the dll REXXUTIL).                                            */
  908. /*                                                                    */
  909. LoadDll:  PROCEDURE expose (exposeList)
  910.   parse arg regFunc , ,
  911.             dllName , ,
  912.             entryPoint , ,
  913.             deregFunc , ,
  914.             checkFunc , ,
  915.             ignoreRXFuncAddRC, ,
  916.             registerErrorRC, ,
  917.             errorAction
  918.  
  919.                         /* check the necessary parameters             */
  920.   if '' == entryPoint | '' == dllName | '' == regFunc then
  921.     call ShowError global.__ErrorExitCode, I!.__GetMsg( 6 )
  922.  
  923.   if '' == ignoreRXFuncAddRC then
  924.     ignoreRXFuncAddRc = 0
  925.  
  926.   if '' == errorAction then
  927.     errorAction = 1
  928.  
  929.   I!.__LoadDLLRc = 0
  930.                         /* if the 'checkFunc' is missing, we      */
  931.                         /* assume that the dll is not loaded          */
  932.   dllNotLoaded = 1
  933.   if ( checkFunc <> '' ) then
  934.     dllNotLoaded = rxFuncQuery( checkFunc )
  935.  
  936.   if dllNotLoaded then
  937.   do
  938.                         /* first deRegister the function        v3.01 */
  939.     call rxFuncDrop regFunc                                  /* v3.01 */
  940.  
  941.                         /* load the dll and register the init         */
  942.                         /* function of the dll                        */
  943.     rxFuncAddRC = rxFuncAdd( regFunc, dllName, entryPoint )
  944.  
  945.     if \ rxFuncAddRC | ignoreRxFuncAddRC then
  946.     do
  947.  
  948.       I!.__DllInitRC = 0
  949.       if I!.__CallUserProc( 0, regFunc ) == 0 then
  950.         I!.__DllInitRC = 'ERROR'
  951.  
  952.       if ( registerErrorRC <> '' & I!.__DLLInitRC == registerErrorRC ) | ,
  953.          ( I!.__DllInitRC == 'ERROR' ) then
  954.         nop
  955.       else
  956.       do
  957.                         /* add the dll deregister function to the     */
  958.                         /* program exit routine list                  */
  959.         if DeregFunc <> '' then
  960.           if \ rxFuncQuery( DeregFunc ) then
  961.             prog.__ExitRoutines = prog.__ExitRoutines || ' ' || ,
  962.                                   DeregFunc
  963.  
  964.         I!.__LoadDLLRc = 1
  965.       end /* else */
  966.     end /* if \ rxFuncAddRC | ignoreRxFuncAddRC then */
  967.   end /* if dllNotLoaded then */
  968.   else
  969.     I!.__LoadDLLRc = 2  /* dll is already loaded                      */
  970.  
  971.   if 1 == errorAction & 0 == I!.__LoadDLLRC then
  972.     call ShowError global.__ErrorExitCode,,
  973.                    I!.__GetMsg( 5, dllName )
  974.  
  975. RETURN I!.__LoadDLLRc
  976.  
  977. /* ------------------------------------------------------------------ */
  978. /*-function: show a string with word wrapping                         */
  979. /*                                                                    */
  980. /*-call:     showString Prefix, thisString                            */
  981. /*                                                                    */
  982. /*-where:                                                             */
  983. /*           Prefix = prefix for the first line (e.g. "*-*" or "#" to */
  984. /*                    use # leading blanks, # = 1 ... n )             */
  985. /*           thisString - string to print                             */
  986. /*                                                                    */
  987. /*-returns:  ''                                                       */
  988. /*                                                                    */
  989. ShowString: PROCEDURE EXPOSE (exposeList)
  990.   parse arg Prefix, thisStr
  991.  
  992.   maxLineL = prog.__ScreenCols-4
  993.  
  994.   if datatype( prefix, 'W' ) == 1 then
  995.     prefix = copies( ' ' , prefix )
  996.  
  997.   maxWordL = maxLineL - length( prefix )
  998.  
  999.   thisRC = 0
  1000.   curStr = ''
  1001.  
  1002.   do i = 1 to words( thisStr)
  1003.     pStr = 0
  1004.  
  1005.     curStr = curStr || word( thisStr, i ) || ' '
  1006.  
  1007.     if length( curStr || prefix ||  word( thisStr, i+1 ) ) > maxLineL then
  1008.       pStr = 1
  1009.  
  1010.     if 1 == pStr | i == words( thisStr ) then
  1011.     do
  1012.       if length( prefix || curStr ) > prog.__ScreenCols then
  1013.       do until curStr = ''
  1014.         parse var curStr curStr1 =(maxWordL) ,
  1015.                                   curStr
  1016.         call log left( prefix || curStr1, prog.__ScreenCols )
  1017.         prefix = copies( ' ', length( prefix ) )
  1018.       end /* if length( ... then do until */
  1019.       else
  1020.         call Log left( prefix || curStr, prog.__ScreenCols )
  1021.  
  1022.       curStr = ''
  1023.       prefix = copies( ' ', length( prefix ) )
  1024.     end /* if 1 == pStr | ... */
  1025.  
  1026.   end /* do i = 1 to words( thisStr */
  1027.  
  1028. RETURN ''
  1029.  
  1030. /* ------------------------------------------------------------------ */
  1031. /*-function: show a warning message                                   */
  1032. /*                                                                    */
  1033. /*-call:     showWarning message                                      */
  1034. /*                                                                    */
  1035. /*-where:    warningMessage - warning Message                         */
  1036. /*                                                                    */
  1037. /*-returns:  ''                                                       */
  1038. /*                                                                    */
  1039. ShowWarning: PROCEDURE expose (exposeList)
  1040.   parse arg wMsg
  1041.  
  1042.   screen.__CurColor = screen.__ErrorColor
  1043.  
  1044.   call I!.__LogStart
  1045.  
  1046.   call ShowString I!.__GetMsg( 7 ) || ' ', wMsg || '!'
  1047.   call I!.__LogSeparator
  1048.  
  1049.   screen.__CurColor = screen.__NormalColor
  1050.   call Log
  1051.  
  1052. RETURN ''
  1053.  
  1054. /* ------------------------------------------------------------------ */
  1055. /*-function: show an error message and end the program                */
  1056. /*                                                                    */
  1057. /*-call:     ShowError exitCode, errorMessage                         */
  1058. /*                                                                    */
  1059. /*-where:    ExitCode - no of the error (= program exit code)         */
  1060. /*           errorMessage - error Message                             */
  1061. /*                                                                    */
  1062. /*-returns:  nothing                                                  */
  1063. /*                                                                    */
  1064. /*-Note:     THIS ROUTINE WILL NOT COME BACK!!!                       */
  1065. /*                                                                    */
  1066. ShowError: PROCEDURE expose (exposeList)
  1067.   parse arg prog.__ExitCode, I!.__errMsg
  1068.  
  1069.   I!.__QM = prog.__QuietMode
  1070.                         /* turn quiet mode off                        */
  1071.   prog.__QuietMode = ''
  1072.  
  1073.   screen.__CurColor = screen.__ErrorColor
  1074.  
  1075.   call I!.__LogStart
  1076.  
  1077.   call Log left( I!.__GetMsg( 8, prog.__Name , prog.__ExitCode ) ,,
  1078.                  prog.__ScreenCols )
  1079.   call ShowString 1, I!.__errMsg || '!'
  1080.  
  1081.   call I!.__LogSeparator
  1082.   call Log
  1083.                         /* restore quiet mode status                  */
  1084.   prog.__QuietMode = I!.__QM
  1085.  
  1086.   if prog.__NoSound <> 1 then
  1087.   do
  1088.     call beep 537,300
  1089.     call beep 237,300
  1090.     call beep 537,300
  1091.   end /* if prog.__NoSound <> 1 then */
  1092.  
  1093. SIGNAL I!.__ProgramEnd
  1094.  
  1095. RETURN
  1096.  
  1097. /* ------------------------------------------------------------------ */
  1098. /*-function: log a debug message and clear the rest of the line       */
  1099. /*                                                                    */
  1100. /*-call:     logDebugMsg message                                      */
  1101. /*                                                                    */
  1102. /*-where:    message - message to show                                */
  1103. /*                                                                    */
  1104. /*-returns:  ''                                                       */
  1105. /*                                                                    */
  1106. /*-Note:     You do not need the 'call' keyword to use this routine.  */
  1107. /*                                                                    */
  1108. LogDebugMsg: PROCEDURE expose (exposeList)
  1109.   if global.__verbose <> '' then
  1110.   do
  1111.     parse arg dMsg
  1112.     screen.__CurColor = screen.__DebugColor
  1113.     call Log '+++' dMsg
  1114.     screen.__CurColor = screen.__NormalColor
  1115.   end /* if global.__verbose <> '' then */
  1116. RETURN ''
  1117.  
  1118. /* ------------------------------------------------------------------ */
  1119. /*-function: write a CR/LF and a separator line to the screen and to  */
  1120. /*           the logfile                                              */
  1121. /*                                                                    */
  1122. /*-call:     I!.__LogStart                                            */
  1123. /*                                                                    */
  1124. /*-returns:  nothing                                                  */
  1125. /*                                                                    */
  1126.  
  1127. /* ------------------------------------------------------------------ */
  1128. /*-function: write a separator line to the screen and to the logfile  */
  1129. /*                                                                    */
  1130. /*-call:     I!.__LogSeparator                                        */
  1131. /*                                                                    */
  1132. /*-returns:  nothing                                                  */
  1133. /*                                                                    */
  1134. I!.__LogStart:
  1135.   call log
  1136. I!.__LogSeparator:
  1137.   call Log ' ' || left('-', prog.__ScreenCols-2, '-' ) || ' '
  1138. RETURN
  1139.  
  1140. /* ------------------------------------------------------------------ */
  1141. /*-function: log a message and clear the rest of the line             */
  1142. /*                                                                    */
  1143. /*-call:     log message                                              */
  1144. /*                                                                    */
  1145. /*-where:    message - message to show                                */
  1146. /*                                                                    */
  1147. /*-returns:  ''                                                       */
  1148. /*                                                                    */
  1149. /*-Note:     You do not need the 'call' keyword to use this routine.  */
  1150. /*                                                                    */
  1151. Log: PROCEDURE expose (exposeList)
  1152.   parse arg msg
  1153.  
  1154.   logmsg = msg
  1155.   do i = 1 to words( prog.__LogExcludeWords )
  1156.     curWord = word( prog.__LogExcludeWords, i )
  1157.    
  1158.     do until j = 0
  1159.       j = Pos( curWord, logmsg )
  1160.       if j <> 0 then
  1161.         logmsg = delstr( logmsg, j, length( curWord ) )
  1162.     end /* do until j = 0 */
  1163.   end /* do i = 1 to words( prog.__LogExcludeWords ) */
  1164.  
  1165.   if prog.__QuietMode <> 1 then
  1166.   do
  1167.     if length( logmsg ) == prog.__ScreenCols  then
  1168.       call charout prog.__STDOUT, screen.__CurColor || ,
  1169.                                   msg || screen.__AttrOff
  1170.     else
  1171.       call lineOut prog.__STDOUT, screen.__CurColor || ,
  1172.                                   msg || screen.__AttrOff ||,
  1173.                                   screen.__DelEOL
  1174.   end /* if prog.__Quietmode <> 1 then */
  1175.  
  1176.   if symbol( 'prog.__LogFile' ) == 'VAR' then
  1177.     if prog.__LogFile <> '' then
  1178.     do
  1179.       call lineout prog.__LogFile, logmsg
  1180.  
  1181.                                 /* close the logfile                  */
  1182.       call stream prog.__LogFile, 'c', 'CLOSE'
  1183.     end /* if prog.__LogFile <> '' then */
  1184.  
  1185. RETURN ''
  1186.  
  1187. /* ------------------------------------------------------------------ */
  1188. /*-function: check if there is a patched version of this program      */
  1189. /*                                                                    */
  1190. /*-call:     I!.__CheckPatch                                          */
  1191. /*                                                                    */
  1192. /*-returns:  nothing                                                  */
  1193. /*                                                                    */
  1194. /*-Note:     I!.__RealParam must contain the parameters for           */
  1195. /*           this program.                                            */
  1196. /*           The variables prog.__Path and prog.__Name must be set!   */
  1197. /*           This procedure ends the program with an EXIT command!    */
  1198. /*                                                                    */
  1199. I!.__CheckPatch: PROCEDURE expose (exposeList)
  1200.  
  1201.                         /* get the drive with patch cmd files         */
  1202.   pLW = translate( value( 'PATCHDRIVE',, prog.__Env) )
  1203.  
  1204.   if pLW <> '' & pLW <> prog.__Drive then
  1205.   do
  1206.  
  1207.     pVer = pLW || prog.__Path || prog.__Name
  1208.  
  1209.                         /* check if a patched program version exists  */
  1210.     if stream( pVer, 'c', 'QUERY EXIST' ) <> '' then
  1211.     do
  1212.       pCmd = pVer || ' ' || I!.__RealParam
  1213.  
  1214.       screen.__CurColor = screen.__PatchColor
  1215.       call Log left( I!.__GetMsg( 9, pver ), prog.__ScreenCols )
  1216.       screen.__CurColor = screen.__AttrOff
  1217.       call I!.__LogSeparator
  1218.  
  1219.       '@cmd /c ' pCmd
  1220.  
  1221.       screen.__CurColor = screen.__AttrOff
  1222.       call I!.__LogSeparator
  1223.       screen.__CurColor = screen.__PatchColor
  1224.       call Log left( I!.__GetMsg( 10, rc ), prog.__ScreenCols )
  1225.  
  1226.       exit rc
  1227.     end /* if stream( ... */
  1228.   end /* if pLW <> '' */
  1229. RETURN
  1230.  
  1231. /* ------------------------------------------------------------------ */
  1232. /*-function: error handler for unexpected errors                      */
  1233. /*                                                                    */
  1234. /*-call:     DO NOT CALL THIS ROUTINE BY HAND!!!                      */
  1235. /*                                                                    */
  1236. /*-returns:  nothing                                                  */
  1237. /*                                                                    */
  1238. /*-input:    I!.__IncActive:                                          */
  1239. /*             if 1 the error occured while executing an include file */
  1240. /*             statement. In this case the following variables are    */
  1241. /*             also used (Note that this variables are automaticly    */
  1242. /*             set by the routine INCLUDE()):                         */
  1243. /*               I!.__IncLineNo                                       */
  1244. /*                 Line no. of the include file                       */
  1245. /*               I!.__IncFileName:                                    */
  1246. /*                 Name of the include file                           */
  1247. /*               I!.__IncCurLinePos:                                  */
  1248. /*                 Fileposition of the first char of the line causing */
  1249. /*                 the error                                          */
  1250. /*                                                                    */
  1251. /*-Note:     THIS FUNCTION ABORTS THE PROGRAM WITH A JUMP TO THE      */
  1252. /*           LABEL I!.__PROGRAMEND!!!                                 */
  1253. /*                                                                    */
  1254. I!.__ErrorAbort:
  1255.  
  1256.                             /* turn ANSI word wrap on                 */   
  1257.   if screen.__CurColor <> '' then
  1258.     call CharOut prog.__STDOUT, '1B'x || '[7h'
  1259.  
  1260.                         /* check if the error occured in the error    */
  1261.                         /* handler                                    */
  1262.   if I!.__errorLineNo == sigl then
  1263.   do
  1264.     call charout 'STDERR:',,
  1265.                                                             '0D0A'x  ,
  1266.        'Fatal Error: Error in the error handler detected!'  '0D0A'x  ,
  1267.                                                             '0D0A'x  ,
  1268.        'Linenumber:       ' || sigl                         '0D0A'x  ,
  1269.        'Errorname:        ' || condition('C')               '0D0A'x  ,
  1270.        'Errordescription: ' || condition('D')               '0D0A'x  ,
  1271.                                                             '0D0A'x  ,
  1272.        'The program exit routines were not called!'         '0D0A'x  ,
  1273.        'Check if "(EXPOSELIST)" is included in the ' || ,
  1274.        'expose lists of all procedures!'                    '0D0A'x
  1275.  
  1276.     call beep 637,300 ; call beep 437,300 ; call beep 637,300
  1277.     exit 255
  1278.  
  1279.   end /* if I!.__errorLineNo == sigl then */
  1280.  
  1281.                         /* get the number of the line causing the     */
  1282.                         /* error                                      */
  1283.   I!.__errorLineNo = sigl
  1284.  
  1285.                         /* get the name of this error                 */
  1286.   I!.__ErrorName = condition('C')
  1287.  
  1288.                         /* get further information for this error     */
  1289.                         /* if available                               */
  1290.   I!.__ErrorCondition = condition('D')
  1291.   if I!.__ErrorCondition <> '' then
  1292.     I!.__ErrorCondition = ' (Desc.: "' || I!.__ErrorCondition || '")'
  1293.  
  1294.   if datatype( prog.__ScreenCols, 'W' ) <> 1 then
  1295.     prog.__ScreenCols = 80
  1296.  
  1297.   if SYMBOL( 'prog.__Name' ) <> 'VAR' | value( 'prog.__Name' ) == '' then
  1298.     if I!.__errorLineNO < I!.__FirstUserCodeLine then
  1299.       I!.__pName = '**Runtime**'
  1300.     else
  1301.       I!.__pName = '***???***'
  1302.   else
  1303.     i!.__pName = prog.__Name
  1304.  
  1305.                         /* reInstall the error handler                */
  1306.   INTERPRET  'SIGNAL ON ' value(condition('C')) ' NAME I!.__ErrorAbort'
  1307.  
  1308.                         /* check, if we should ignore the error       */
  1309.   if value( 'sigl' ) == value( 'I!.__ICmdLine' ) then
  1310.   do
  1311.     I!.__errorLineNo = 0
  1312.     SIGNAL I!.__CallUserProc2
  1313.   end /* if value( ... */
  1314.  
  1315.   screen.__CurColor = screen.__ErrorColor
  1316.  
  1317.   I!.__QM = prog.__QuietMode
  1318.                         /* turn quiet mode off                        */
  1319.   prog.__QuietMode = ''
  1320.  
  1321.                         /* init variables for printing the line       */
  1322.                         /* causing the error to the screen            */
  1323.   I!.__ThisSRCLine = ''
  1324.   I!.__ThisPrefix = ' *-* '
  1325.  
  1326.   call I!.__LogStart
  1327.  
  1328.   call ShowString ' ' || I!.__pName || ' - ', I!.__ErrorName || ,
  1329.                   I!.__ErrorCondition || ' error detected!'
  1330.  
  1331.                         /* check, if the RC is meaningfull for this   */
  1332.                         /* error                                      */
  1333.   if pos( I!.__ErrorName, 'ERROR FAILURE SYNTAX' ) <> 0 then
  1334.   do
  1335.     if datatype(rc, 'W' ) == 1 then
  1336.       if 'SYNTAX' == I!.__ErrorName then
  1337.          if rc > 0 & rc < 100 then
  1338.             call Log left( ' The error code is ' || rc || ,
  1339.                            ', the REXX error message is: ' || ,
  1340.                            errorText( rc ), ,
  1341.                            prog.__ScreenCols )
  1342.          else
  1343.            call log left( ' The error code is ' || rc || ,
  1344.                           ', this error code is unknown.',,
  1345.                           prog.__ScreenCols )
  1346.       else
  1347.         call Log left( ' The RC is ' || rc || '.', prog.__ScreenCols )
  1348.   end /* if pos( ... */
  1349.  
  1350.   if value( 'I!.__IncActive' ) == 1 then
  1351.   do
  1352.                 /* error occured while interpreting an include file   */
  1353.     call ShowString 1, 'The error occured while executing the line ' || ,
  1354.                        I!.__IncLineNo || ' of the include file "' || ,
  1355.                        I!.__IncFileName || '".'
  1356.  
  1357.                         /* reset the file pointer of the include file */
  1358.                         /* to the start of the line causing the error */
  1359.     call stream I!.__IncFileName, 'c', 'SEEK =' || ,
  1360.                                                    I!.__IncCurLinePos
  1361.  
  1362.     I!.__SrcAvailable = stream( I!.__IncFileName, ,
  1363.                                    'c', 'QUERY EXIST' ) <> ''
  1364.   end
  1365.   else
  1366.   do
  1367.     call ShowString 1, 'The error occured in line ' ||,
  1368.                        I!.__errorLineNo || '.'
  1369.  
  1370.     I!.__thisLineNo = I!.__errorLineNo
  1371.  
  1372.                 /* error occured in this file                         */
  1373.                 /* check if the sourcecode is available               */
  1374.     SIGNAL ON SYNTAX   NAME I!.__NoSourceCode
  1375.     I!.__inMacroSpace = 1
  1376.     I!.__SrcAvailable = 0
  1377.     if sourceLine( I!.__errorLineNo ) <> '' then
  1378.       I!.__SrcAvailable = 1
  1379.  
  1380.     SIGNAL ON SYNTAX NAME I!.__ErrorAbort
  1381.     I!.__inMacroSpace = 0
  1382.  
  1383.   end /* else */
  1384.  
  1385.                         /* print the statement causing the error to   */
  1386.                         /* the screen                                 */
  1387.   if 1 == I!.__SrcAvailable then
  1388.   do
  1389.     call Log left( ' The line reads: ', prog.__ScreenCols )
  1390.     I!.__InterpretVar = 0
  1391.  
  1392.                 /* read the line causing the error                    */
  1393.     call I!.__GetSourceLine
  1394.  
  1395.     I!.__FirstToken = strip(word( I!.__ThisSRCLine,1))
  1396.     if translate( I!.__FirstToken ) == 'INTERPRET' then
  1397.     do
  1398.       parse var I!.__ThisSRCLine (I!.__FirstToken) ,
  1399.                 I!.__interpretValue
  1400.       I!.__InterpretVar = 1
  1401.     end /* if I!.__thisLineNo = I!.__errorLineNo */
  1402.  
  1403.                         /* handle multi line statements               */
  1404.     do forever
  1405.       call ShowString I!.__ThisPrefix, I!.__ThisSRCLine
  1406.  
  1407.       if right( strip( I!.__ThisSRCLine),1 ) <> ',' then
  1408.         leave
  1409.  
  1410.       I!.__ThisPrefix = 5
  1411.  
  1412.       call I!.__GetSourceLine
  1413.     end /* do forever */
  1414.  
  1415.     if 1 == I!.__InterpretVar then
  1416.     do
  1417.       I!.__interpretValue = strip( word(I!.__interpretValue,1) )
  1418.  
  1419.       if symbol( I!.__interpretValue ) == 'VAR' then
  1420.       do
  1421.         call Log left( '', prog.__ScreenCols )
  1422.         call Log left( ' The value of "' || I!.__interpretValue || ,
  1423.                        '" is:', prog.__ScreenCols )
  1424.         call ShowString ' >V> ', value( I!.__interpretValue )
  1425.       end /* if symbol( I!.__interpretValue ) = 'VAR' then */
  1426.  
  1427.     end /* if 1 == I!.__InterpretVar */
  1428.  
  1429.   end /* if 1 == I!.__SrcAvailable  then do */
  1430.   else
  1431.     call Log left( ' The sourcecode for this line is not available',,
  1432.                    prog.__ScreenCols )
  1433.  
  1434. I!.__NoSourceCode:
  1435.   SIGNAL ON SYNTAX NAME I!.__ErrorAbort
  1436.  
  1437.   if 1 == I!.__inMacroSpace then
  1438.   do
  1439.     parse source . . I!.__thisProgName
  1440.  
  1441.     if fileSpec( 'D', I!.__thisProgName ) == '' then
  1442.       call ShowString 1, ' The sourcecode for this line is not' || ,
  1443.                          ' available because the program is in' || ,
  1444.                          ' the macro space.'
  1445.     else
  1446.       call ShowString 1, ' The sourcecode for this line is not' || ,
  1447.                          ' available because the program is unreadable.'
  1448.   end /* if 1 == I!.__inMacroSpace then */
  1449.  
  1450.   call I!.__LogSeparator
  1451.   call Log
  1452.  
  1453.   prog.__ExitCode = global.__ErrorExitCode
  1454.  
  1455.   if prog.__NoSound <> 1 then
  1456.   do
  1457.     call beep 137,300;  call beep 337,300;  call beep 137,300
  1458.   end /* if prog.__NoSound <> 1 then */
  1459.  
  1460.   if 'DEBUG' == global.__verbose | prog.__Trace = 1 then
  1461.   do
  1462.                         /* enter interactive debug mode               */
  1463.     trace ?a
  1464.     nop
  1465.   end /* if 'DEBUG' == global.__verbose | ... */
  1466.  
  1467.                         /* restore quiet mode status                  */
  1468.   prog.__QuietMode = I!.__QM
  1469.  
  1470. SIGNAL I!.__programEnd
  1471.  
  1472. /* ------------------------------------------------------------------ */
  1473. /*-function: get the sourceline causing an error (subroutine of       */
  1474. /*           I!.__ErrorAbort)                                         */
  1475. /*                                                                    */
  1476. /*-call:     DO NOT CALL THIS IN YOUR CODE!!!                         */
  1477. /*                                                                    */
  1478. /*-returns:  nothing                                                  */
  1479. /*                                                                    */
  1480. /*-Note:     -                                                        */
  1481. /*                                                                    */
  1482. I!.__GetSourceLine:
  1483.   if 1 == I!.__IncActive then
  1484.     I!.__ThisSRCLine = lineIn( I!.__IncFileName )
  1485.   else
  1486.   do
  1487.     I!.__ThisSRCLine = sourceLine( I!.__ThisLineNo )
  1488.     I!.__ThisLineNo = I!.__ThisLineNo + 1
  1489.   end /* else */
  1490. RETURN
  1491.  
  1492. /* ------------------------------------------------------------------ */
  1493. /*-function: error handler for user breaks                            */
  1494. /*                                                                    */
  1495. /*-call:     DO NOT CALL THIS ROUTINE BY HAND!!!                      */
  1496. /*                                                                    */
  1497. /*-returns:  nothing                                                  */
  1498. /*                                                                    */
  1499. /*-Note:     THIS FUNCTION ABORTS THE PROGRAM WITH A JUMP TO THE      */
  1500. /*           LABEL I!.__PROGRAMEND IF prog.__UserAbort IS NOT 0!!!    */
  1501. /*                                                                    */
  1502. /*           In exit routines you may test if the variable            */
  1503. /*           prog.__ExitCode is 254 to check if the program           */
  1504. /*           was aborted by the user.                                 */
  1505. /*                                                                    */
  1506. I!.__UserAbort:
  1507.   I!.__sSigl = sigl
  1508.                         /* reinstall the error handler                */
  1509.   CALL ON HALT NAME I!.__UserAbort
  1510.  
  1511.                         /* check if user aborts are allowed           */
  1512.   if 0 == prog.__UserAbort then
  1513.     RETURN              /* CTRL-BREAK not allowed                     */
  1514.  
  1515.   I!.__QM = prog.__QuietMode
  1516.  
  1517.                         /* turn quiet mode off                        */
  1518.   prog.__QuietMode = ''
  1519.  
  1520.   call Log
  1521.  
  1522.   screen.__CurColor = screen.__ErrorColor
  1523.   call I!.__LogSeparator
  1524.   call Log left( I!.__GetMsg( 11, I!.__ssigl ), prog.__ScreenCols )
  1525.   call I!.__LogSeparator
  1526.   screen.__CurColor = screen.__NormalColor
  1527.  
  1528.   prog.__ExitCode = 254
  1529.  
  1530.                         /* restore quiet mode status                  */
  1531.   prog.__QuietMode = I!.__QM
  1532.  
  1533. SIGNAL I!.__ProgramEnd
  1534.  
  1535. /* ------------------------------------------------------------------ */
  1536. /*-function: get a message                                            */
  1537. /*                                                                    */
  1538. /*-call:     I!.__GetMsg msgNo {,msgP1} {...,msgP9}                   */
  1539. /*                                                                    */
  1540. /*-returns:  the message or an empty string                           */
  1541. /*                                                                    */
  1542. /*-note:     This routines calls the external routine which name is   */
  1543. /*           saved in the variable 'global.__GetMsg' if this variable */
  1544. /*           is not equal ''.                                         */
  1545. /*                                                                    */
  1546. /*           I!.__GetMsg adds global.__BaseMsgNo to the msgNo.        */
  1547. /*                                                                    */
  1548. I!.__GetMsg: PROCEDURE expose (exposeList)
  1549.   parse arg msgNo, mP1 , mP2 , mP3, mP4, mP5, mP6, mP7, mP8, mP9
  1550.  
  1551.   f = 0
  1552.   t = ''
  1553.  
  1554.   if symbol( 'global.__GetMsg' ) = 'VAR' then
  1555.     if global.__GetMsg <> '' then
  1556.     do
  1557.             /* first check if there's a user defined GetMsg routine   */
  1558.  
  1559.                         /* install a local error handler              */
  1560.       SIGNAL ON SYNTAX Name I!.__GetMsg1
  1561.  
  1562.                     /* try to call the user defined GetMsg routine    */
  1563.       interpret 'call ' global.__GetMsg ' msgNo+global.__BaseMsgNo,,' ,
  1564.                 ' mP1, mP2, mP3, mP4, mP5, mP6, mP7, mP8, mP9 '
  1565.       f = 1
  1566.     end /* if global.__GetMsg <> '' then */
  1567.  
  1568. I!.__GetMsg1:
  1569.  
  1570.   if f = 1 then
  1571.   do
  1572.                         /* user defined GetMsg routine found -- use   */
  1573.                         /* the result                                 */
  1574.     if symbol( 'RESULT' ) == 'VAR' then
  1575.       t = result
  1576.   end /* if result = 0 then */
  1577.   else
  1578.   do
  1579.                         /* user defined GetMsg routine not found --   */
  1580.                         /* use the hardcoded message strings          */
  1581.       msgString =  ,
  1582. /* 1001 */      'Routine_"@1"_not_found ',
  1583. /* 1002 */      'Can_not_write_to_the_logfile_"@1",_the_status_of_the_logfile_is_"@2"._Now_using_the_NUL_device_for_logging ',
  1584. /* 1003 */      'Include_file_"@1"_not_found ' ||,
  1585. /* 1004 */      'Unexpected_EOF_detected_while_reading_the_include_file_"@1" ' || ,
  1586. /* 1005 */      'Error_loading_the_DLL_"@1" ' ||,
  1587. /* 1006 */      'Invalid_call_to_LOADDLL ' ||,
  1588. /* 1007 */      '_Warning: ' ||,
  1589. /* 1008 */      '_@1_-_Error_@2_detected!_The_error_message_is_ ' ||,
  1590. /* 1009 */      '_Calling_the_patched_version_@1_... ' ||,
  1591. /* 1010 */      '_..._the_patched_version_endet_with_RC_=_@1 ' ||,
  1592. /* 1011 */      '_Program_aborted_by_the_user_(sigl=@1) ' ||,
  1593. /* 1012 */      '@1_@2_started_on_@3_at_@4_... ' ||,
  1594. /* 1013 */      '@1_@2_ended_on_@3_at_@4_with_RC_=_@5_(=''@6''x) ' || ,
  1595. /* 1014 */      '_Usage: '
  1596.  
  1597.                     /* get the message and translate all underscores  */
  1598.                     /* to blanks                                      */
  1599.     t = translate( word( msgString, msgNo ), ' ', '_'  )
  1600.  
  1601.                     /* replace place holder                           */
  1602.     i = 1
  1603.     do until i > 9
  1604.      j = pos( '@' || i, t )
  1605.      if j <> 0 then
  1606.        t = insert( arg( i+1 ), delStr(t, j, 2) , j-1 )
  1607.      else
  1608.        i = i +1
  1609.     end /* do until i > 9 */
  1610.   end /* else */
  1611. return t
  1612.  
  1613. /* ------------------------------------------------------------------ */
  1614. /*-function: get the line no of the call statement of this routine    */
  1615. /*                                                                    */
  1616. /*-call:     GetLineNo                                                */
  1617. /*                                                                    */
  1618. /*-returns:  the line number                                          */
  1619. /*                                                                    */
  1620. /*                                                                    */
  1621. GetLineNo:
  1622.   RETURN sigl
  1623.  
  1624. /* ------------------------------------------------------------------ */
  1625. /*-function: get the no. of the first line with the user code         */
  1626. /*                                                                    */
  1627. /*-call:     DO NOT CALL THIS ROUTINE BY HAND!!!                      */
  1628. /*                                                                    */
  1629. /*-returns:  nothing                                                  */
  1630. /*                                                                    */
  1631. /*                                                                    */
  1632. I!.__GetUserCode:
  1633.   I!.__FirstUserCodeLine = GetLineNo()+2
  1634. RETURN
  1635.  
  1636. /********************** End of Runtime Routines ***********************/
  1637. /**********************************************************************/
  1638.  
  1639. /***        End of Part 3 of the source code of TEMPLATE.CMD        ***/
  1640.  
  1641. /***       Start of Part 4 of the source code of TEMPLATE.CMD       ***/
  1642.                                                                    /*!*/
  1643.  
  1644. /* ------------------------------------------------------------------ */
  1645. /*-function: main procedure of the program                            */
  1646. /*                                                                    */
  1647. /*-call:     called by the runtime system with:                       */
  1648. /*           => call main parameter_of_the_program <=                 */
  1649. /*                                                                    */
  1650. /*-returns:  program return code                                      */
  1651. /*           If no return code is returned, the value of the variable */
  1652. /*           prog.__ExitCode is returned to the calling program.      */
  1653. /*                                                                    */
  1654. Main: PROCEDURE expose (exposeList)
  1655.  
  1656.                         /* get the parameter of the program           */
  1657.   parse arg thisParameter
  1658.  
  1659. /* ------------------------------ */
  1660.                         /* strings which should not be written into   */
  1661.                         /* the log file                               */
  1662.   prog.__LogExcludeWords = screen.__fgYellow screen.__highlight,
  1663.                            screen.__AttrOff
  1664.  
  1665. /* ------------------------------ */
  1666.                         /* init the global variables                  */
  1667.   call InitGlobalVariables
  1668.  
  1669. /* ------------------------------ */
  1670.                         /* get the options and parameters from the    */
  1671.                         /* environment variable and from the command  */
  1672.                         /* line                                       */
  1673.   call GetProgramOptions thisParameter
  1674.  
  1675. /* ------------------------------ */
  1676.  
  1677.   call UnpackFile global.__sourceFile
  1678.  
  1679. /* ------------------------------ */
  1680.  
  1681.                         /* exit the program                           */
  1682. RETURN
  1683.  
  1684. /* ------------------------------------------------------------------ */
  1685.  
  1686. /* ------------------------------------------------------------------ */
  1687. /* function: unpack a file                                            */
  1688. /*                                                                    */
  1689. /* call:     UnpackFile sFile                                         */
  1690. /*                                                                    */
  1691. /* where:    sFile - name of the source file                          */
  1692. /*                                                                    */
  1693. /* returns:  nothing                                                  */
  1694. /*                                                                    */
  1695. UnpackFile: PROCEDURE expose (exposeList)
  1696.   parse arg sFile
  1697.  
  1698.   call log ' Unpacking the file ' || AddColor1( '"', sFile ) || ' ...'
  1699.  
  1700.                         /* check if the source file exist             */
  1701.   if stream( sFile, 'c', 'QUERY EXIST' ) = '' then
  1702.     call ShowError global.__ErrorExitCode ,,
  1703.           "File not found"
  1704.  
  1705.                         /* check the extension of the source file     */
  1706.   if translate( FileSpec( 'E', sFile ) ) <> 'CMD' & ,
  1707.      global.__IgnoreExtension = 0 then
  1708.     call ShowError global.__ErrorExitCode,,
  1709.           'The extension of the source file must be "CMD"'
  1710.  
  1711.                         /* read the source file                       */
  1712.   call ReadFile sFile
  1713.  
  1714.                         /* check the file                             */
  1715.                         /* (The first two characters of the file      */
  1716.                         /*  should be a comment start delimiter)      */
  1717.   if substr( global.__SourceCode,1,2 ) <> global.__c1 then
  1718.   do
  1719.     global.__Warnings = global.__Warnings + 1
  1720.     if global.__IgnoreExtension = 1 then
  1721.       call ShowWarning ,
  1722.             'The file "' || sfile || '" seems not to be a valid REXX program'
  1723.     else
  1724.       call ShowError global.__ErrorExitCode ,,
  1725.             'The file "' || sfile || '" seems not to be a valid REXX program'
  1726.   end /* if ... */
  1727.  
  1728.                         /* check for the internal used ASCII codes    */
  1729.     if verify( global.__SourceCode, '01020304'x, 'M' ) <> 0 then
  1730.       call ShowError global.__ErrorExitCode ,,
  1731.             'Can not handle files with the ASCII codes 01, 02, 03 or 04'
  1732.  
  1733.                         /* replace the comments with placeholder      */
  1734.                         /* or delete them (depending on the /DL       */
  1735.                         /* switch)                                    */
  1736.   call ReplaceComments
  1737.  
  1738.                         /* replace string constants with placeholder  */
  1739.   call ReplaceStrings
  1740.  
  1741.                         /* split the file into lines                  */
  1742.   call SplitFile
  1743.  
  1744. /* --------------------------- */
  1745. /* --- FOR DEBUGGING ONLY! --- */
  1746.  
  1747.   if global.__verbose <> '' then
  1748.     call WriteInternalVariablestoFile sFile
  1749.  
  1750. /* -- END OF DEBUGGING CODE -- */
  1751. /* --------------------------- */
  1752.  
  1753.                         /* format the file for propper indents        */
  1754.   call FormatFile sFile
  1755.  
  1756.                         /* insert the string constants again          */
  1757.   call Insertstrings
  1758.  
  1759.   if global.__DeleteComments <> 1 then
  1760.   do
  1761.                         /* insert the comments again                  */
  1762.     call InsertComments
  1763.   end /* if */
  1764.  
  1765.                         /* create a backup of the source file         */
  1766.   call CreateBackupFile sFile
  1767.  
  1768.                         /* write the target file                      */
  1769.   call WriteFile sFile
  1770.  
  1771.   if global.__Warnings = 0 then
  1772.     call log ' ... file successfully unpacked.'
  1773.   else
  1774.     call log ' ... file unpacked with warnings.'
  1775.  
  1776. RETURN
  1777.  
  1778. /* ------------------------------------------------------------------ */
  1779. /* function: format a statement (line or block)                       */
  1780. /*                                                                    */
  1781. /* call:     FormatLine curIndent, curIndex                           */
  1782. /*                                                                    */
  1783. /* where:    curIndent - current indent in number of chars            */
  1784. /*           curIndex - index of the current line in the sourceStem   */
  1785. /*                                                                    */
  1786. /* returns:  nothing                                                  */
  1787. /*                                                                    */
  1788. FormatLine: PROCEDURE expose (exposeList) format.
  1789.   parse arg curIndent, curIndex
  1790.  
  1791.   call CharOut global.__DeviceForStatusMsgs,,
  1792.         screen.__RestPos || curIndex
  1793.  
  1794.                     /* format the statement according to it's type    */
  1795.   select
  1796.  
  1797.     when format.__SyntaxType = 1 then   /* IF, or WHEN                */
  1798.     do
  1799.                         /* take care of the type of the previous line */
  1800.       if format.__PrevSyntaxType <> 1 & ,       /* no IF or WHEN      */
  1801.          format.__PrevSyntaxType <> 7 then      /* no ELSE            */
  1802.         format.__PrefixLine = global.__NewLine  /* add an empty line  */
  1803.  
  1804.                     /* use the current indent for the current line    */
  1805.                     /* (this is the IF or WHEN statement)             */
  1806.       call PutLine curIndent
  1807.  
  1808.                     /* get the next line ( if i = -1 -> EOF reached)  */
  1809.       i = GetLine()
  1810.  
  1811.                     /* use an increased indent for the next line(s)   */
  1812.       if i <> -1 then
  1813.       do
  1814.         call FormatLine curIndent + global.__IndentStep, i
  1815.  
  1816.                                 /* check for following ELSE statement */
  1817.         if CheckSyntaxType( format.__curIndex + 1 ) = 7 then
  1818.         do
  1819.                                         /* process the ELSE statement */
  1820.  
  1821.                     /* get the next line ( if i = -1 -> EOF reached)  */
  1822.           i = GetLine()
  1823.  
  1824.                     /* use the current indent for the ELSE statement  */
  1825.           call PutLine CurIndent
  1826.  
  1827.                     /* use an increased indent for the next line(s)   */
  1828.                     /* get the next line ( if i = -1 -> EOF reached)  */
  1829.           i = GetLine()
  1830.           if i <> - 1 then
  1831.             call FormatLine curIndent + global.__IndentStep, i
  1832.         end /* if */
  1833.         /* ELSE SYNTAX WARNING */
  1834.  
  1835.         i = CheckSyntaxType( format.__CurIndex + 1 )
  1836.  
  1837.                     /* insert an empty line if the next statement is  */
  1838.                     /* neither IF/WHEN nor ELSE                       */
  1839.         if i <> 1 & i <> 7 then
  1840.           format.__PrefixLine = global.__NewLine
  1841.  
  1842.       end /* if i <> -1 then */
  1843.       /* ELSE SYNTAX WARNING */
  1844.  
  1845.     end /* when */
  1846.  
  1847.     when format.__SyntaxType = 3 then   /* DO                         */
  1848.     do
  1849.       format.__InBlock = format.__InBlock + 1
  1850.  
  1851.                         /* create the comment for the END statement   */
  1852.  
  1853.                         /* take care of the type of the previous line */
  1854.       if format.__PrevSyntaxType = 1 | ,        /* IF, WHEN           */
  1855.          format.__PrevSyntaxType = 7 | ,        /* ELSE               */
  1856.          format.__PrevSyntaxType = 8 then       /* OTHERWISE          */
  1857.       do
  1858.                     /* use the previous statement for the comment     */
  1859.                     /* after the END statement                        */
  1860.         curComment = global.__c1 ,
  1861.                      value( 'sourceStem.' || curIndex-1 ) ,
  1862.                      sourceStem.curIndex ,
  1863.                      global.__c2
  1864.         curIndent = curIndent - global.__IndentStep
  1865.       end /* if */
  1866.       else
  1867.       do
  1868.                     /* use only the DO statement for the              */
  1869.                     /* comment after the END statement                */
  1870.         curComment = global.__c1 ,
  1871.                      sourceStem.curIndex ,
  1872.                      global.__c2
  1873.  
  1874.         format.__PrefixLine = global.__NewLine
  1875.       end /* else */
  1876.       format.__PostLine = global.__NewLine
  1877.  
  1878.                     /* use the current indent for the current line    */
  1879.       call PutLine curIndent
  1880.  
  1881.                     /* get the next line ( if i = -1 -> EOF reached)  */
  1882.       i = GetLine()
  1883.  
  1884.                     /* now process the block until the corresponding  */
  1885.                     /* END statement                                  */
  1886.       do while format.__SyntaxType <> 6 & format.__eofReached = 0
  1887.  
  1888.                     /* increase the indent for the next line(s)       */
  1889.         call FormatLine curIndent + global.__IndentStep, i
  1890.  
  1891.                     /* get the next line ( if i = -1 -> EOF reached)  */
  1892.         i = GetLine()
  1893.       end /* do until ... */
  1894.  
  1895.                     /* now process the END statement                  */
  1896.       if i <> -1 then
  1897.       do
  1898.                     /* insert a new line if the next statement is not */
  1899.                     /* ELSE                                           */
  1900.         if CheckSyntaxType( format.__curIndex + 1 ) <> 7 then
  1901.           format.__PostLine = global.__NewLine
  1902.  
  1903.         format.__PrefixLine = global.__NewLine
  1904.  
  1905.         call PutLine curIndent , curComment
  1906.       end /* if */
  1907.       /* ELSE SYNTAX ERROR */
  1908.  
  1909.       format.__InBlock = format.__InBlock - 1
  1910.  
  1911.     end /* when */
  1912.  
  1913.     when format.__SyntaxType = 4 then   /* SELECT                     */
  1914.     do
  1915.       format.__InBlock = format.__InBlock + 1
  1916.  
  1917.       if format.__PrevSyntaxType = 1 then
  1918.       do
  1919.         /* curIndent = curIndent - global.__IndentStep */
  1920.       end /* if */
  1921.       else
  1922.       do
  1923.         format.__PrefixLine = global.__NewLine
  1924.       end /* else */
  1925.  
  1926.                     /* create the comment for the END statement       */
  1927.       curComment = global.__c1 sourceStem.curIndex global.__c2
  1928.  
  1929.                     /* use the current indent for the current line    */
  1930.       call PutLine curIndent
  1931.  
  1932.                     /* now process the block until the corresponding  */
  1933.                     /* END statement                                  */
  1934.  
  1935.                     /* get the next line ( if i = -1 -> EOF reached)  */
  1936.       i = GetLine()
  1937.  
  1938.       do while format.__SyntaxType <> 6 & format.__eofReached = 0
  1939.  
  1940.                     /* increase the indent for the next line(s)       */
  1941.         call FormatLine curIndent + global.__IndentStep, i
  1942.  
  1943.                     /* get the next line ( if i = -1 -> EOF reached)  */
  1944.         i = GetLine()
  1945.       end /* do until ... */
  1946.  
  1947.                     /* now process the END statement                  */
  1948.       if i <> -1 then
  1949.       do
  1950.         format.__PrefixLine = global.__NewLine
  1951.         if CheckSyntaxType( format.__curIndex + 1 ) <> 7 then
  1952.           format.__PostLine = global.__NewLine
  1953.  
  1954.         call PutLine curIndent , curComment
  1955.       end /* if */
  1956.       /* ELSE SYNTAX ERROR */
  1957.  
  1958.       format.__InBlock = format.__InBlock - 1
  1959.  
  1960.     end /* when */
  1961.  
  1962.     when format.__SyntaxType = 8 then    /* OTHERWISE                 */
  1963.     do
  1964.       format.__prefixLine = global.__NewLine
  1965.  
  1966.       call PutLine curIndent
  1967.     end /* when */
  1968.  
  1969.     when format.__SyntaxType = 99 then   /* label                      */
  1970.     do
  1971.                         /* get the name of the function/procedure      */
  1972.       global.__funcName = substr( format.__FirstWord,1, pos( ':', format.__FirstWord )-1 )
  1973.  
  1974.                     /* insert the function header if the last          */
  1975.                     /* statement was RETURN, EXIT or SIGNAL            */
  1976.       if format.__PrevSyntaxType = 5 | ,    /* RETURN                  */
  1977.          format.__PrevSyntaxType = 9 | ,    /* SIGNAL                  */
  1978.          format.__PrevSyntaxType = 10 then  /* EXIT                    */
  1979.         format.__prefixLine = PrepareFunctionHeader( global.__funcName )
  1980.       else
  1981.         format.__prefixLine = global.__NewLine
  1982.  
  1983.       call PutLine 0
  1984.  
  1985.     end /* when */
  1986.  
  1987.     when format.__SyntaxType = 5  | ,    /* RETURN                    */
  1988.          format.__SyntaxType = 10 | ,    /* EXIT                      */
  1989.          format.__SyntaxType = 9 then    /* SIGNAL                    */
  1990.     do
  1991.                     /* insert a new line if the next statement is     */
  1992.                     /* a label or a comment                           */
  1993.       i = CheckSyntaxType( format.__curIndex + 1 )
  1994.                                          /* 99 : LABEL                */
  1995.                                          /* 98 : comment              */
  1996.       if i = 99 | i = 98  then
  1997.         format.__PostLine = global.__NewLine
  1998.  
  1999.       curComment = ''
  2000.       if format.__Syntaxtype = 5 then    /* RETURN                    */
  2001.         if global.__funcName = '' then   /* end of the program        */
  2002.           curComment = global.__c1 global.__sourceFile global.__c2
  2003.         else                             /* end of a subroutine/func. */
  2004.           curComment = global.__c1 global.__funcName global.__c2
  2005.  
  2006.       if format.__SyntaxType = 10 then   /* EXIT                      */
  2007.         curComment = global.__c1 global.__sourceFile global.__c2
  2008.  
  2009.       if format.__InBlock > 0 | format.__PrevSyntaxType = 1 then
  2010.         call PutLine curIndent, curComment  /* either in a block or   */
  2011.       else                              /* the prev. stmt is IF/WHEN  */
  2012.         call PutLine 0, curComment
  2013.     end /* when */
  2014.  
  2015.     when format.__SyntaxType = 98 then  /* comment                    */
  2016.     do
  2017.                     /* write comments ranged right                    */
  2018.       n = 0
  2019.       i = format.__CurIndex
  2020.       if  left( sourceStem.i, 1 ) = global.__CommentStartMarker then
  2021.         if right( sourceStem.i, 1 ) = global.__CommentEndMarker then
  2022.         do
  2023.           i = dbrleft( dbrright( sourceStem.i, 1 ),1 )
  2024.           i = length( commentStem.i )
  2025.           if i < global.__LineLength then
  2026.             n = global.__LineLength - i
  2027.         end /* if */
  2028.  
  2029.       call PutLine n
  2030.     end /* when */
  2031.  
  2032.     otherwise
  2033.     do
  2034.                                         /* all other lines            */
  2035.       call PutLine curIndent
  2036.     end /* otherwise */
  2037.  
  2038.   end /* select */
  2039.  
  2040. RETURN
  2041.  
  2042. /* ------------------------------------------------------------------ */
  2043. /* function: format the file for propper indents                      */
  2044. /*                                                                    */
  2045. /* call:     FormatFile fileName                                      */
  2046. /*                                                                    */
  2047. /* where:    fileName - name of the source file                       */
  2048. /*                                                                    */
  2049. /* returns:  nothing                                                  */
  2050. /*                                                                    */
  2051. FormatFile: PROCEDURE expose (exposeList) format.
  2052.   parse arg fileName
  2053.  
  2054.   call CharOut global.__DeviceForStatusMsgs,,
  2055.         '  Formating lines ... line ' || screen.__SavePos
  2056.  
  2057.   format.__curIndex = 0       /* index for the stem sourceStem.       */
  2058.   format.__eofReached = 0     /* 1: eof reached                       */
  2059.   format.__FirstWord = ''     /* first word of the current line in    */
  2060.                               /* uppercase                            */
  2061.   format.__SyntaxType = ''    /* syntax type of the current line      */
  2062.  
  2063.   format.__PrefixLine = ''    /* prefix for the current line          */
  2064.   format.__PostLine = ''      /* postfix for the current line         */
  2065.  
  2066.   format.__InBlock = 0        /* <> 0: currently in a DO/SELECT block */
  2067.  
  2068.                               /* 1: last line was an empty line       */
  2069.   format.__LastLineWasEmpty = 0
  2070.  
  2071.                               /* indent for the current line          */
  2072.   curIndent = global.__IndentStart
  2073.  
  2074.                               /* variable for the target code         */
  2075.   if global.__InsertHeader <> 0 then
  2076.     global.__TargetCode = ,
  2077.      '/' || '* ------------------------------------------------------------------ *' || '/' || global.__crLF || ,
  2078.      '/' || '* ' || left(  translate( fileName ), 66 ) || ' *' || '/' || global.__crLF || ,
  2079.      '/' || '*                                                                    *' || '/' || global.__crLF || ,
  2080.      '/' || '* function:                                                          *' || '/' || global.__crLF || ,
  2081.      '/' || '*                                                                    *' || '/' || global.__crLF || ,
  2082.      '/' || '*                                                                    *' || '/' || global.__crLF || ,
  2083.      '/' || '* usage:                                                             *' || '/' || global.__crLF || ,
  2084.      '/' || '*                                                                    *' || '/' || global.__crLF || ,
  2085.      '/' || '*                                                                    *' || '/' || global.__crLF || ,
  2086.      '/' || '* parameters:                                                        *' || '/' || global.__crLF || ,
  2087.      '/' || '*                                                                    *' || '/' || global.__crLF || ,
  2088.      '/' || '*                                                                    *' || '/' || global.__crLF || ,
  2089.      '/' || '* history:                                                           *' || '/' || global.__crLF || ,
  2090.      '/' || '*                                                                    *' || '/' || global.__crLF || ,
  2091.      '/' || '*                                                                    *' || '/' || global.__crLF || ,
  2092.      '/' || '* notes:                                                             *' || '/' || global.__crLF || ,
  2093.      '/' || '*                                                                    *' || '/' || global.__crLF || ,
  2094.      '/' || '*                                                                    *' || '/' || global.__crLF
  2095.   else
  2096.     global.__TargetCode = ''
  2097.  
  2098.   global.__TargetCode = global.__TargetCode || ,
  2099.     '/' || '* ------------------------------------------------------------------ *' || '/' || global.__crLF || ,
  2100.     '/' || '* unpacked on ' || date( 'U' ) || ' at ' || time() || ' with UPCKREXX.CMD (c) B. Schemmer *' || '/' || global.__crLF || ,
  2101.     '/' || '* ------------------------------------------------------------------ *' || '/' || global.__crLF || ,
  2102.     global.__crLF
  2103.  
  2104.                     /* get the first line ( if i = -1 -> EOF reached) */
  2105.   i = GetLine()
  2106.  
  2107.   do while format.__eofReached = 0
  2108.  
  2109.                     /* format the line                                */
  2110.     call FormatLine curIndent, i
  2111.  
  2112.                     /* get the next line ( if i = -1 -> EOF reached)  */
  2113.     i = GetLine()
  2114.  
  2115.   end /* while */
  2116.  
  2117.   call LineOut global.__DeviceForStatusMsgs,,
  2118.         screen.__RestPos || copies( '08'x, 5) || ' done. ' || screen.__DelEOL
  2119.  
  2120. RETURN
  2121.  
  2122. /* ------------------------------------------------------------------ */
  2123. /* function: add a line to the target source                          */
  2124. /*                                                                    */
  2125. /* call:     PutLine curIndent {, curComment}                         */
  2126. /*                                                                    */
  2127. /* where:    curIndent - current indent in chars                      */
  2128. /*           curComment - comment for the current line                */
  2129. /*                                                                    */
  2130. /* returns:  nothing                                                  */
  2131. /*                                                                    */
  2132. PutLine: PROCEDURE expose (exposeList) format.
  2133.   parse arg curIndent, curComment
  2134.  
  2135.             /* get the index of the current line of the source code   */
  2136.   i = format.__curIndex
  2137.  
  2138.                     /* suppress comments if necessary                 */
  2139.   if global.__InsertComments = 0 then
  2140.     curComment = ''
  2141.  
  2142.                     /* suppress superflous empty lines                */
  2143.   if format.__LastLineWasEmpty = 1 & ,
  2144.      format.__PrefixLine = global.__NewLine then
  2145.     format.__PrefixLine = ''
  2146.  
  2147.                     /* add the line to the target code                */
  2148.   global.__TargetCode = global.__TargetCode || ,
  2149.                         format.__PrefixLine || ,
  2150.                         copies( ' ', curIndent ) || ,
  2151.                         sourceStem.i curComment || ,
  2152.                         global.__CRLF || ,
  2153.                         format.__PostLine
  2154.  
  2155.               /* save status of the last line (empty or not empty)    */
  2156.   if format.__PostLine = global.__NewLine then
  2157.     format.__LastLineWasEmpty = 1
  2158.   else
  2159.     format.__LastLineWasEmpty = 0
  2160.  
  2161.                         /* reset the line prefix and post variables   */
  2162.   format.__PrefixLine = ''
  2163.   format.__PostLine = ''
  2164. RETURN
  2165.  
  2166. /* ------------------------------------------------------------------ */
  2167. /* function: get and prepeare the next line of the source file        */
  2168. /*                                                                    */
  2169. /* call:     GetLine                                                  */
  2170. /*                                                                    */
  2171. /* where:    -                                                        */
  2172. /*                                                                    */
  2173. /* returns:  -1 : eof reached                                         */
  2174. /*           else index of the current line                           */
  2175. /*                                                                    */
  2176. /* output:   format.__SyntaxType : type of the line                   */
  2177. /*           format.__FirstWord : first word of the line              */
  2178. /*           format.__PrevSyntaxType : type of the previous line      */
  2179. /*           format.__PrevFirstWord : first word of the previous line */
  2180. /*           format.__curIndex : index of the current line            */
  2181. /*           format.__eofReached : 1 if eof reached                   */
  2182. /*                                                                    */
  2183. GetLine: PROCEDURE expose (exposeList) format.
  2184.  
  2185.                         /* save the values of the last line           */
  2186.   format.__PrevFirstWord  = format.__FirstWord
  2187.   format.__PrevSyntaxType = format.__SyntaxType
  2188.  
  2189.   format.__curIndex = format.__curIndex + 1
  2190.   if format.__curIndex > sourceStem.0 then
  2191.   do
  2192.                         /* end of file reached                        */
  2193.     format.__eofReached = 1
  2194.     thisRC = -1
  2195.   end
  2196.   else
  2197.   do
  2198.     i = format.__curIndex
  2199.  
  2200.                         /* get the values for this line               */
  2201.     format.__FirstWord = word( sourceStem.i,1 )
  2202.     format.__SyntaxType = CheckSyntaxType( i )
  2203.  
  2204.     thisRC = i
  2205.   end /* else */
  2206.  
  2207. RETURN thisRC
  2208.  
  2209. /* ------------------------------------------------------------------ */
  2210. /* function: get the syntax type of a line                            */
  2211. /*                                                                    */
  2212. /* call:     CheckSyntaxType lineNo                                   */
  2213. /*                                                                    */
  2214. /* where:    lineNo - line number                                     */
  2215. /*                                                                    */
  2216. /* returns:  the type of the line                                     */
  2217. /*           or -1 if the parameter is invalid or the line does not   */
  2218. /*           exist                                                    */
  2219. /*                                                                    */
  2220. CheckSyntaxType: PROCEDURE expose (exposeList)
  2221.   parse arg lineNo
  2222.  
  2223.   thisRC = -1
  2224.  
  2225.                     /* variables for detecting the type of the line   */
  2226.   specialWords = 'IF WHEN ELSE DO SELECT EXIT RETURN END SIGNAL OTHERWISE' /* comment */ /* label */
  2227.   syntaxTypes  = ' 1   1   7   3    4     10     5     6    9        8           98          99'
  2228.  
  2229.   if datatype( lineNo, 'W' ) = 1 then
  2230.     if symbol( 'sourceStem.' || lineNo ) = 'VAR' then
  2231.     do
  2232.                         /* translate the test values to uppercase     */
  2233.       testLine = translate( sourceStem.lineNo )
  2234.       FirstWord = word( testLine,1 )
  2235.  
  2236.       SyntaxType = wordPos( FirstWord, specialWords )
  2237.  
  2238.       select
  2239.  
  2240.         when SyntaxType <> 0 then
  2241.         do
  2242.           SyntaxType = word( syntaxtypes, SyntaxType )
  2243.                         /* handle statements like                     */
  2244.                         /*   SIGNAL ON ... NAME ...                   */
  2245.                         /* correct                                    */
  2246.           if SyntaxType = 9 then
  2247.             if words( sourceStem.lineNo ) >= 3 then
  2248.               SyntaxType = 0
  2249.         end /* when */
  2250.  
  2251.         when right( FirstWord,1 ) = ':' | ,
  2252.              pos( ':PROCEDURE', FirstWord ) <> 0 then
  2253.         do
  2254.                         /* LABEL                                      */
  2255.           SyntaxType = 99
  2256.         end /* when */
  2257.  
  2258.         when left( FirstWord,1 ) = global.__CommentStartMarker then
  2259.         do
  2260.                         /* COMMENT                                    */
  2261.           SyntaxType = 98
  2262.         end /* when */
  2263.  
  2264.         otherwise
  2265.           nop
  2266.  
  2267.       end /* select */
  2268.  
  2269.       thisRC = SyntaxType
  2270.     end /* if */
  2271.  
  2272. RETURN thisRC
  2273.  
  2274. /* ------------------------------------------------------------------ */
  2275. /* function: split file into lines                                    */
  2276. /*                                                                    */
  2277. /* call:     SplitFile                                                */
  2278. /*                                                                    */
  2279. /* where:    sFile - name of the input file                           */
  2280. /*                                                                    */
  2281. /* returns:  nothing                                                  */
  2282. /*                                                                    */
  2283. SplitFile: PROCEDURE expose (exposeList)
  2284.  
  2285.   call CharOut global.__DeviceForStatusMsgs,,
  2286.         '  Splitting the file into lines ... Offset ' || screen.__SavePos
  2287.  
  2288.                     /* init the variables                             */
  2289.   j = sourceStem.0+1
  2290.  
  2291.                     /* begin at the start of the file                 */
  2292.   curPtr = 1
  2293.  
  2294.  
  2295.                     /* replace LFs with ';' and CRs and TABs with ' ' */
  2296.   global.__SourceCode = translate( global.__SourceCode, ' ; ', '0D0A09'x )
  2297.  
  2298.   do forever
  2299.  
  2300.                     /* show the 'in progress' message                 */
  2301.     call CharOut global.__DeviceForStatusMsgs,,
  2302.           screen.__RestPos || curPtr || screen.__DelEOL
  2303.  
  2304.     curLine = ''
  2305.  
  2306.                     /* get the first line                             */
  2307.                     /* There's always at least one semicolon!         */
  2308.                     /* (see routine ReadFile)                         */
  2309.     i = pos( ';', global.__SourceCode, curPtr )
  2310.  
  2311.     if i = 0 then
  2312.       leave         /* end of file reached                            */
  2313.  
  2314.     do while i <> 0
  2315.                         /* FUTURE enhancement:                        */
  2316.                         /*   Create a copy of the line with NO        */
  2317.                         /*   comments in it!                          */
  2318.  
  2319.                         /* get the line                               */
  2320.       curLine = curLine || strip( space( ( substr( global.__SourceCode, curPtr, i-curPtr ) ) ) )
  2321.  
  2322.                         /* correct the pointer to the next line       */
  2323.       curPtr = i + 1
  2324.  
  2325.                         /* check for multi line statements            */
  2326.       tStr = curLine
  2327.       lastCharPos = length( tStr )
  2328.       lastChar = right( tStr,1 )
  2329.  
  2330.                         /* ignore comments at the end of the line     */
  2331.       do while lastChar = global.__CommentEndMarker
  2332.         tStr = strip( substr( curLine, 1, lastPos( global.__CommentStartMarker, tStr )-1 ), 'T' )
  2333.  
  2334.         lastCharPos = length( tstr )
  2335.         LastChar = right( tstr,1 )
  2336.       end /* do while */
  2337.  
  2338.       if LastChar = ',' then
  2339.         curLine = overlay( ' ', curLine, lastCharPos )
  2340.       else
  2341.         leave
  2342.                     /* get the next line                              */
  2343.       i = pos( ';', global.__SourceCode, curPtr )
  2344.  
  2345.     end /* do while i = 0 */
  2346.  
  2347.     cmtLine = ''
  2348.                     /* cut leading comments                           */
  2349.     do forever
  2350.       curLine = strip( curLine )
  2351.       if left( curLine,1 ) <> global.__commentStartMarker then
  2352.         leave
  2353.  
  2354.       n = pos( global.__CommentEndMarker, curLine )
  2355.  
  2356.       cmtLine = cmtLine || substr( curLine, 1, n )
  2357.       curLine =            substr( curLine, n+1 )
  2358.     end /* do forever */
  2359.  
  2360.                 /* save the leading comment into an additional line   */
  2361.     if cmtLine <> '' then
  2362.     do
  2363.       sourceStem.j = cmtLine
  2364.       j = j + 1
  2365.     end /* if cmtLine <> '' then */
  2366.  
  2367.                 /* save the line in the source stem                   */
  2368.     sourceStem.j = curLine
  2369.  
  2370.     if sourceStem.j <> '' then
  2371.     do
  2372.  
  2373.                 /* split the line into multiple lines if necessary    */
  2374.       FirstWord = translate( word( sourceStem.j ,1 ) )
  2375.       LastWord  = translate( word( sourceStem.j, words( sourceStem.j ) ) )
  2376.  
  2377.       select
  2378.  
  2379.         when ( FirstWord = 'IF' | FirstWord = 'WHEN' ) & ,
  2380.              ( LastWord <> 'THEN' ) then
  2381.         do
  2382.                     /* ensure that THEN is the last word in a line    */
  2383.           n = pos( ' THEN ', translate( sourceStem.j ) )
  2384.           if n <> 0 then
  2385.           do
  2386.             k = j + 1
  2387.             sourceStem.k = strip( substr( sourceStem.j, n+5 ) )
  2388.  
  2389.                     /* ignore comments after THEN                     */
  2390.             if left( sourceStem.k,1 ) = global.__CommentStartMarker & ,
  2391.                right( sourceStem.k, 1 ) = global.__CommentEndMarker then
  2392.               nop
  2393.             else
  2394.             do
  2395.               sourceStem.j = strip( substr( sourceStem.j, 1, n+5 ) )
  2396.               j = k
  2397.             end /* else */
  2398.           end /* if n <> 0 then */
  2399.         end /* when */
  2400.  
  2401.         when ( ( FirstWord = 'ELSE') | ( FirstWord = 'OTHERWISE' ) ) &,
  2402.              ( LastWord <> FirstWord ) then
  2403.         do
  2404.           n = length( firstword )
  2405.  
  2406.                     /* ensure that ELSE and OTHERWISE are the only    */
  2407.                     /* words in a line                                */
  2408.           k = j + 1
  2409.           sourceStem.k = strip( substr( sourceStem.j, n+2 ) )
  2410.  
  2411.                     /* ignore comments after ELSE                     */
  2412.           if left( sourceStem.k,1 ) = global.__CommentStartMarker & ,
  2413.              right( sourceStem.k, 1 ) = global.__CommentEndMarker then
  2414.             nop
  2415.           else
  2416.           do
  2417.             sourceStem.j = strip( substr( sourceStem.j, 1, n ) )
  2418.             j = k
  2419.           end /* else */
  2420.         end /* when */
  2421.  
  2422.         otherwise
  2423.           nop
  2424.  
  2425.       end /* select */
  2426.  
  2427.                 /* increase the index into the source stem            */
  2428.       j = j + 1
  2429.  
  2430.     end /* if sourceStem.j <> '' then */
  2431.  
  2432.   end /* until i = 0 */
  2433.  
  2434.   sourceStem.0 = j - 1
  2435.  
  2436.   call LineOut global.__DeviceForStatusMsgs,,
  2437.         screen.__RestPos || copies( '08'x, 7) || ' done. ' || screen.__DelEOL
  2438.  
  2439. RETURN
  2440.  
  2441. /* ------------------------------------------------------------------ */
  2442. /* function: init global variables                                    */
  2443. /*                                                                    */
  2444. /* call:     InitGlobalVariables                                      */
  2445. /*                                                                    */
  2446. /* where:    -                                                        */
  2447. /*                                                                    */
  2448. /* returns:  nothing                                                  */
  2449. /*                                                                    */
  2450. InitGlobalVariables: PROCEDURE expose (exposeList) ,
  2451.                                stringStem. commentStem. sourceStem.
  2452.  
  2453.                                 /* number of warnings                 */
  2454.   global.__Warnings = 0
  2455.  
  2456.                                 /* default line delimiter             */
  2457.   global.__CRLF = '0D0A'x
  2458.  
  2459.                                 /* name of the environment variable   */
  2460.                                 /* for default switches               */
  2461.   global.__envVarName = 'UPCKREXX'
  2462.  
  2463.                                 /* comment start and end delimiter    */
  2464.   global.__c1 = '/' || '*'
  2465.   global.__c2 = '*' || '/'
  2466.  
  2467.                                 /* string start and end delimiter     */
  2468.   global.__stringChar1 = "'"
  2469.   global.__stringChar2 = '"'
  2470.  
  2471.                                 /* start and end delimiter for        */
  2472.                                 /* comment place holder               */
  2473.   global.__CommentStartMarker = '01'x
  2474.   global.__CommentEndMarker   = '02'x
  2475.  
  2476.                                 /* start and end delimiter for string */
  2477.                                 /* place holder                       */
  2478.   global.__StringStartMarker  = '03'x
  2479.   global.__StringEndMarker    = '04'x
  2480.  
  2481.                                 /* get the output device for          */
  2482.                                 /* 'In progress' messages             */
  2483.   if ( prog.__QuietMode <> 1 ) & ( screen.__normalColor <> '' ) then
  2484.     global.__DeviceForStatusMsgs = 'STDOUT'
  2485.   else
  2486.     global.__DeviceForStatusMsgs = 'NUL'
  2487.  
  2488.                                 /* variable with the contents of the  */
  2489.                                 /* source file                        */
  2490.   global.__SourceCode = ''
  2491.  
  2492.                                 /* variable with the lines for the    */
  2493.                                 /* target file                        */
  2494.   global.__TargetCode = ''
  2495.  
  2496.                                 /* last function or procedure name    */
  2497.   global._FuncName = ''
  2498.  
  2499.                                 /* stem for the lines from the source */
  2500.                                 /* file                               */
  2501.   sourceStem.0 = 0
  2502.  
  2503.                                 /* stem to temporary save the string  */
  2504.                                 /* constants                          */
  2505.   stringStem.0 = 0
  2506.  
  2507.                                 /* stem to temporary save the         */
  2508.                                 /* comments                           */
  2509.   commentStem.0 = 0
  2510.  
  2511.                                 /* name of the source file            */
  2512.   global.__sourceFile = ''
  2513.  
  2514.                                 /* name of the target file            */
  2515.   global.__targetFile = ''
  2516.  
  2517.                                 /* default line length for the target */
  2518.                                 /* file                               */
  2519.   global.__LineLength = 72
  2520.  
  2521.                                 /* default start indent value for the */
  2522.                                 /* lines                              */
  2523.   global.__IndentStart = 2
  2524.  
  2525.                                 /* default indent step value          */
  2526.   global.__IndentStep = 2
  2527.  
  2528.                                 /* ASCII codes to insert a new line   */
  2529.   global.__NewLine = global.__CRLF
  2530.  
  2531.                                 /* 1 : insert comments after END      */
  2532.                                 /*     statements                     */
  2533.   global.__InsertComments = 1
  2534.  
  2535.                                 /* 1 : delete all existing comments   */
  2536.   global.__DeleteComments = 0
  2537.  
  2538.                                 /* 1 : check the extension and the    */
  2539.                                 /*     format of the file             */
  2540.   global.__IgnoreExtension = 0
  2541.  
  2542.                                 /* 1 : insert function & procedure    */
  2543.                                 /*     headers                        */
  2544.   global.__InsertHeader = 1
  2545.  
  2546.                                 /* default function header            */
  2547.                                 /* place holder used:                 */
  2548.                                 /*   %f - insert the function name    */
  2549.                                 /*                                    */
  2550.   global.__functionHeader = ,
  2551.   global.__CRLF || ,
  2552. '/' || '* ------------------------------------------------------------------ *' || '/' || global.__CRLF || ,
  2553. '/' || '* function:                                                          *' || '/' || global.__CRLF || ,
  2554. '/' || '*                                                                    *' || '/' || global.__CRLF || ,
  2555. '/' || '* usage:     %f                                                      *' || '/' || global.__CRLF || ,
  2556. '/' || '*                                                                    *' || '/' || global.__CRLF || ,
  2557. '/' || '* where:     -                                                       *' || '/' || global.__CRLF || ,
  2558. '/' || '*                                                                    *' || '/' || global.__CRLF || ,
  2559. '/' || '* returns:   -                                                       *' || '/' || global.__CRLF || ,
  2560. '/' || '*                                                                    *' || '/' || global.__CRLF || ,
  2561. '/' || '*                                                                    *' || '/' || global.__CRLF || ,
  2562. '/' || '* notes:     -                                                       *' || '/' || global.__CRLF || ,
  2563. '/' || '*                                                                    *' || '/' || global.__CRLF || ,
  2564. '/' || '*                                                                    *' || '/' || global.__CRLF || ,
  2565. ''
  2566.                                 /* correct the expose list            */
  2567.   exposeList = exposeList 'stringStem. commentStem. sourceStem. '
  2568. RETURN
  2569.  
  2570. /* ------------------------------------------------------------------ */
  2571. /* function: prepare the function header                              */
  2572. /*                                                                    */
  2573. /* call:     PrepareFunctionHeader functionName                       */
  2574. /*                                                                    */
  2575. /* where:    functionName = name of the function/procedure            */
  2576. /*                                                                    */
  2577. /* returns:  the prepared function header                             */
  2578. /*                                                                    */
  2579. PrepareFunctionHeader: PROCEDURE expose (exposeList)
  2580.   parse arg functionName
  2581.  
  2582.   if global.__InsertHeader = 1 then
  2583.   do
  2584.     fHeader = global.__FunctionHeader
  2585.  
  2586.     if length( functionName ) = 1 then
  2587.       functionName = functionName || ' '
  2588.  
  2589.     do until i = 0
  2590.       i = pos( '%f', fHeader )
  2591.       if i <> 0 then
  2592.         fHeader = overlay( functionName, fHeader, i )
  2593.     end /* do until i = 0 */
  2594.  
  2595.   end /* if */
  2596.   else
  2597.     fHeader = ''
  2598.  
  2599. return fHeader
  2600.  
  2601. /* ------------------------------------------------------------------ */
  2602. /* function: replace comments in the source file with place holder    */
  2603. /*                                                                    */
  2604. /* call:     ReplaceComments                                          */
  2605. /*                                                                    */
  2606. /* where:    -                                                        */
  2607. /*                                                                    */
  2608. /* returns:  0 - ok                                                   */
  2609. /*           else  error                                              */
  2610. /*                                                                    */
  2611. /* input:    global.__SourceCode contains the source file contents    */
  2612. /*                                                                    */
  2613. /*                                                                    */
  2614. /* output:   global.__SourceCode contains the converted file contents */
  2615. /*                                                                    */
  2616. ReplaceComments: PROCEDURE expose (exposeList)
  2617.  
  2618.   cio = ''          /* <> '' if unmatched comment delimiter found     */
  2619.  
  2620.   if global.__DeleteComments <> 1 then
  2621.     call CharOut global.__DeviceForStatusMsgs,,
  2622.           '  Replacing comments ... Offset ' || screen.__SavePos
  2623.   else
  2624.     call CharOut global.__DeviceForStatusMsgs,,
  2625.           '  Deleting comments ... Offset ' || screen.__SavePos
  2626.  
  2627.                         /* search the start of the first comment      */
  2628.   i1 = pos( global.__c1 , global.__SourceCode )
  2629.  
  2630.   do while i1 <> 0
  2631.  
  2632.     call CharOut global.__DeviceForStatusMsgs,screen.__RestPos || i1
  2633.  
  2634.                 /* if 1: replace the comment with CR/LF               */
  2635.     global.__InsertEmptyLine = 0
  2636.  
  2637.                 /* save the position of the comment start delimiter   */
  2638.     i5 = i1
  2639.  
  2640.     do forever
  2641.                         /* search the end of the comment              */
  2642.       global.__NestedCommentLevel = 1
  2643.       i2 = FindCommentEnd( i1 )
  2644.  
  2645.       if i2 = 0 then
  2646.         leave           /* unmatched comments in the source file      */
  2647.  
  2648.                         /* check for sequential comment lines         */
  2649.       if substr( global.__SourceCode, i2+2,4 ) <> global.__CRLF || global.__c1 then
  2650.         leave           /* no comment following this line             */
  2651.  
  2652.                         /* sequential comment following               */
  2653.  
  2654.                         /* i1 = start of next comment                 */
  2655.       i1 = i2 +4
  2656.                         /* set the marker to replace this comment     */
  2657.                         /* with CR/LF                                 */
  2658.       global.__InsertEmptyLine = 1
  2659.  
  2660.     end /* do forever */
  2661.  
  2662.                         /* check for unmatched comments               */
  2663.     if i2 = 0 then
  2664.     do
  2665.                         /* unmatched comments in the file             */
  2666.       global.__Warnings = global.__Warnings + 1
  2667.       cio = global.__c1
  2668.       leave
  2669.     end /* if i2 = 0 then */
  2670.  
  2671.     if global.__DeleteComments <> 1 then
  2672.     do
  2673.                     /* save the comment in the comment stem           */
  2674.  
  2675.                     /* current index to the stem for the comments     */
  2676.       j = commentStem.0 +1
  2677.  
  2678.                     /* save the comment in the stem for the comments  */
  2679.       CommentStem.j = substr( global.__SourceCode, i5, i2-i5+2 )
  2680.     end /* if global.__DeleteComments <> 1 then */
  2681.  
  2682.                     /* delete the comment                             */
  2683.     global.__SourceCode = delStr( global.__SourceCode, i5, i2-i5+2 )
  2684.  
  2685.     if global.__DeleteComments <> 1 then
  2686.     do
  2687.                     /* insert a place holder                          */
  2688.       global.__SourceCode = insert( global.__CommentStartMarker || j || global.__CommentEndMarker ,,
  2689.                                     global.__SourceCode, i5-1, )
  2690.  
  2691.       CommentStem.0 = j
  2692.     end /* if global.__DeleteComments <> 1 then */
  2693.     else
  2694.       if global.__InsertEmptyLine = 1 then
  2695.         global.__SourceCode = insert( global.__CRLF, global.__SourceCode, i5-1 )
  2696.  
  2697.                     /* search the start of the next comment           */
  2698.     i1 = pos( global.__c1 , global.__SourceCode, i5 )
  2699.  
  2700.   end /* do forever */
  2701.  
  2702.   call LineOut global.__DeviceForStatusMsgs,,
  2703.         screen.__RestPos || copies( '08'x, 7) || ' done (' || ,
  2704.         AddColor1( , commentStem.0 ) || ' comment(s) found). ' || screen.__DelEOL
  2705.  
  2706.                     /* check for unmatched comment end delimiter      */
  2707.   if cio = '' & pos( global.__c2, global.__SourceCode ) <> 0 then
  2708.     cio = global.__c2
  2709.  
  2710.   if cio <> '' then
  2711.   do
  2712.     global.__Warnings = global.__Warnings + 1
  2713.  
  2714.     call ShowWarning 'Unmatched comment chars <' || ,
  2715.                      cio || '> in the sourcefile'
  2716.   end /* if cio <> '' then */
  2717.  
  2718. RETURN
  2719.  
  2720. /* ------------------------------------------------------------------ */
  2721. /* function: find the end of a comment                                */
  2722. /*                                                                    */
  2723. /* call:     FindCommentEnd commentStart                              */
  2724. /*                                                                    */
  2725. /* where:    commentStart - comment start offset                      */
  2726. /*                                                                    */
  2727. /* returns:  0 - error                                                */
  2728. /*           else  offset of the end of the comment                   */
  2729. /*                                                                    */
  2730. /*                                                                    */
  2731. FindCommentEnd: PROCEDURE expose (exposeList)
  2732.   parse arg i1
  2733.  
  2734.   global.__NestedCommentLevel = global.__NestedCommentLevel + 1
  2735.   if global.__NestedCommentLevel >= 40 then
  2736.     call ShowError global.__ErrorExitCode,,
  2737.           'Comment level nested to deep (max. is 40)'
  2738.  
  2739.   do until i2 < i3 | i3 = 0
  2740.  
  2741.                         /* i2 = end of comment                        */
  2742.     i2 = pos( global.__c2, global.__SourceCode, i1+2 )
  2743.  
  2744.                         /* i3 = start of next or imbedded comment     */
  2745.     i3 = pos( global.__c1, global.__SourceCode, i1+2 )
  2746.  
  2747.     if i3 < i2 & i3 <> 0 then
  2748.       i1 = FindCommentEnd( i3, 1 )      /* imbedded comment found     */
  2749.  
  2750.     if i1 = 0 then
  2751.     do
  2752.                         /* unmatched comment delimiter found          */
  2753.       i2 = 0
  2754.       leave
  2755.     end /* if i1 = 0 then */
  2756.  
  2757.   end /* do until i2 > i3 */
  2758.  
  2759. RETURN i2
  2760.  
  2761. /* ------------------------------------------------------------------ */
  2762. /* function: insert comments back into the source file                */
  2763. /*                                                                    */
  2764. /* call:     InsertComments                                           */
  2765. /*                                                                    */
  2766. /* where:    -                                                        */
  2767. /*                                                                    */
  2768. /* returns:  nothing                                                  */
  2769. /*                                                                    */
  2770. /* input:    global.__TargetCode contains the source file contents    */
  2771. /*                                                                    */
  2772. /* output:   global.__TargetCode contains the converted file contents */
  2773. /*                                                                    */
  2774. InsertComments: PROCEDURE expose (exposeList)
  2775.  
  2776.   call CharOut global.__DeviceForStatusMsgs,,
  2777.         '  Inserting comments again ... Comment ' || screen.__SavePos
  2778.  
  2779.   j = 0
  2780.   i1 = 1
  2781.  
  2782.   do forever
  2783.                         /* search comment place holder                */
  2784.     i1 = pos( global.__CommentStartMarker, global.__TargetCode, i1 )
  2785.     i2 = pos( global.__CommentEndMarker, global.__TargetCode, i1+1 )
  2786.     if i1 = 0 | i2 = 0 then
  2787.       leave
  2788.  
  2789.                         /* get the index for the comment stem         */
  2790.     j = substr( global.__TargetCode ,i1+1,i2-i1-1 )
  2791.  
  2792.     call CharOut global.__DeviceForStatusMsgs,,
  2793.           screen.__RestPos || j
  2794.  
  2795.                         /* delete the place holder                    */
  2796.     global.__TargetCode = delStr( global.__TargetCode,i1,i2-i1+1 )
  2797.  
  2798.                         /* insert the comment                         */
  2799.     global.__TargetCode = insert( commentStem.j, global.__TargetCode,i1-1 )
  2800.  
  2801.   end /* do forever */
  2802.  
  2803.   call LineOut global.__DeviceForStatusMsgs,,
  2804.         screen.__RestPos || copies( '08'x, 8) || ' done. ' || screen.__DelEOL
  2805.  
  2806. RETURN
  2807.  
  2808. /* ------------------------------------------------------------------ */
  2809. /* function: replace string constants in the source file with place   */
  2810. /*           holder                                                   */
  2811. /*                                                                    */
  2812. /* call:     ReplaceStrings                                           */
  2813. /*                                                                    */
  2814. /* where:    -                                                        */
  2815. /*                                                                    */
  2816. /* returns:  0 - ok                                                   */
  2817. /*           else  error                                              */
  2818. /*                                                                    */
  2819. /* input:    global.__SourceCode contains the source file contents    */
  2820. /*                                                                    */
  2821. /* output:   global.__SourceCode contains the converted file contents */
  2822. /*                                                                    */
  2823. ReplaceStrings: PROCEDURE expose (exposeList)
  2824.  
  2825.   cio = ''          /* <> '' if unmatched string delimiter found      */
  2826.  
  2827.   call CharOut global.__DeviceForStatusMsgs,,
  2828.         '  Replacing string constants ... Offset ' || screen.__SavePos
  2829.  
  2830.   i1 = 1
  2831.   i0 = 1
  2832.  
  2833.   do forever
  2834.  
  2835.                     /* take care of the two possible string constant  */
  2836.                     /* delimiters in REXX                             */
  2837.     i2 = pos( global.__StringChar2 , global.__SourceCode, i0 )
  2838.     i1 = pos( global.__StringChar1 , global.__SourceCode, i0 )
  2839.     
  2840.     if ( i2 < i1 | i1 = 0 ) & i2 <> 0 then
  2841.     do
  2842.       i1 = i2
  2843.       curStringChar = global.__StringChar2
  2844.     end /* if i1 < i2 then */
  2845.     else
  2846.     do
  2847.       curStringChar = global.__StringChar1
  2848.     end /* else */
  2849.  
  2850.     if i1 = 0 then
  2851.       leave
  2852.  
  2853.     call CharOut global.__DeviceForStatusMsgs,,
  2854.           screen.__RestPos || i1
  2855.  
  2856.     i2 = pos( curStringChar, global.__SourceCode, i1 +1 )
  2857.  
  2858.     if i2 = 0 then
  2859.     do
  2860.       global.__Warnings = global.__Warnings + 1
  2861.       cio = curStringChar
  2862.       leave
  2863.     end /* if i2 = 0 then */
  2864.  
  2865.                     /* current index to the stem for the string       */
  2866.                     /* constants                                      */
  2867.     j = stringStem.0 +1
  2868.  
  2869.                     /* save the comment in the stem for the string    */
  2870.                     /* constants                                      */
  2871.     StringStem.j = substr( global.__SourceCode, i1, i2-i1+1 )
  2872.  
  2873.                     /* delete the string constant                     */
  2874.     global.__SourceCode = delStr( global.__SourceCode, i1, i2-i1+1 )
  2875.  
  2876.                     /* and insert a marker                            */
  2877.     global.__SourceCode = insert( global.__StringStartMarker || j || global.__StringEndMarker ,,
  2878.                                   global.__SourceCode, i1-1,,
  2879.               )
  2880.  
  2881.     StringStem.0 = j
  2882.     i0 = i1
  2883.   end /* do forever */
  2884.  
  2885.   call LineOut global.__DeviceForStatusMsgs,,
  2886.         screen.__RestPos || copies( '08'x, 7) || ' done (' ||,
  2887.         AddColor1( , StringStem.0 ) || ' string constant(s) found). ' || screen.__DelEOL
  2888.  
  2889.   if cio <> '' then
  2890.     call ShowWarning 'Unmatched string chars <' || ,
  2891.                      cio || '> in the sourcefile'
  2892. RETURN
  2893.  
  2894. /* ------------------------------------------------------------------ */
  2895. /* function: insert string constants back into the source file        */
  2896. /*                                                                    */
  2897. /* call:     InsertStrings                                            */
  2898. /*                                                                    */
  2899. /* where:    -                                                        */
  2900. /*                                                                    */
  2901. /* returns:  nothing                                                  */
  2902. /*                                                                    */
  2903. /* input:    global.__TargetCode contains the source file contents    */
  2904. /*                                                                    */
  2905. /* output:   global.__TargetCode contains the converted file contents */
  2906. /*                                                                    */
  2907. InsertStrings: PROCEDURE expose (exposeList)
  2908.  
  2909.   call CharOut global.__DeviceForStatusMsgs,,
  2910.         '  Inserting string constants again ... String ' || screen.__SavePos
  2911.  
  2912.   j = 0
  2913.   i1 = 1
  2914.   do forever
  2915.                         /* search the string placeholder              */
  2916.     i1 = pos( global.__StringStartMarker, global.__TargetCode, i1 )
  2917.     i2 = pos( global.__StringEndMarker, global.__TargetCode, i1+1 )
  2918.     if i1 = 0 | i2 = 0 then
  2919.       leave
  2920.  
  2921.     call CharOut global.__DeviceForStatusMsgs,,
  2922.           screen.__RestPos || j
  2923.  
  2924.                         /* get the index for the strings stem         */
  2925.     j = substr( global.__TargetCode ,i1+1,i2-i1-1 )
  2926.  
  2927.                         /* delete the placeholder                     */
  2928.     global.__TargetCode = delStr( global.__TargetCode,i1,i2-i1+1 )
  2929.  
  2930.                         /* insert the string                          */
  2931.     global.__TargetCode = insert( stringStem.j,,
  2932.                                   global.__TargetCode,,
  2933.                                   i1-1 )
  2934.  
  2935.   end /* do forever */
  2936.  
  2937.   call LineOut global.__DeviceForStatusMsgs,,
  2938.         screen.__RestPos || copies( '08'x, 7) || ' done. ' || screen.__DelEOL
  2939.  
  2940. RETURN
  2941.  
  2942. /* ------------------------------------------------------------------ */
  2943. /* function: Read a file using CharIn()                               */
  2944. /*                                                                    */
  2945. /* call:     ReadFile fileName                                        */
  2946. /*                                                                    */
  2947. /* where:    fileName - name of the file to read                      */
  2948. /*                                                                    */
  2949. /* returns:  -1 - file not found                                      */
  2950. /*           0 - okay                                                 */
  2951. /*                                                                    */
  2952. /* output:   global.__SourceCode contains the file contents           */
  2953. /*                                                                    */
  2954. ReadFile: PROCEDURE expose (exposeList)
  2955.   parse arg fileName
  2956.  
  2957.                         /* init the return code                       */
  2958.   thisRC = -1
  2959.  
  2960.   if fileName <> "" then
  2961.     if stream( fileName, "c", "QUERY EXIST" ) <> "" then
  2962.     do
  2963.                             /* open the file in READ ONLY mode        */
  2964.       call stream fileName, "c", "OPEN READ"
  2965.  
  2966.                             /* read the complete file using Charin()  */
  2967.       global.__SourceCode = charIN( fileName, 1, chars( fileName ) ) || '0D0A'x
  2968.  
  2969.                             /* close the file                         */
  2970.       call stream fileName, "c", "CLOSE"
  2971.  
  2972.                             /* correct the return code                */
  2973.       thisRC = 0
  2974.     end /* if */
  2975.  
  2976. RETURN thisRC
  2977.  
  2978. /* ------------------------------------------------------------------ */
  2979. /* function: Write the file                                           */
  2980. /*                                                                    */
  2981. /* call:     WriteFile fileName                                       */
  2982. /*                                                                    */
  2983. /* where:    fileName - name of the file to write                     */
  2984. /*                                                                    */
  2985. /* returns:  nothing                                                  */
  2986. /*                                                                    */
  2987. /* input:    global.__TargetCode contains the file contents           */
  2988. /*                                                                    */
  2989. WriteFile: PROCEDURE expose (exposeList)
  2990.   parse arg tFile
  2991.  
  2992.                         /* delete the original file                   */
  2993.   ADDRESS 'CMD' '@del ' tFile  prog.__logAll
  2994.   if rc <> 0 then
  2995.     call ShowError global.__ErrorExitCode ,,
  2996.           'Error deleting the source file!'
  2997.  
  2998.                         /* open, write and close the converted file   */
  2999.   call stream tFile, 'c', 'OPEN WRITE'
  3000.   call CharOut tFile, global.__TargetCode
  3001.   call stream tFile, 'c', 'CLOSE'
  3002. RETURN
  3003.  
  3004. /* ------------------------------------------------------------------ */
  3005. /* Function: create a backup of a file                                */
  3006. /*                                                                    */
  3007. /* call:     CreateBackupFile fileToBackup                            */
  3008. /*                                                                    */
  3009. /* where:    fileToBackup = name of the file to backup                */
  3010. /*                                                                    */
  3011. /* returns:  nothing                                                  */
  3012. /*                                                                    */
  3013. CreateBackupFile: PROCEDURE EXPOSE (exposeList)
  3014.   parse arg cbf.oldfileName
  3015.  
  3016.   cbf.i = lastpos( '.', cbf.oldFileName )
  3017.   if cbf.i <> 0 then
  3018.     cbf.testFileName = substr( cbf.oldFileName, 1, cbf.i-1 )
  3019.   else
  3020.     cbf.testFileName = cbf.oldFileName
  3021.  
  3022.   do cbf.index=0 to 999
  3023.     cbf.newFileName = cbf.testFileName || '.' || copies( '0', 3 - LENGTH( cbf.index ) ) || cbf.index
  3024.     if stream( cbf.newFileName,'c', 'QUERY EXISTS' ) = '' then
  3025.       leave
  3026.     cbf.newFileName = ''
  3027.   end /* do cbf.index=0 to 999 */
  3028.  
  3029.   if cbf.newFilename = '' then
  3030.   do
  3031.                                 /* no possible file name found        */
  3032.     call ShowError global.__ErrorExitCode,,
  3033.           'Can not create a backup of the file "' || ,
  3034.                         cbf.oldfilename || '"'
  3035.   end /* if cbf.newFilename then */
  3036.   else
  3037.   do
  3038.                                 /* create the backup                  */
  3039.     call log '  Creating backup of the file ' || ,
  3040.              AddColor1( '"', cbf.oldFilename ) || ' with name ' || ,
  3041.              AddColor1( '"', cbf.newFileName )
  3042.  
  3043.     ADDRESS 'CMD' '@copy ' convertNameToOS( cbf.oldFileName ),
  3044.              convertNameToOS( cbf.newFileName ) '/V ' prog.__LogALL
  3045.     if rc <> 0 & rc <> "RC" then
  3046.       call ShowError global.__ErrorExitCode,,
  3047.             'Error creating a backup of the file "' || ,
  3048.             cbf.oldfilename || '"' || ' (RC is ' || RC || ')'
  3049.   end /* else */
  3050.  
  3051.   drop cbf.
  3052. RETURN
  3053.  
  3054. /* ------------------------------------------------------------------ */
  3055. /* function: Extended FILESPEC function                               */
  3056. /*                                                                    */
  3057. /* call:     FileSpec option,fileName                                 */
  3058. /*                                                                    */
  3059. /* where:    option                                                   */
  3060. /*             - E{xtension}                                          */
  3061. /*                 return the extension of the file                   */
  3062. /*             - B{asename}                                           */
  3063. /*                 returns the name of the file without extension     */
  3064. /*             All other values for "option" are processed by the     */
  3065. /*             original FILESPEC function.                            */
  3066. /*           fileName                                                 */
  3067. /*             - name of the file                                     */
  3068. /*                                                                    */
  3069. /* returns:  if option = E{xtension}:                                 */
  3070. /*             the extension of the fileName or "" if none            */
  3071. /*           else                                                     */
  3072. /*             if option = B{asename}:                                */
  3073. /*               the name of the file without the path and extension  */
  3074. /*             else                                                   */
  3075. /*               the return code of the original FILESPEC function    */
  3076. /*               or "SYNTAX ERROR" if called with invalid parameter   */
  3077. /*                                                                    */
  3078. /* note:     To call the original FILESPEC function direct use        */
  3079. /*             myResult = "FILESPEC"( option, fileName )              */
  3080. /*                                                                    */
  3081. /* Source:   REXX Tips & Tricks v1.90 by Bernd Schemmer               */
  3082. /*                                                                    */
  3083. FileSpec: PROCEDURE
  3084.   parse arg option, fileName
  3085.  
  3086.                         /* init the return code                       */
  3087.   rc = "SYNTAX ERROR"
  3088.                         /* install a local error handler              */
  3089.   SIGNAL ON SYNTAX NAME FileSpecError
  3090.  
  3091.   option = translate( strip( option ) )
  3092.  
  3093.                         /* check the option code                      */
  3094.   select
  3095.     when abbrev( "EXTENSION", option ) = 1 then
  3096.     do
  3097.                         /* process the new added option code          */
  3098.       i = lastPos( ".", fileName )
  3099.       if i > lastPos( "\", fileName ) then
  3100.         rc = substr( fileName, i+1 )
  3101.       else
  3102.         rc = ""
  3103.     end /* when */
  3104.  
  3105.     when abbrev( "BASENAME", option ) = 1 then
  3106.     do
  3107.       rc = "FILESPEC"( "N", fileName )
  3108.       i = lastpos( ".", rc )
  3109.       if i <> 0 then
  3110.         rc = substr( rc,1, i-1 )
  3111.     end /* when */
  3112.  
  3113.     otherwise
  3114.     do
  3115.                         /* call the original FILESPEC function        */
  3116.       rc = "FILESPEC"( option, fileName )
  3117.     end /* otherwise */
  3118.   end /* when */
  3119. FileSpecError:
  3120.  
  3121. RETURN rc
  3122.  
  3123. /* ------------------------------------------------------------------ */
  3124. /* Function: add quote chars and color codes to a string              */
  3125. /*                                                                    */
  3126. /* call:     AddColor1( quoteChar ,myString )                         */
  3127. /*                                                                    */
  3128. /* where:    quoteChar - leading and trailing character for the       */
  3129. /*                       converted string (may be ommited)            */
  3130. /*           myString - string to convert                             */
  3131. /*                                                                    */
  3132. /* returns:  converted string                                         */
  3133. /*                                                                    */
  3134. AddColor1: PROCEDURE expose (exposeList)
  3135.   parse arg qChar, mStr
  3136.  
  3137. return qChar || screen.__fgYellow || screen.__highlight || ,
  3138.        mStr || ,
  3139.        screen.__AttrOff || qChar
  3140.  
  3141. /* ------------------------------------------------------------------ */
  3142. /*-function: Get the options and parameter from the environment       */
  3143. /*           variable and from the command line                       */
  3144. /*                                                                    */
  3145. /*-call:     GetProgramOptions thisParameter                          */
  3146. /*                                                                    */
  3147. /*-where:    thisParameter = parameter for the program                */
  3148. /*                                                                    */
  3149. /*-returns:  nothing                                                  */
  3150. /*                                                                    */
  3151. /*                                                                    */
  3152. /*                                                                    */
  3153. GetProgramOptions: PROCEDURE expose (exposeList)
  3154.   parse arg thisParameter
  3155.  
  3156.                         /* first process the environment variable if  */
  3157.                         /* it is defined                              */
  3158.   envValue = value( global.__envVarName ,, prog.__env )
  3159.   if envValue <> '' then
  3160.   do
  3161.     envValue = strip( ProcessOptions( 'E', envValue ) )
  3162.     if envValue <> '' then
  3163.       call ShowError global.__ErrorExitCode ,,
  3164.             'Invalid options in the environment variable "' || ,
  3165.             global.__envVarName || ,
  3166.                            '. The invalid options are "' || envValue || '"'
  3167.  
  3168.   end /* if envValue <> '' then */
  3169.  
  3170.                         /* now process the parameater                 */
  3171.   thisParameter = ProcessOptions( 'P', thisParameter )
  3172.  
  3173.   global.__sourceFile = strip( thisParameter )
  3174.  
  3175.   select
  3176.     when left( global.__sourceFile, 1 ) = '"' & ,
  3177.         right( global.__sourceFile, 1 ) = '"' then
  3178.       parse var global.__sourceFile '"' global.__sourceFile '"'
  3179.  
  3180.     when left( global.__sourceFile, 1 ) = "'" & ,
  3181.         right( global.__sourceFile, 1 ) = "'" then
  3182.       parse var global.__sourceFile "'" global.__sourceFile "'"
  3183.  
  3184.     otherwise
  3185.       nop
  3186.   end /* select */
  3187.  
  3188.   if global.__sourceFile = '' then
  3189.     call ShowError global.__ErrorExitCode,,
  3190.           'Sourcefile parameter missing'
  3191.  
  3192. /* --------------------------- */
  3193. /* --- FOR DEBUGGING ONLY! --- */
  3194.  
  3195.   if global.__verbose <> '' then
  3196.   do
  3197.     call logDebugMsg 'Current values of the parameters:'
  3198.     call logDebugMsg '  Global.__LineLength      /LL   = ' || global.__LineLength
  3199.     call logDebugMsg '  Global.__EmptyLines      /NL   = ' || (global.__NewLine <> '')
  3200.     call logDebugMsg '  Global.__DeleteComments  /DL   = ' || global.__DeleteComments
  3201.     call logDebugMsg '  Global.__IndentStart     /SI   = ' || global.__IndentStart
  3202.     call logDebugMsg '  Global.__IndentStep      /BI   = ' || global.__IndentStep
  3203.     call logDebugMsg '  Global.__InsertComments  /CM   = ' || global.__InsertComments
  3204.     call logDebugMsg '  Global.__InsertHeader    /FH   = ' || global.__InsertHeader
  3205.     call logDebugMsg '  Global.__IgnoreExtension /IExt = ' || global.__IgnoreExtension
  3206.     call logDebugMsg '  Global.__SourceFile  =' '"' || global.__SourceFile || '"'
  3207.   end /* if global.__Verbose <> '' then */
  3208.  
  3209. /* -- END OF DEBUGGING CODE -- */
  3210. /* --------------------------- */
  3211.  
  3212. RETURN
  3213.  
  3214. /* ------------------------------------------------------------------ */
  3215. /*-function: Process the options for the program                      */
  3216. /*                                                                    */
  3217. /*-call:     ProcessOptions sourceTyp, optionString                   */
  3218. /*                                                                    */
  3219. /*-where:    sourceType = 'E' - environment variable                  */
  3220. /*                        'P' - parameter                             */
  3221. /*                        'S' - get usage help for additional         */
  3222. /*                              parameter                             */
  3223. /*           optionString = string with the options                   */
  3224. /*                                                                    */
  3225. /*-returns:  if sourceType = 'E' or 'P':                              */
  3226. /*             the remaining string after extracting the options      */
  3227. /*           if sourceType = 'S':                                     */
  3228. /*             string with the additional parameter                   */
  3229. /*                                                                    */
  3230. /*                                                                    */
  3231. /*                                                                    */
  3232. ProcessOptions: PROCEDURE expose (exposeList)
  3233.   parse arg sourceTyp, OptionString
  3234.  
  3235.   if sourceTyp = 'S' then
  3236.   do
  3237.                     /* return the additional options for the program  */
  3238.                     /* (used by the ShowUsage routine)                */
  3239.     return 'sourceFile {/LL:n} {/SI:n} {/BI:n} {/FH{:n}} {/CM{:n}} {/NL{:n}} {/DL{:n}} {/IE{xt}{:n}}'
  3240.   end
  3241.  
  3242.   if sourceTyp = 'E' then
  3243.     sourceMsg = ' in the environment variable "' || global.__envVarName || '"'
  3244.   else
  3245.     sourceMsg = ' in the parameters'
  3246.  
  3247.   do forever
  3248.  
  3249.     parse var optionString optionString '/' curOption rest
  3250.     optionString = optionString rest
  3251.     parse var curOption switchName ':' switchValue
  3252.  
  3253.     switchName = translate( switchName )
  3254.  
  3255.     select
  3256.  
  3257.       when switchName = '' then
  3258.         leave
  3259.  
  3260.       when switchName = 'NL' then
  3261.       do
  3262.         if CheckOptionValue( switchname,switchValue,sourceMsg,0,1,1 ) = 0 then
  3263.           global.__NewLine = ''
  3264.         else
  3265.           global.__NewLine = '0D0A'x
  3266.       end /* when */
  3267.  
  3268.       when switchName = 'SI' then
  3269.       do
  3270.         global.__IndentStart = CheckOptionValue( switchname,switchValue,sourceMsg,0 )
  3271.       end /* when */
  3272.  
  3273.       when switchName = 'LL' then
  3274.       do
  3275.         global.__LineLength = ,
  3276.           CheckOptionValue( switchname,switchValue,sourceMsg,60 )
  3277.       end /* when */
  3278.  
  3279.       when switchName = 'IE' | switchName = 'IEXT' then
  3280.       do
  3281.         global.__IgnoreExtension = ,
  3282.           CheckOptionValue( switchname,switchValue,sourceMsg,0,1,1 )
  3283.       end /* when */
  3284.  
  3285.       when switchName = 'BI' then
  3286.       do
  3287.         global.__IndentStep = ,
  3288.           CheckOptionValue( switchname,switchValue,sourceMsg,0 )
  3289.       end /* when */
  3290.  
  3291.       when switchName = 'FH' then
  3292.       do
  3293.         global.__InsertHeader = ,
  3294.           CheckOptionValue( switchname,switchValue,sourceMsg,0,1,1 )
  3295.       end /* when */
  3296.  
  3297.       when switchName = 'DL' then
  3298.       do
  3299.         global.__DeleteComments = ,
  3300.           CheckOptionValue( switchname,switchValue,sourceMsg,0,1,1 )
  3301.       end /* when */
  3302.  
  3303.       when switchName = 'CM' then
  3304.       do
  3305.         global.__InsertComments = ,
  3306.           CheckOptionValue( switchname,switchValue,sourceMsg,0,1,1 )
  3307.       end /* when */
  3308.  
  3309.       otherwise
  3310.       do
  3311.         call ShowError global.__ErrorExitCode,,
  3312.               'Invalid switch found' || sourceMsg || ,
  3313.               '. The invalid switch is "' || switchName || '"'
  3314.       end /* otherwise */
  3315.  
  3316.     end /* select */
  3317.  
  3318.   end /* do forever */
  3319. RETURN optionString
  3320.  
  3321. /* ------------------------------------------------------------------ */
  3322. /*-function: check the value of an option                             */
  3323. /*                                                                    */
  3324. /*-call:     CheckOptionValue switchName, switchValue, sourceMsg,,    */
  3325. /*                            minValue, maxValue, default             */
  3326. /*                                                                    */
  3327. /*-where:    switchName  - name of the switch                         */
  3328. /*           switchValue - value of the switch                        */
  3329. /*           sourceMsg - source for the option                        */
  3330. /*           minValue - minimum value                                 */
  3331. /*           maxValue - maximum value                                 */
  3332. /*           default - default value if the switch is specified with  */
  3333. /*                     no value                                       */
  3334. /*                                                                    */
  3335. /*-returns:  if ok: the value                                         */
  3336. /*           else: program abort                                      */
  3337. /*                                                                    */
  3338. /*                                                                    */
  3339. /*                                                                    */
  3340. CheckOptionValue: PROCEDURE expose (exposeList)
  3341.   parse arg switchName, switchValue, sourceMsg, minValue, maxValue, default
  3342.  
  3343.   thisValue = ''
  3344.  
  3345.                     /* use the default value if no value specified    */
  3346.   if switchValue = '' & default <> '' then
  3347.     switchValue = default
  3348.  
  3349.   if datatype( switchValue, 'W' ) <> 1 then
  3350.     call ShowError global.__ErrorExitCode,,
  3351.            'Invalid value for switch "' || switchName || '" found' ||,
  3352.            sourceMsg || '. The invalid value is "' || switchValue || '"'
  3353.   else
  3354.   do
  3355.     thisValue = switchValue
  3356.  
  3357.     if (minValue <> '' & thisValue < minValue) |,
  3358.        (maxValue <> '' & thisValue > maxValue) then
  3359.     do
  3360.       if minValue = '' then
  3361.         minValue = 'n'
  3362.       if maxValue = '' then
  3363.         maxValue = 'm'
  3364.  
  3365.       call ShowError global.__ErrorExitCode,,
  3366.              'The value for the switch "' || switchname || ,
  3367.              '" must be in the range ' || ,
  3368.              minValue || ' ... ' || maxValue
  3369.     end /* if */
  3370.   end /* else */
  3371.  
  3372. RETURN thisValue
  3373.  
  3374. /* ------------------------------------------------------------------ */
  3375. /*-function: Show the invocation syntax                               */
  3376. /*                                                                    */
  3377. /*-call:     called by the runtime system with                        */
  3378. /*           => call ShowUsage <=                                     */
  3379. /*                                                                    */
  3380. /*-where:    -                                                        */
  3381. /*                                                                    */
  3382. /*-returns:  ''                                                       */
  3383. /*                                                                    */
  3384. /*                                                                    */
  3385. ShowUsage: PROCEDURE expose (exposeList)
  3386.   call ShowString I!.__GetMsg( 14 ) || ' ' || prog.__name || ' ',,
  3387.            ProcessOptions( 'S' ) ,
  3388.            prog.__DefParms
  3389. RETURN ''
  3390.  
  3391. /* ------------------------------------------------------------------ */
  3392.  
  3393. /*** DEBUGGING SUBROUTINES ***/
  3394.  
  3395. /* ------------------------------------------------------------------ */
  3396. /* function: Write internal variables to a file                       */
  3397. /*                                                                    */
  3398. /* call:     WriteInternalVariablesToFile sFile                       */
  3399. /*                                                                    */
  3400. /* where:    sFile - name of the source file                          */
  3401. /*                                                                    */
  3402. /* returns:  nothing                                                  */
  3403. /*                                                                    */
  3404. WriteInternalVariablesToFile: PROCEDURE expose (exposeList)
  3405.   parse arg sFile
  3406.                     /* create filenames for the files to hold the     */
  3407.                     /* internal data                                  */
  3408.   global.__DebugCmtFile = FileSpec( 'B', sFile ) || '.CMT'
  3409.   global.__DebugStrFile = FileSpec( 'B', sFile ) || '.STR'
  3410.   global.__DebugSrcFile = FileSpec( 'B', sFile ) || '.SCR'
  3411.   global.__DebugTmpFile = FileSpec( 'B', sFile ) || '.TMP'
  3412.  
  3413.   call logDebugMsg 'Writing the comment stem to "' || ,
  3414.                    global.__debugCmtFile || '" ...'
  3415.   ADDRESS 'CMD' '@del ' ConvertNameToOS( global.__DebugCmtFile ) prog.__logAll
  3416.   call LineOut global.__DebugCmtFile, 'There are ' || ,
  3417.                                       commentStem.0 ,
  3418.                                       ' entrys in the comment stem:'
  3419.   do i = 1 to commentStem.0
  3420.     call LineOut global.__DebugCmtFile, i || ': >>' || commentStem.i || '<<'
  3421.   end
  3422.   call stream global.__DebugCmtFile , 'c', 'CLOSE'
  3423.  
  3424.   call logDebugMsg 'Writing the string constant stem to "' || ,
  3425.                    global.__DebugStrFile || '" ...'
  3426.  
  3427.   ADDRESS 'CMD' '@del ' ConvertNameToOS( global.__DebugStrFile ) prog.__logAll
  3428.   call LineOut global.__DebugStrFile, 'There are ' || ,
  3429.                                       stringStem.0 ,
  3430.                                       ' entrys in the string constant stem:'
  3431.   do i = 1 to stringStem.0
  3432.     call LineOut global.__DebugStrFile, i || ': >>' || stringStem.i || '<<'
  3433.   end
  3434.   call stream global.__DebugStrFile , 'c', 'CLOSE'
  3435.  
  3436.   call LogDebugMsg 'Writing the source code to "' || ,
  3437.                    global.__DebugSrcFile || '" ...'
  3438.   ADDRESS 'CMD' '@del ' ConvertNameToOS( global.__DebugSrcFile ) prog.__LogAll
  3439.  
  3440.   call CharOut global.__DebugSrcFile, global.__SourceCode
  3441.   call stream global.__DebugSrcFile, 'c', 'CLOSE'
  3442.  
  3443.   call logDebugMsg 'Writing the sourcelines stem to "' || ,
  3444.                    global.__debugTmpFile || '" ...'
  3445.   ADDRESS 'CMD' '@del ' ConvertNameToOS( global.__DebugTmpFile ) prog.__logAll
  3446.   call LineOut global.__DebugTmpFile, 'There are ' || ,
  3447.                                       sourceStem.0 ,
  3448.                                       ' entrys in the sourceLines stem:'
  3449.   do i = 1 to sourceStem.0
  3450.     call LineOut global.__DebugTmpFile, i || ': >>' || sourceStem.i || '<<'
  3451.   end
  3452.   call stream global.__DebugTmpFile , 'c', 'CLOSE'
  3453.  
  3454. RETURN
  3455.  
  3456. /* ------------------------------------------------------------------ */
  3457. /* NOTE: You must uncomment this routines before using them!!!        */
  3458.  
  3459. /**DEBUG** Delete this line before using the debugging routines!!!
  3460.  
  3461. /* ------------------------------------------------------------------ */
  3462. /* function: show all variables defined for the routine calling       */
  3463. /*           this routine.                                            */
  3464. /*                                                                    */
  3465. /* call:     ShowDefinedVariables {N}, {varMask}                      */
  3466. /*                                                                    */
  3467. /* where:    N - no pause if the screen is full                       */
  3468. /*           varMask - mask for the variables                         */
  3469. /*                                                                    */
  3470. /* returns:  nothing                                                  */
  3471. /*                                                                    */
  3472. /* note:     This routine needs the DLL YDBAUTIL.                     */
  3473. /*           Be aware that the special REXX variables SIGL, RC and    */
  3474. /*           RESULT are changed if you call this routine!             */
  3475. /*                                                                    */
  3476. /*           This routine uses Dave Bolls excellent DLL YDBAUTIL      */
  3477. /*                                                                    */
  3478. /*                                                                    */
  3479. ShowDefinedVariables:
  3480.   parse upper arg SDV.__pauseMode, SDV.__varMask
  3481.  
  3482.                                 /* install a local error handler      */
  3483.   signal on syntax name SDV.__YDbaUtilNotFound
  3484.  
  3485.                                 /* load the necessary DLL function    */
  3486.   if RxFuncQuery( 'RxVList' ) then
  3487.     call rxFuncAdd 'RxVlist', 'YdbaUtil', 'RxVList'
  3488.  
  3489.   if RxFuncQuery( 'RxPullQueue' ) then
  3490.     call rxFuncAdd 'RxPullQueue', 'YdbaUtil', 'RxPullQueue'
  3491.  
  3492.                                 /* create a queue for the variables   */
  3493.   SDV.__newQueue = rxqueue( 'create' )
  3494.  
  3495.                                 /* the 'D' parameter of the RxVList   */
  3496.                                 /* functions won't pause if the       */
  3497.                                 /* screen is full                     */
  3498.   SDV.__thisRC = RxVList( SDV.__varMask, 'V' , SDV.__newQueue )
  3499.  
  3500.                                 /* ignore local variables of this     */
  3501.                                 /* routine                            */
  3502.   SDV.__thisRC = SDV.__thisRC
  3503.  
  3504.   call log '  ' || copies( '─',76 )
  3505.  
  3506.   if SDV.__thisRC <> 0 then
  3507.   do
  3508.  
  3509.     call log '  Defined variable(s) and their values:'
  3510.     SDV.__i = 0
  3511.  
  3512.     do SDV.__n = 1 to SDV.__ThisRC
  3513.       if SDV.__i >= prog.__ScreenRows-2 & ,
  3514.          SDV.__pauseMode <> 'N' then
  3515.       do
  3516.         ADDRESS 'CMD' 'PAUSE'
  3517.         SDV.__i = 0
  3518.       end /* if */
  3519.       SDV.__varName = RxPullQueue( SDV.__newQueue, 'Nowait', 'SDV.__dummy' )
  3520.       SDV.__varValue = RxPullQueue( SDV.__newQueue, 'Nowait', 'SDV.__dummy' )
  3521.  
  3522.                                 /* ignore local variables of this     */
  3523.                                 /* routine                            */
  3524.       if left( SDV.__varName, 6 ) <> 'SDV.__' then
  3525.       do
  3526.         call log '     ' || SDV.__varName || ' = "' || SDV.__varValue ||,
  3527.                  '"' || screen.__AttrOff || screen.__DelEOL
  3528.         SDV.__i = SDV.__i+1
  3529.       end /* if right( ... */
  3530.  
  3531.     end /* do */
  3532.  
  3533.                         /* delete the queue for the variables         */
  3534.     call rxqueue 'Delete', SDV.__newQueue
  3535.   end
  3536.   else
  3537.     call log '  No variables defined.'
  3538.   call log '  ' || copies( '─',76 )
  3539.  
  3540.                         /* delete local variables                     */
  3541.   drop SDV.
  3542. return ''
  3543.                         /* error exit for ShowDefinedVariables        */
  3544. SDV.__YDbaUtilNotFound:
  3545.   call ShowError global.__ErrorExitCode ,,
  3546.         'ShowDefinedVariables: YDBAUTIL not found'
  3547. return
  3548.  
  3549.    Delete this line before using the debugging routines!!!    **DEBUG**/
  3550.  
  3551. /***        End of Part 4 of the source code of TEMPLATE.CMD        ***/
  3552. /**********************************************************************/
  3553.    
  3554.