home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 18 REXX / 18-REXX.zip / rxtmp2.zip / MAKECMD.CMD next >
OS/2 REXX Batch file  |  1995-01-08  |  88KB  |  1,983 lines

  1. /* ------------------------------------------------------------------ */
  2. /* MAKECMD.CMD - update the runtime system for REXX programs based on */
  3. /*               TEMPLATE v2.+                                        */
  4. /*                                                                    */
  5. /* (c) Copyright Bernd Schemmer 1994,1995                             */
  6. /*                                                                    */
  7. /* Author:                                                            */
  8. /*   Bernd Schemmer                                                   */
  9. /*   Baeckerweg 48                                                    */
  10. /*   D-60316 Frankfurt am Main                                        */
  11. /*   Germany                                                          */
  12. /*   Compuserve: 100104,613                                           */
  13. /*                                                                    */
  14. /* Usage:                                                             */
  15. /*   MAKECMD {sourceFiles} {targetDir} {TEMPLATEFile}                 */
  16. /*                                                                    */
  17. /* where:                                                             */
  18. /*   sourceFiles                                                      */
  19. /*     - source files (joker ok, def.: .\*.SRC)                       */
  20. /*       MAKECMD assumes that files with the extension .SRC           */
  21. /*       are files created with MAKESRC.CMD but you can also use      */
  22. /*       MAKECMD for full functional .CMD-files based on              */
  23. /*       TEMPLATE v2.+. This files must have the extension .CMD.      */
  24. /*                                                                    */
  25. /*   targetDir                                                        */
  26. /*     - directory for the target files (def. parent dir [..])        */
  27. /*                                                                    */
  28. /*   templateFile                                                     */
  29. /*     - file with the runtime system for the cmds                    */
  30. /*       (def.: .\TEMPLATE.CMD)                                       */
  31. /*                                                                    */
  32. /* returns:                                                           */
  33. /*   0 - okay                                                         */
  34. /*  else error                                                        */
  35. /*                                                                    */
  36. /* IMPORTANT:                                                         */
  37. /*   MAKECMD updates only those files, from which the targetfile      */
  38. /*   is out of date compared to the date of the sourcefile or the     */
  39. /*   date of the templatefile.                                        */
  40. /*   Not existing targetfiles are created. To force an update in any  */
  41. /*   case delete the targetfiles.                                     */
  42. /*                                                                    */
  43. /*   To use this program you MUST LEAVE the lines                     */
  44. /*                                                                    */
  45. /*      ... Start of Part n of the source code of TEMPLATE.CMD ...    */
  46. /*                                                                    */
  47. /*   and                                                              */
  48. /*                                                                    */
  49. /*      ...  End of Part n of the source code of TEMPLATE.CMD ...     */
  50. /*                                                                    */
  51. /*   (where n is 1,2,3 or 4) in your programs!!!                      */
  52. /*   You may only change the lines prior to the line                  */
  53. /*                                                                    */
  54. /*      ...  End of Part n of the source code of TEMPLATE ...         */
  55. /*                                                                    */
  56. /*   (with n=1) and the lines after the line                          */
  57. /*                                                                    */
  58. /*      ... Start of Part n of the source code of TEMPLATE ...        */
  59. /*                                                                    */
  60. /*   (with n=4) in your programs!                                     */
  61. /*                                                                    */
  62. /* Notes:                                                             */
  63. /*   This cmd needs the programs RXQUEUE and ATTRIB to be in the PATH.*/
  64. /*   Sourcefiles with an extension not equal .SRC or .CMD are only    */
  65. /*   copied.                                                          */
  66. /*   You may use the file MAKECMD.INI in the source directory to      */
  67. /*   exclude some files from the update process.                      */
  68. /*   This is helpful if you're using a filemask for the parameter     */
  69. /*   sourcefile.                                                      */
  70. /*   The format of MAKECMD.INI is:                                    */
  71. /*                                                                    */
  72.  
  73. /*------------------ Start of example --------------------------------*\
  74. ;
  75. ; this is an example ini file for makecmd.cmd
  76. ; (lines beginning with a semikolon are comment lines)
  77. ;
  78. ; files to copy (no further action):
  79. COPY: CID.INC DEFAULT.CMD 
  80. ;
  81. ; files to exclude (no action at all):
  82. ;
  83. EXCLUDE: __GEFM__ MAKECMD.INI MAKECMD.CMD MAKE.CMD
  84. EXCLUDE: MAKESRC.CMD
  85. EXCLUDE: MAKELOG.BAK MAKELOG.LOG
  86. ;
  87. \*-------------------- End of example --------------------------------*/
  88.  
  89. /*                                                                    */
  90. /* History:                                                           */
  91. /*   02.12.1994 /bs v1.00                                             */
  92. /*   03.12.1994 /bs                                                   */
  93. /*   14.12.1994 /bs v1.10                                             */
  94. /*     - changed messages for one file compiles                       */
  95. /*   18.12.1994 /bs v1.15                                             */
  96. /*     - added code to create the tokenimage of the target files      */
  97. /*   08.01.1995 /bs v1.20                                             */
  98. /*     - first public release                                         */
  99. /*                                                                    */
  100. /* Distribution:                                                      */
  101. /*   This program is part of the TEMPLATE package. See the file       */
  102. /*   README.DOC from this package or the file TEMPLATE.CMD for my     */
  103. /*   distribution and using policy.                                   */
  104. /*   If you need further help, you may write me a message.            */
  105. /*                                                                    */
  106. /*                                                                    */
  107. /* Based on TEMPLATE.CMD v2.52, TEMPLATE is (c) 1995 Bernd Schemmer,  */
  108. /* Baeckerweg 48, D-60316 Frankfurt, Germany, Compuserve: 100104,613  */
  109. /*                                                                    */
  110. /* ------------------------------------------------------------------ */
  111.  
  112.                         /* init all global stems                      */
  113. parse value '' with prog. global. screen. I!.
  114.  
  115. /* ------------------------------------------------------------------ */
  116. /*** change the following values to your need                       ***/
  117.  
  118.          global.__Version = 1.20         /* Version of MAKECMD.CMD    */
  119.  
  120.        global.__SignOnMsg = 1   /* set to 0 if you do not want the    */
  121.                                 /* program start and end messages     */
  122.  
  123.          global.__NeedCID = 0   /* set to 1 if you need CID support   */
  124.  
  125.       global.__NeedColors = 1   /* set to 1 if you want colored msgs  */
  126.  
  127.   global.__NeedPatchCheck = 1   /* set to 1 if you want the program   */
  128.                                 /* to search for a patched version of */
  129.                                 /* this program                       */
  130.  
  131. /***                End of variables to change                      ***/
  132. /*      HINT: The further program code is in the function MAIN        */
  133.  
  134. /***        End of Part 1 of the source code of TEMPLATE.CMD        ***/
  135.  
  136.  
  137. /***       Start of Part 2 of the source code of TEMPLATE.CMD       ***/
  138.  
  139. /*************** DO NOT CHANGE THE FOLLOWING LINES ********************/
  140.  
  141.                         /* names of the global variables, which all   */
  142.                         /* procedures must know                       */
  143. exposeList = 'prog. screen. I!. global. exposeList '
  144.  
  145.                         /* init all global stems                      */
  146. parse value '' with prog. screen. I!.
  147.  
  148.                         /* get the number of the first line with      */
  149.                         /* user code                                  */
  150. call I!.__GetUserCode
  151.  
  152. /* ------------------------------------------------------------------ */
  153. /* install the error handler                                          */
  154.  
  155.                         /* break errors (CTRL-C)                      */
  156.   CALL ON HALT        NAME I!.__UserAbort
  157.                         /* syntax errors                              */
  158.   SIGNAL ON SYNTAX    NAME I!.__ErrorAbort
  159.                         /* using of not initialisized variables       */
  160.   SIGNAL ON NOVALUE   NAME I!.__ErrorAbort
  161.                         /*                                            */
  162.   SIGNAL ON FAILURE   NAME I!.__ErrorAbort
  163.                         /*                                            */
  164.   SIGNAL ON ERROR     NAME I!.__ErrorAbort
  165.                         /*                                            */
  166.   SIGNAL ON NOTREADY  NAME I!.__ErrorAbort
  167.  
  168. /* ------------------------------------------------------------------ */
  169. /* init the variables                                                 */
  170.  
  171.   parse arg I!.__RealParameter
  172.  
  173.   prog.__QParm = '/SILENT'
  174.  
  175.                         /* check for the parameter /SILENT            */
  176.   if pos( prog.__QParm, translate( I!.__RealParameter ) ) <> 0 then
  177.   do
  178.     parse var I!.__RealParameter prog.__Param (prog.__QParm) I!.__rest
  179.     prog.__Param = prog.__Param I!.__Rest
  180.     prog.__QuietMode = 1
  181.   end /* if pos( ... */
  182.   else
  183.     prog.__Param = I!.__RealParameter
  184.   call I!.__InitVars
  185.  
  186. /* ------------------------------------------------------------------ */
  187. /* show program start message                                         */
  188.  
  189.   if global.__SignOnMsg = 1 then
  190.   do
  191.     screen.__CurColor = screen.__SignOnColor
  192.     call Log prog.__Name || " " || global.__version || " started on " || ,
  193.          date() || ' at ' || time() || ' ...'
  194.     screen.__CurColor = screen.__NormalColor
  195.   end /* if global.__SignOnMsg = 1 then */
  196.  
  197. /* ------------------------------------------------------------------ */
  198.  
  199.                         /* check if there is a patched version of     */
  200.                         /* this program                               */
  201.   if global.__NeedPatchCheck <> 0 then
  202.     call I!.__CheckPatch
  203.  
  204. /* ------------------------------------------------------------------ */
  205.                         /* check for a help parameter                 */
  206.   if pos( translate( word( prog.__Param,1 ) ), ,
  207.           '/?/H/HELP/-?-H-HELP' ) <> 0 then
  208.   do
  209.     prog.__exitCode = 253
  210.  
  211.     call I!.__CallUserProc 1, 'ShowUsage'
  212.  
  213.     SIGNAL I!.__programEnd
  214.  
  215.   end /* pos( translate( ... */
  216.  
  217. /* ------------------------------------------------------------------ */
  218.  
  219.                         /* call the main procedure                    */
  220.   call I!.__CallUserProc 2, 'main' prog.__Param
  221.                         /* set prog.__ExitCode to the return          */
  222.                         /* code of the function main, if any          */
  223.                         /* returned                                   */
  224.   if symbol( 'I!.__UserProcRC' ) = 'VAR' then
  225.     prog.__ExitCode = I!.__UserProcRC
  226.  
  227. /* ------------------------------------------------------------------ */
  228. /* house keeping                                                      */
  229.  
  230. I!.__ProgramEnd:
  231.  
  232.                                 /* call exit routines                 */
  233.   do while strip( prog.__exitRoutines ) <> ''
  234.     I!.__CurExitRoutine = word( prog.__ExitRoutines,1 )
  235.  
  236.                         /* delete the name of the routine from the    */
  237.                         /* list to avoid endless loops!               */
  238.     prog.__ExitRoutines = substr( prog.__ExitRoutines , ,
  239.                           Pos( I!.__CurExitRoutine, ,
  240.                                prog.__ExitRoutines ) + ,
  241.                           length( I!.__CurExitRoutine ) )
  242.  
  243.     call I!.__CallUserProc 1, I!.__CurExitRoutine
  244.  
  245.   end /* do while strip( prog.__ExitRoutines ) <> '' */
  246.  
  247.                                 /* reset the current directory        */
  248.   if symbol( 'prog.__CurDir' ) = 'VAR' then
  249.     call directory prog.__CurDir
  250.  
  251.   if global.__SignOnMsg = 1 then
  252.   do
  253.                                 /* check if the exit code is decimal  */
  254.     if dataType( prog.__ExitCode, "W" ) then
  255.     do
  256.                                 /* convert exit code to hexadecimal   */
  257.       if prog.__ExitCode < 0 then
  258.         prog.__ExitCode = 65536 + prog.__ExitCode
  259.       prog.__hexExitCode = " ('" || D2X( prog.__ExitCode ) || "'x)"
  260.     end /* if .. */
  261.     else
  262.       prog.__hexExitCode = ''
  263.  
  264.                                 /* show program end message           */
  265.     screen.__CurColor = screen.__SignOnColor
  266.     call Log prog.__Name || " " || global.__Version || " ended on " || ,
  267.          date() || ' at ' || time() || ' with RC = ' || ,
  268.          prog.__ExitCode || prog.__hexExitCode
  269.  
  270.     screen.__CurColor = screen.__NormalColor
  271.   end /* if global.__SignOnMsg = 1 then */
  272.  
  273. EXIT prog.__ExitCode
  274.  
  275. /* ------------------------------------------------------------------ */
  276. /*-function: call a user defined routine                              */
  277. /*           (avoid errors if the routine is not defined)             */
  278. /*                                                                    */
  279. /*-call:     I!.__CallUserProc errorAction, procName {prcoParameter}  */
  280. /*                                                                    */
  281. /*-where:    errorAction - action, if procName is not defined         */
  282. /*                         0: do nothing (only set the RC)            */
  283. /*                         1: show a warning and set the RC           */
  284. /*                         2: abort the program                       */
  285. /*           procName - name of the procedure                         */
  286. /*           procParameter - parameter for the procedure              */
  287. /*                                                                    */
  288. /*-returns:  1 - ok                                                   */
  289. /*           0 - procname not found                                   */
  290. /*                                                                    */
  291. /*-output:   I!.__UserProcRC - Returncode of the called procedure     */
  292. /*                             (uninitialisied if the proedure didn't */
  293. /*                             reeturn a value)                       */
  294. /*                                                                    */
  295. I!.__CallUserProc: PROCEDURE expose (exposeList) result rc sigl
  296.   parse arg I!.__ErrorAction , I!.__procName I!.__procParameter
  297.  
  298.   I!.__thisRC = 0
  299.   drop I!.__UserProcRC
  300.  
  301.   iLine =  'call ' I!.__procName
  302.  
  303.   if I!.__procParameter <> '' then
  304.   do
  305.     if pos( '"' , I!.__procParameter ) = 0 then
  306.       iLine = iLine || ' "' I!.__procParameter '"'
  307.     else
  308.       iLine = iLine || " '" I!.__procParameter "'"
  309.   end /* if I!.__procParameter <> '' then */
  310.  
  311. /*  I!.__MaxLength = 263 */
  312.   if length( iLine ) > 263 then
  313.     call ShowError global.__ErrorExitCode ,,
  314.          'To many parameters defined for the call of the routine "' || ,
  315.          I!.__procName || '" (The max. length for the parameter is ' || ,
  316.          263 - length( I!.__procName ) -11 || ')'
  317. /*  drop I!.__maxLength */
  318.  
  319. /*** DO NOT CHANGE, ADD OR DELETE ONE OF THE FOLLOWING FOUR LINES!! ***/
  320.   SIGNAL I!.__CallUserProc1
  321. I!.__CallUserProc1:
  322.   I!.__InterpretCMDLine = sigl + 3
  323.   interpret iLine
  324. /*** DO NOT CHANGE, ADD OR DELETE ONE OF THE PRECEEDING FOUR LINES! ***/
  325.  
  326.   I!.__thisRC = 1
  327.   if symbol( 'RESULT' ) = 'VAR' then
  328.     I!.__UserProcRC = value( 'RESULT' )
  329.  
  330. I!.__CallUserProc2:
  331.  
  332.   if I!.__ThisRC = 0 then
  333.     select
  334.       when I!.__ErrorAction = 0 then
  335.         nop
  336.       when I!.__ErrorAction = 1 then
  337.         call ShowWarning 'Can not find the routine "' || ,
  338.                          I!.__procName || '"'
  339.       when I!.__ErrorAction = 2 then
  340.         call ShowError global.__ErrorExitCode , ,
  341.                        'Can not find the routine "' || I!.__procName || '"'
  342.     end /* select */
  343.  
  344. RETURN I!.__thisRC
  345.  
  346. /* ------------------------------------------------------------------ */
  347. /*-function: set the variables for the logfile handling               */
  348. /*                                                                    */
  349. /*-call:     I!.__SetLogVars                                          */
  350. /*                                                                    */
  351. /*-input:    prog.__Param - parameter for the program                 */
  352. /*                                                                    */
  353. /*-output:   prog.__LogFile     - name of the logfile (or NUL)        */
  354. /*           prog.__LogSTDERR   - string to direct STDERR into the    */
  355. /*                                logfile                             */
  356. /*           prog.__LogSTDOUT   - string to direct STDOUT into the    */
  357. /*                                logfile                             */
  358. /*           prog.__LogAll      - string to direct STDOUT and STDERR  */
  359. /*                                into the logfile                    */
  360. /*           prog.__LogFileParm - string to inherit the logfile       */
  361. /*                                parameter to a child CMD            */
  362. /*           prog.__Param       - program parameter without the       */
  363. /*                                logfile parameter                   */
  364. /*                                                                    */
  365. /*-returns:  ''                                                       */
  366. /*                                                                    */
  367. I!.__SetLogVars: PROCEDURE expose (exposeList)
  368.   parse var prog.__Param prog.__param "/L:" logFileName " " rest
  369.  
  370.   prog.__param= prog.__Param rest
  371.  
  372.                         /* avoid an error if the drive is not ready   */
  373.   SIGNAL OFF NOTREADY
  374.   if logFileName <> '' then
  375.   do
  376.                         /* check if we can write to the logfile       */
  377.     logStatus = stream( logFileName, 'c', 'OPEN WRITE')
  378.     if logStatus <> 'READY:' then
  379.     do
  380.       prog.__LogFile = 'NUL'
  381.       prog.__LogFileParm = ''
  382.  
  383.       call ShowWarning 'Can not write to the logfile "' || logFileName || ,
  384.                        '", the status of the logfile is "' || ,
  385.                        logStatus || ,
  386.                        '". Now using the NUL device for logging'
  387.     end /* if logStatus <> 'READY' then */
  388.     else
  389.     do
  390.                         /* close the logfile                          */
  391.       call stream logFileName, 'c', 'CLOSE'
  392.  
  393.                         /* get the full name (incl. the path) of the  */
  394.                         /* logfile                                    */
  395.       prog.__LogFile = stream( logFileName, 'c', 'QUERY EXIST' )
  396.  
  397.       prog.__LogFileParm = '/L:' || prog.__LogFile
  398.     end /* else */
  399.   end /* if prog.__LogFile <> '' then */
  400.   else
  401.     prog.__LogFile = 'NUL'
  402.  
  403.   prog.__LogFile = translate( prog.__LogFile )
  404.  
  405.                         /* variable to direct STDOUT of an OS/2       */
  406.                         /* program into the logfile                   */
  407.   prog.__LogSTDOUT = ' 1>>' || prog.__LogFile
  408.  
  409.                         /* variable to direct STDERR of an OS/2       */
  410.                         /* program into the logfile                   */
  411.   prog.__LogSTDERR = ' 2>>' || prog.__LogFile
  412.  
  413.                         /* variable to direct STDOUT and STDERR of    */
  414.                         /* an OS/2 program into the log file          */
  415.       prog.__LogALL = ' 2>>' || prog.__LogFile || ' 1>>&2'
  416.  
  417. RETURN ''
  418.  
  419. /* ------------------------------------------------------------------ */
  420. /*-function: check some environment variables                         */
  421. /*                                                                    */
  422. /*-call:     I!.__CheckEnvVars                                        */
  423. /*                                                                    */
  424. /*-where:    -                                                        */
  425. /*                                                                    */
  426. /*-returns:  ''                                                       */
  427. /*                                                                    */
  428. I!.__CheckEnvVars: PROCEDURE expose (exposeList)
  429.  
  430.                     /* check if we should show the debug information  */
  431.   global.__verbose = value( 'verbose' ,, prog.__env )
  432.  
  433.                     /* check if we should not use colors              */
  434.   testV = translate( value( 'ANSI' ,, prog.__env ) )
  435.   if testV = "OFF" | testV = 0 then
  436.     screen. = ''
  437.  
  438.                     /* check if we should not use sounds              */
  439.   testV = translate( value( 'SOUND' ,, prog.__env ) )
  440.   if testV = "OFF" | testV = 0 then
  441.     prog.__noSound = 1
  442.  
  443. RETURN ''
  444.  
  445. /* ------------------------------------------------------------------ */
  446. /*-function:  convert a file or directory name to OS conventions      */
  447. /*            by adding a leading and trailing quote or double quote  */
  448. /*                                                                    */
  449. /*-call:      convertNameToOS dir_or_file_name                        */
  450. /*                                                                    */
  451. /*-where:     dir_or_file_name = name to convert                      */
  452. /*                                                                    */
  453. /*-returns:   converted file or directory name                        */
  454. /*                                                                    */
  455. ConvertNameToOS: PROCEDURE expose (exposeList)
  456.   parse arg fn
  457.  
  458.   if pos( '"', fn ) = 0 then
  459.     fn = '"' || fn || '"'
  460.   else if pos( "'", fn ) = 0 then
  461.     fn = "'" || fn || "'"
  462.  
  463. RETURN fn
  464.  
  465. /* ------------------------------------------------------------------ */
  466. /*-function: flush the default REXX queue                             */
  467. /*                                                                    */
  468. /*-call:     FlushQueue                                               */
  469. /*                                                                    */
  470. /*-returns:  ''                                                       */
  471. /*                                                                    */
  472. FlushQueue: PROCEDURE expose (exposeList)
  473.   do while( QUEUED() <> 0 )
  474.     pull i
  475.   end /* do while( QUEUED() <> 0 ) */
  476. RETURN ''
  477.  
  478. /* ------------------------------------------------------------------ */
  479. /*-function: include a file if it exists                              */
  480. /*                                                                    */
  481. /*-call:     TryInclude( IncludeFile )                                */
  482. /*                                                                    */
  483. /*-where:    IncludeFile = name of the file to include                */
  484. /*                                                                    */
  485. /*-output:   prog.__rc = 0 - include file executed                    */
  486. /*           else: file not found                                     */
  487. /*                                                                    */
  488. /*-returns:  ''                                                       */
  489. /*                                                                    */
  490. /*-Note:     You do not need the 'call' keyword to use this routine.  */
  491. /*                                                                    */
  492. TryInclude:
  493.   parse arg I!.__TryIncludeFile
  494.  
  495.   prog.__rc = 1
  496.  
  497.   if I!.__TryIncludeFile <> '' then
  498.     if stream( I!.__TryIncludeFile, 'c', 'QUERY EXIST' ) <> '' then
  499.     do
  500.       prog.__rc = 0
  501.       call Include I!.__TryIncludeFile
  502.     end /* if stream( ... */
  503.   drop I!.__TryIncludeFile
  504. RETURN ''
  505.  
  506. /* ------------------------------------------------------------------ */
  507. /*-function: include a file                                           */
  508. /*                                                                    */
  509. /*-call:     Include( IncludeFile )                                   */
  510. /*                                                                    */
  511. /*-where:    IncludeFile = name of the file to include                */
  512. /*                                                                    */
  513. /*-returns:  ''                                                       */
  514. /*                                                                    */
  515. /*-Note:     You do not need the 'call' keyword to use this routine.  */
  516. /*                                                                    */
  517. Include:
  518.   parse upper arg I!.__IncFileName
  519.  
  520.                         /* check if the include file exists           */
  521.   if stream( I!.__IncFileName, 'c', 'QUERY EXIST') = '' then
  522.     call ShowError global.__ErrorExitCode, ,
  523.                    'Can not find the include file "' || ,
  524.                    I!.__IncFileName || '"'
  525.  
  526.                         /* read and interpret the include file        */
  527.   do I!.__IncLineNO = 1 while lines( I!.__IncFileName ) <> 0
  528.     I!.__IncCurLine = ''
  529.                         /* save the absolute position of the start of */
  530.                         /* this line for the error handler            */
  531.     I!.__IncCurLinePos = stream(I!.__IncFileName,'c','SEEK +0')
  532.  
  533.                         /* handle multi line statements               */
  534.     do forever
  535.       I!.__IncCurLine = I!.__IncCurLine ,
  536.                         strip( lineIn( I!.__IncFileName ) )
  537.  
  538.       if right( I!.__IncCurLine,1 ) = ',' then
  539.       do
  540.                         /* statement continues on the next line       */
  541.         if lines( I!.__IncFileName ) = 0 then
  542.           call ShowError global.__ErrorExitCode ,,
  543.             'Unexpected EOF detected while reading the include file "' ||,
  544.             I!.__IncFileName || '"'
  545.         else
  546.           I!.__IncCurLine = substr( I!.__IncCurLine,1, ,
  547.                                     length( I!.__IncCurLine )-1 )
  548.       end /* if right( ... */
  549.       else
  550.         leave
  551.     end /* do forever */
  552.  
  553.     I!.__IncActive = 1
  554.     interpret I!.__IncCurLine
  555.     I!.__IncActive = 0
  556.  
  557.   end /* do I!.__IncLineNO = 1 while lines( I!.__IncFileName ) <> 0 ) */
  558.  
  559.                         /* close the include file!                    */
  560.   call stream I!.__IncFileName 'c' 'CLOSE'
  561.  
  562. RETURN ''
  563.  
  564. /* ------------------------------------------------------------------ */
  565. /*-function: init color variables                                     */
  566. /*                                                                    */
  567. /*-call:     I!.__InitColorVars                                       */
  568. /*                                                                    */
  569. /*-returns:  ''                                                       */
  570. /*                                                                    */
  571. I!.__InitColorVars: PROCEDURE expose (exposeList)
  572.  
  573.   if global.__NeedColors = 1 then
  574.   do
  575.                         /* delete rest of the line                    */
  576.        screen.__DelEOL = '1B'x || '[K'
  577.  
  578.                         /* save the cursor position                   */
  579.       screen.__SavePos = '1B'x || '[s'
  580.  
  581.                         /* restore the cursor position                */
  582.       screen.__RestPos = '1B'x || '[u'
  583.  
  584.                         /* define color attributes                    */
  585.       screen.__AttrOff = '1B'x || '[0;m'
  586.     screen.__Highlight = '1B'x || '[1;m'
  587.        screen.__normal = '1B'x || '[2;m'
  588.         screen.__blink = '1B'x || '[5;m'
  589.        screen.__invers = '1B'x || '[7;m'
  590.     screen.__invisible = '1B'x || '[8;m'
  591.  
  592.                         /* define foreground color variables          */
  593.       screen.__fgBlack = '1B'x || '[30;m'
  594.         screen.__fgRed = '1B'x || '[31;m'
  595.       screen.__fgGreen = '1B'x || '[32;m'
  596.      screen.__fgYellow = '1B'x || '[33;m'
  597.        screen.__fgBlue = '1B'x || '[34;m'
  598.    screen.__fgMagnenta = '1B'x || '[35;m'
  599.        screen.__fgCyan = '1B'x || '[36;m'
  600.       screen.__fgWhite = '1B'x || '[37;m'
  601.  
  602.                         /* define background color variables          */
  603.       screen.__bgBlack = '1B'x || '[40;m'
  604.         screen.__bgRed = '1B'x || '[41;m'
  605.       screen.__bgGreen = '1B'x || '[42;m'
  606.      screen.__bgYellow = '1B'x || '[43;m'
  607.        screen.__bgBlue = '1B'x || '[44;m'
  608.    screen.__bgMagnenta = '1B'x || '[45;m'
  609.        screen.__bgCyan = '1B'x || '[46;m'
  610.       screen.__bgWhite = '1B'x || '[47;m'
  611.  
  612.                         /* define color variables                     */
  613.     screen.__ErrorColor = screen.__AttrOff || screen.__Highlight || ,
  614.                           screen.__FGYellow || screen.__bgRed
  615.    screen.__NormalColor = screen.__AttrOff ||                       ,
  616.                           screen.__fgWhite || screen.__bgBlack
  617.     screen.__DebugColor = screen.__AttrOff || screen.__Highlight || ,
  618.                           screen.__fgBlue || screen.__bgWhite
  619.    screen.__PromptColor = screen.__AttrOff || screen.__Highlight || ,
  620.                           screen.__fgYellow || screen.__bgMagnenta
  621.  
  622. /* +++++++++++++++ DO NOT USE THE FOLLOWING COLORS! +++++++++++++++++ */
  623.    screen.__SignOnColor = screen.__AttrOff || screen.__Highlight || ,
  624.                           screen.__fggreen || screen.__bgBlack
  625.     screen.__PatchColor = screen.__AttrOff || screen.__Highlight || ,
  626.                           screen.__fgcyan || screen.__bgRed
  627. /* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
  628.  
  629.                             /* set the default color                  */
  630.    screen.__CurColor = screen.__NormalColor
  631.  
  632.   end /* if global.__NeedColors = 1 then */
  633.   else
  634.   do
  635.                         /* init all color variables with ''           */
  636.     screen. = ''
  637.   end /* else */
  638.  
  639. RETURN ''
  640.  
  641. /* ------------------------------------------------------------------ */
  642. /*-function: init the stem prog.                                      */
  643. /*                                                                    */
  644. /*-call:     I!.__InitProgStem                                        */
  645. /*                                                                    */
  646. /*-returns:  ''                                                       */
  647. /*                                                                    */
  648. /*-Note:     DO NOT ADD ANY CODE TO THIS ROUTINE!                     */
  649. /*                                                                    */
  650. I!.__InitProgStem: PROCEDURE expose (exposeList)
  651.                         /* get drive, path and name of this program   */
  652.   parse upper source . . prog.__FullName
  653.         prog.__Drive = filespec( "drive", prog.__FullName )
  654.          prog.__Path = filespec( "path",  prog.__FullName )
  655.          prog.__Name = filespec( "name",  prog.__FullName )
  656.           prog.__Env = 'OS2ENVIRONMENT'
  657.        prog.__CurDir = translate( directory() )
  658.                         /* version of TEMPLATE.CMD                    */
  659.       prog.__Version = 'V2.52'
  660.      prog.__ExitCode = 0
  661.     prog.__UserAbort = 1        /* allow user aborts                  */
  662.  prog.__ExitRoutines = ''       /* list of routines to execute at     */
  663.                                 /* program end                        */
  664.   prog.__ScreenCols = 80
  665.   prog.__ScreenRows = 25
  666.  
  667.   if I!.__CallUserProc( 0, 'SysTextScreenSize' ) = 1 then
  668.     if symbol( 'I!.__UserProcRC' ) = 'VAR' then
  669.       parse var I!.__UserProcRC prog.__ScreenRows prog.__ScreenCols
  670.  
  671. RETURN ''
  672.  
  673. /* ------------------------------------------------------------------ */
  674. /*-function: init the variables for CID programs (only if the value   */
  675. /*           of the variable global.__NeedCID is 1)                   */
  676. /*                                                                    */
  677. /*-call:     I!.__InitCIDVars                                         */
  678. /*                                                                    */
  679. /*-returns:  ''                                                       */
  680. /*                                                                    */
  681. /*-Note:     DO NOT ADD ANY CODE TO THIS ROUTINE!                     */
  682. /*           Returncodes as defined by LCU 2.0                        */
  683. /*                                                                    */
  684. I!.__InitCIDVars: PROCEDURE expose (exposeList) exposeList CIDRC.
  685.  
  686.   if global.__NeedCID = 1 then
  687.   do
  688.                         /* define return codes for CID programs       */
  689.     CIDRC.__successful_program_termination  = C2D('0000'x, 2);
  690.     CIDRC.__successful_log_warning_message  = C2D('0004'x, 2);
  691.     CIDRC.__successful_log_error_Message    = C2D('0008'x, 2);
  692.     CIDRC.__successful_log_severe_error     = C2D('0012'x, 2);
  693.  
  694.     CIDRC.__data_resource_not_found         = C2D('0800'x, 2);
  695.     CIDRC.__data_resource_already_in_use    = C2D('0804'x, 2);
  696.     CIDRC.__data_resource_Noauthorization   = C2D('0808'x, 2);
  697.     CIDRC.__data_path_not_found             = C2D('0812'x, 2);
  698.     CIDRC.__product_not_configured          = C2D('0816'x, 2);
  699.  
  700.     CIDRC.__storage_medium_exception        = C2D('1200'x, 2);
  701.     CIDRC.__device_Not_Ready                = C2D('1204'x, 2);
  702.     CIDRC.__not_enough_diskspace            = C2D('1208'x, 2);
  703.  
  704.     CIDRC.__incorrect_program_invocation    = C2D('1600'x, 2);
  705.     CIDRC.__unexpected_condition            = C2D('1604'x, 2);
  706.  
  707.     CIDRC.__successfull_reboot              = C2D('FE00'x, 2);
  708.     CIDRC.__successfull_reboot_with_warning = C2D('FE04'x, 2);
  709.     CIDRC.__successfull_reboot_with_errmsg  = C2D('FE08'x, 2);
  710.     CIDRC.__successfull_reboot_with_server_errMsg = C2D('FE12'x, 2);
  711.  
  712.  
  713.                         /* xx = next state of the program             */
  714. /*    CIDRC.__successfull_reboot_with_callback = C2D('FFxx'x, 2);     */
  715.  
  716.                         /* define exit code values                    */
  717.     global.__ErrorExitCode = CIDRC.__unexpected_condition
  718.        global.__OKExitCode = CIDRC.__successful_program_termination
  719.  
  720.                         /* add the stem CIDRC. to the exposeList      */
  721.     exposeList = exposeList || ' CIDRC. '
  722.   end /* if global.__NeedCID = 1 then */
  723.  
  724. RETURN ''
  725.  
  726. /* ------------------------------------------------------------------ */
  727. /*-function: init program vars                                        */
  728. /*                                                                    */
  729. /*-call:     I!.__InitVars                                            */
  730. /*                                                                    */
  731. /*-returns:  ''                                                       */
  732. /*                                                                    */
  733. /*-Note:     DO NOT ADD ANY CODE TO THIS ROUTINE!                     */
  734. /*                                                                    */
  735. I!.__InitVars:
  736.  
  737.                         /* define exit code values                    */
  738.   global.__ErrorExitCode = 255
  739.      global.__OKExitCode = 0
  740.  
  741.                         /* define the stem prog.                      */
  742.   call I!.__InitProgStem
  743.  
  744.                         /* define the color variables                 */
  745.   call I!.__InitColorVars
  746.  
  747.                         /* define the variables for CID programs      */
  748.   call I!.__InitCIDVars
  749.  
  750.                         /* check some environment variables           */
  751.   call I!.__CheckEnvVars
  752.  
  753.                         /* check if there is a logfile parameter      */
  754.   call I!.__SetLogVars
  755.  
  756.                         /* init the program exit code                 */
  757.   prog.__ExitCode = global.__OKExitCode
  758.  
  759. RETURN ''
  760.  
  761. /***        End of Part 2 of the source code of TEMPLATE.CMD        ***/
  762.  
  763. /***       Start of Part 3 of the source code of TEMPLATE.CMD       ***/
  764.  
  765. /* ------------------------------------------------------------------ */
  766. /*-function:  load a dll                                              */
  767. /*                                                                    */
  768. /*-call:                                                              */
  769. /*   thisRC = LoadDll( registerFunction, dllName, entryPoint,         */
  770. /*                     ,{deRegisterFunction},{checkFunction}          */
  771. /*                     ,{IgnoreRxFuncAddRC},{RegisterErrorRC}         */
  772. /*                     ,{errorAction}                                 */
  773. /*                                                                    */
  774. /*-where:                                                             */
  775. /*     registerFunction = name of the dll init function               */
  776. /*                        (e.g. "SysLoadFuncs")                       */
  777. /*              dllName = name of the dll                             */
  778. /*                        (e.g. "REXXUTIL")                           */
  779. /*           entryPoint = entryPoint for the dll init function        */
  780. /*                        (e.g. "SysLoadFuncs")                       */
  781. /*   deRegisterFunction = name of the dll exit function               */
  782. /*                        (e.g. "SysDropFuncs")                       */
  783. /*                        If this parameter is entered, the           */
  784. /*                        deRegisterFunction is automaticly called    */
  785. /*                        at program end if the loading of the dll    */
  786. /*                        was successfull.                            */
  787. /*        checkFunction = function which must be loaded if the dll is */
  788. /*                        loaded (def.: none -> always load the dll)  */
  789. /*                        Note:                                       */
  790. /*                        Do not use the registerFunction for this    */
  791. /*                        parameter! A good candidate for this        */
  792. /*                        parameter is the deRegisterFunction.        */
  793. /*    IgnoreRxFuncAddRC = 1: ignore the rc from rxFuncAdd             */
  794. /*                        0: do not ignore the rc from rxFuncAdd      */
  795. /*                        (def.: 0)                                   */
  796. /*       RegisterErroRC = returncode of the dll init function         */
  797. /*                        indicating a load error                     */
  798. /*                        (def. none, -> ignore the returncode of the */
  799. /*                         dll init function)                         */
  800. /*           actionCode = 1: abort program if loading failed          */
  801. /*                        0: do not abort program if loading failed   */
  802. /*                        (def.: 1)                                   */
  803. /*                                                                    */
  804. /*-returns:                                                           */
  805. /*   0 - loading failed                                               */
  806. /*   1 - dll loaded                                                   */
  807. /*   2 - dll already loaded                                           */
  808. /*                                                                    */
  809. /*-Note:                                                              */
  810. /*   See the routine MAIN for some examples for using LoadDLL.        */
  811. /*   LoadDLL can only handle dlls with an init function to register   */
  812. /*   the further routines in the dll (like the function SysLoadFuncs  */
  813. /*   in the dll REXXUTIL).                                            */
  814. /*                                                                    */
  815. LoadDll:  PROCEDURE expose (exposeList)
  816.   parse arg registerFunction , ,
  817.             dllName , ,
  818.             entryPoint , ,
  819.             deRegisterFunction , ,
  820.             checkFunction , ,
  821.             ignoreRXFuncAddRC, ,
  822.             registerErrorRC, ,
  823.             errorAction
  824.  
  825.                         /* check the neccessary parameters            */
  826.   if entryPoint = '' | dllName = '' | registerFunction = '' then
  827.     call ShowError global.__ErrorExitCode, 'Invalid call to LOADDLL'
  828.  
  829.   if ignoreRXFuncAddRC = '' then
  830.     ignoreRXFuncAddRc = 0
  831.  
  832.   if errorAction = '' then
  833.     errorAction = 1
  834.  
  835.   I!.__LoadDLLRc = 0
  836.                         /* if the 'checkFunction' is missing, we      */
  837.                         /* assume that the dll is not loaded          */
  838.   if ( CheckFunction <> '' ) then
  839.   do
  840.                         /* check if the dll is loaded                 */
  841.     dllNotLoaded = rxFuncQuery( CheckFunction )
  842.   end /* if checkFunction <> '' then */
  843.   else
  844.     dllNotLoaded = 1
  845.  
  846.   if dllNotLoaded then
  847.   do
  848.                         /* load the dll and register the init         */
  849.                         /* function of the dll                        */
  850.     rxFuncAddRC = rxFuncAdd( RegisterFunction, dllName, entryPoint )
  851.  
  852.     if \ rxFuncAddRC | ignoreRxFuncAddRC then
  853.     do
  854.  
  855.       if I!.__CallUserProc( 0, RegisterFunction ) = 0 then
  856.         I!.__DllInitRC = 'ERROR'
  857.       else
  858.         I!.__DllInitRC = 0
  859.  
  860.       if ( registerErrorRC <> '' & I!.__DLLInitRC = registerErrorRC ) | ,
  861.          ( I!.__DllInitRC = 'ERROR' ) then
  862.       do
  863.         nop
  864.       end /* if ( registerErrorRC <> '' & ... */
  865.       else
  866.       do
  867.                         /* add the dll deregister function to the     */
  868.                         /* program exit routine list                  */
  869.         if DeRegisterFunction <> '' then
  870.           if \ rxFuncQuery( DeRegisterFunction ) then
  871.             prog.__ExitRoutines = prog.__ExitRoutines || ' ' || ,
  872.                                   DeRegisterFunction
  873.  
  874.         I!.__LoadDLLRc = 1
  875.       end /* else */
  876.     end /* if \ rxFuncAddRC | ignoreRxFuncAddRC then */
  877.   end /* if dllNotLoaded then */
  878.   else
  879.   do
  880.                         /* dll is already loaded                      */
  881.     I!.__LoadDLLRc = 2
  882.  
  883.   end /* else */
  884.  
  885.   if errorAction = 1 & I!.__LoadDLLRC = 0 then
  886.     call ShowError global.__ErrorExitCode, 'Can not load the dll "' || ,
  887.                                            dllName || '"'
  888.  
  889. RETURN I!.__LoadDLLRc
  890.  
  891. /* ------------------------------------------------------------------ */
  892. /*-function: show a string with word wrapping                         */
  893. /*                                                                    */
  894. /*-call:     showString Prefix, thisString                            */
  895. /*                                                                    */
  896. /*-where:                                                             */
  897. /*           Prefix = prefix for the first line (e.g. "*-*" or "#" to */
  898. /*                    use # leading blanks, # = 1 ... n )             */
  899. /*           thisString - string to print                             */
  900. /*                                                                    */
  901. /*-returns:  ''                                                       */
  902. /*                                                                    */
  903. ShowString: PROCEDURE EXPOSE (exposeList)
  904.   parse arg Prefix, StringToShow
  905.  
  906.   maxLineLength = prog.__ScreenCols-4
  907.  
  908.   if datatype( prefix, 'W' ) = 1 then
  909.     prefix = copies( ' ' , prefix )
  910.  
  911.   maxWordLength = maxLineLength - length( prefix )
  912.  
  913.   thisRC = 0
  914.   SE.thisString = ''
  915.  
  916.   do i = 1 to words( StringToShow)
  917.     printString = 0
  918.  
  919.     SE.thisString = SE.thisString || word( StringToShow, i ) || ' '
  920.  
  921.     if length( SE.thisString ) + ,
  922.        length( word( StringToShow, i+1 ) ) > maxLineLength then
  923.       printString = 1
  924.  
  925.     if printString = 1 | i = words( StringToShow ) then
  926.     do
  927.       if length( prefix || SE.ThisString ) > prog.__ScreenCols then
  928.       do
  929.         do until SE.thisString = ''
  930.           parse var SE.thisString SE.thisString1 =(maxWordLength) ,
  931.                                   SE.thisString
  932.           call log left( prefix || SE.thisString1, prog.__ScreenCols )
  933.           prefix = copies( ' ', length( prefix ) )
  934.         end /* do until SE.thisString = '' */
  935.       end /* if length( ... */
  936.       else
  937.         call Log left( prefix || SE.thisString, prog.__ScreenCols )
  938.  
  939.       SE.thisString = ''
  940.       prefix = copies( ' ', length( prefix ) )
  941.     end /* if length( ... */
  942.  
  943.   end /* do i = 1 to words( StringToShow */
  944.  
  945. RETURN ''
  946.  
  947. /* ------------------------------------------------------------------ */
  948. /*-function: show a warning message                                   */
  949. /*                                                                    */
  950. /*-call:     showWarning message                                      */
  951. /*                                                                    */
  952. /*-where:    warningMessage - warning Message                         */
  953. /*                                                                    */
  954. /*-returns:  ''                                                       */
  955. /*                                                                    */
  956. ShowWarning: PROCEDURE expose (exposeList)
  957.   parse arg warningMessage
  958.  
  959.   screen.__CurColor = screen.__ErrorColor
  960.  
  961.   warningMessage = warningMessage || '!'
  962.  
  963.   call Log ''
  964.   call I!.__LogSeparator
  965.   call ShowString ' Warning: ', warningMessage
  966.   call I!.__LogSeparator
  967.  
  968.   screen.__CurColor = screen.__NormalColor
  969.   call Log ''
  970.  
  971. RETURN ''
  972.  
  973. /* ------------------------------------------------------------------ */
  974. /*-function: show an error message and end the program                */
  975. /*                                                                    */
  976. /*-call:     ShowError exitCode, errorMessage                         */
  977. /*                                                                    */
  978. /*-where:    ExitCode - no of the error (= program exit code)         */
  979. /*           errorMessage - error Message                             */
  980. /*                                                                    */
  981. /*-returns:  nothing                                                  */
  982. /*                                                                    */
  983. /*-Note:     THIS ROUTINE WILL NOT COME BACK!!!                       */
  984. /*                                                                    */
  985. ShowError: PROCEDURE expose (exposeList)
  986.   parse arg prog.__ExitCode, prog.__errorMessage
  987.  
  988.   prog.__I!QuietMode = prog.__QuietMode
  989.                         /* turn quiet mode off                        */
  990.   prog.__QuietMode = ''
  991.  
  992.   screen.__CurColor = screen.__ErrorColor
  993.  
  994.   prog.__errorMessage = prog.__errorMessage || '!'
  995.  
  996.   call Log ''
  997.   call I!.__LogSeparator
  998.   call Log left(' Error ' || prog.__ExitCode  || ' detected! ' || ,
  999.       'The error message is: ',prog.__ScreenCols )
  1000.   call ShowString 1, prog.__errorMessage
  1001.  
  1002.   call I!.__LogSeparator
  1003.   call Log ''
  1004.                         /* restore quiet mode status                  */
  1005.   prog.__QuietMode = prog.__I!QuietMode
  1006.  
  1007.   if prog.__NoSound <> 1 then
  1008.   do
  1009.     call beep 537,300
  1010.     call beep 237,300
  1011.     call beep 537,300
  1012.   end /* if prog.__NoSound <> 1 then */
  1013.  
  1014. SIGNAL I!.__ProgramEnd
  1015.  
  1016. RETURN
  1017.  
  1018. /* ------------------------------------------------------------------ */
  1019. /*-function: log a debug message and clear the rest of the line       */
  1020. /*                                                                    */
  1021. /*-call:     logDebugMsg message                                      */
  1022. /*                                                                    */
  1023. /*-where:    message - message to show                                */
  1024. /*                                                                    */
  1025. /*-returns:  ''                                                       */
  1026. /*                                                                    */
  1027. /*-Note:     You do not need the 'call' keyword to use this routine.  */
  1028. /*                                                                    */
  1029. LogDebugMsg: PROCEDURE expose (exposeList)
  1030.   if global.__verbose <> '' then
  1031.   do
  1032.     parse arg debugMessage
  1033.     screen.__CurColor = screen.__DebugColor
  1034.     call Log '+++' debugMessage
  1035.     screen.__CurColor = screen.__NormalColor
  1036.   end /* if global.__verbose <> '' then */
  1037. RETURN ''
  1038.  
  1039. /* ------------------------------------------------------------------ */
  1040. /*-function: write a separator line to the screen and to the logfile  */
  1041. /*                                                                    */
  1042. /*-call:     I!.__LogSeparator                                        */
  1043. /*                                                                    */
  1044. /*-returns:  ''                                                       */
  1045. /*                                                                    */
  1046. I!.__LogSeparator: PROCEDURE expose (exposeList)
  1047.   call Log ' ' || left('-', prog.__ScreenCols-2, '-' ) || ' '
  1048. RETURN
  1049.  
  1050. /* ------------------------------------------------------------------ */
  1051. /*-function: log a message and clear the rest of the line             */
  1052. /*                                                                    */
  1053. /*-call:     log message                                              */
  1054. /*                                                                    */
  1055. /*-where:    message - message to show                                */
  1056. /*                                                                    */
  1057. /*-returns:  ''                                                       */
  1058. /*                                                                    */
  1059. /*-Note:     You do not need the 'call' keyword to use this routine.  */
  1060. /*                                                                    */
  1061. Log: PROCEDURE expose (exposeList)
  1062.   parse arg message
  1063.  
  1064.   logMessage = message
  1065.   do i = 1 to words( prog.__LogExcludeWords )
  1066.     curWord = word( prog.__LogExcludeWords, i )
  1067.     curLength = length( curWord )
  1068.     do until j = 0
  1069.       j = Pos( curWord, logMessage )
  1070.       if j <> 0 then
  1071.         logMessage = delstr( logMessage, j, curLength )
  1072.     end /* do until j = 0 */
  1073.   end /* do i = 1 to words( prog.__LogExcludeWords ) */
  1074.  
  1075.   if prog.__QuietMode = '' then
  1076.   do
  1077.     if length( logMessage) = prog.__ScreenCols  then
  1078.       call charout prog.__STDOUT, screen.__CurColor || ,
  1079.                                   message || screen.__AttrOff
  1080.     else
  1081.       call lineOut prog.__STDOUT, screen.__CurColor || ,
  1082.                                   message || screen.__AttrOff ||,
  1083.                                   screen.__DelEOL
  1084.   end /* if prog.__Quietmode = '' then */
  1085.  
  1086.   if symbol( 'prog.__LogFile' ) = 'VAR' then                 /* v2.52 */
  1087.     if prog.__LogFile <> '' then
  1088.     do
  1089.       call lineout prog.__LogFile, logMessage
  1090.  
  1091.                                 /* close the logfile                  */
  1092.       rc = stream( prog.__LogFile, 'c', 'CLOSE')
  1093.     end /* if prog.__LogFile <> '' then */
  1094.  
  1095. RETURN ''
  1096.  
  1097. /* ------------------------------------------------------------------ */
  1098. /*-function: check if there is a patched version of this program      */
  1099. /*                                                                    */
  1100. /*-call:     I!.__CheckPatch                                          */
  1101. /*                                                                    */
  1102. /*-returns:  ''                                                       */
  1103. /*                                                                    */
  1104. /*-Note:     I!.__RealParameter must contain the parameters for       */
  1105. /*           this program.                                            */
  1106. /*           The variables prog.__Path and prog.__Name must be set!   */
  1107. /*           This procedure ends the program with an EXIT command!    */
  1108. /*                                                                    */
  1109. I!.__CheckPatch: PROCEDURE expose (exposeList)
  1110.  
  1111.                         /* get the drive with patch cmd files         */
  1112.   patchDrive = translate( value( 'patchDrive',, prog.__Env) )
  1113.  
  1114.   if patchDrive <> '' & patchDrive <> prog.__Drive then
  1115.   do
  1116.  
  1117.     patchedVersion = patchDrive || prog.__Path || prog.__Name
  1118.  
  1119.                         /* check if a patched program version exists  */
  1120.  
  1121.     if stream( patchedVersion, 'c', 'QUERY EXISTS') <> "" then
  1122.     do
  1123.       cmdLine= patchedVersion || " " || I!.__Realparameter
  1124.  
  1125.       screen.__CurColor = screen.__PatchColor
  1126.       call Log left( ' Calling patched version ' patchedVersion || ,
  1127.                ' ...', prog.__ScreenCols )
  1128.       screen.__CurColor = screen.__AttrOff
  1129.       call I!.__LogSeparator
  1130.  
  1131.       'cmd /c ' cmdLine
  1132.  
  1133.       screen.__CurColor = screen.__AttrOff
  1134.       call I!.__LogSeparator
  1135.       screen.__CurColor = screen.__PatchColor
  1136.       call Log left( ' ... the patched version endet with RC = ' || ,
  1137.            rc, prog.__ScreenCols )
  1138.  
  1139.       exit rc
  1140.     end /* if stream( ... */
  1141.   end /* if patchDrive <> '' */
  1142. RETURN ''
  1143.  
  1144. /* ------------------------------------------------------------------ */
  1145. /*-function: error handler for unexpected errors                      */
  1146. /*                                                                    */
  1147. /*-call:     DO NOT CALL THIS ROUTINE BY HAND!!!                      */
  1148. /*                                                                    */
  1149. /*-returns:  nothing                                                  */
  1150. /*                                                                    */
  1151. /*-input:    I!.__IncActive:                                          */
  1152. /*             if 1 the error occured while executing an include file */
  1153. /*             statement. In this case the following variables are    */
  1154. /*             also used (Note that this variables are automaticly    */
  1155. /*             set by the routine INCLUDE()):                         */
  1156. /*               I!.__IncLineNo                                       */
  1157. /*                 Line no. of the include file                       */
  1158. /*               I!.__IncFileName:                                    */
  1159. /*                 Name of the include file                           */
  1160. /*               I!.__IncCurLinePos:                                  */
  1161. /*                 Fileposition of the first char of the line causing */
  1162. /*                 the error                                          */
  1163. /*                                                                    */
  1164. /*-Note:     THIS FUNCTION ABORTS THE PROGRAM WITH A JUMP TO THE      */
  1165. /*           LABEL I!.__PROGRAMEND!!!                                 */
  1166. /*                                                                    */
  1167. I!.__ErrorAbort:
  1168.                         /* check if the error occured in the error    */
  1169.                         /* handler                                    */
  1170.   if I!.__errorLineNo = sigl then
  1171.   do
  1172.     call beep 637,300; call beep 437,300; call beep 637,300
  1173.  
  1174.     call charout 'STDERR:',,                                 /* v2.52 */
  1175.                                                             '0D0A'x  ,
  1176.        'Fatal Error: Error in the error handler detected!'  '0D0A'x  ,
  1177.                                                             '0D0A'x  ,
  1178.        'Linenumber:       ' || sigl ||                      '0D0A'x  ,
  1179.        'Errorname:        ' || condition('C')               '0D0A'x  ,
  1180.        'Errordescription: ' || condition('D')               '0D0A'x  ,
  1181.                                                             '0D0A'x  ,
  1182.        'The program exit routines were not called!'         '0D0A'x  ,
  1183.        'Check if "(EXPOSELIST)" is included in the ' || ,
  1184.        'expose lists of all procedures!'                    '0D0A'x
  1185.  
  1186.     call beep 637,300 ; call beep 437,300 ; call beep 637,300
  1187.     exit 255
  1188.  
  1189.   end /* if I!.__errorLineNo = sigl then */
  1190.  
  1191.                         /* get the number of the line causing the     */
  1192.                         /* error                                      */
  1193.   I!.__errorLineNo = sigl
  1194.  
  1195.                         /* get the name of this error                 */
  1196.   I!.__ErrorName = condition('C')
  1197.  
  1198.                         /* get further information for this error     */
  1199.                         /* if available                               */
  1200.   I!.__ErrorCondition = condition('D')
  1201.   if I!.__ErrorCondition <> '' then
  1202.     I!.__ErrorCondition = ' (Desc.: "' || I!.__ErrorCondition || '")'
  1203.  
  1204.   if datatype( prog.__ScreenCols, 'W' ) <> 1 then
  1205.     prog.__ScreenCols = 80
  1206.  
  1207.  
  1208.   if SYMBOL( 'prog.__Name' ) <> 'VAR' | value( 'prog.__Name' ) = '' then
  1209.     if I!.__errorLineNO < I!.__FirstUserCodeLine then
  1210.       I!.__pName = '**Runtimte**'
  1211.     else
  1212.       I!.__pName = '***???***'
  1213.   else
  1214.     i!.__pName = prog.__Name
  1215.  
  1216.                         /* reInstall the error handler                */
  1217.                                                              /* v2.52 */
  1218.   INTERPRET  'SIGNAL ON ' value(condition('C')) ' NAME I!.__ErrorAbort'
  1219.  
  1220.                         /* check, if we should ignore the error       */
  1221.   if value( 'sigl' ) = value( 'I!.__InterpretCMDLine' ) then
  1222.     SIGNAL I!.__CallUserProc2
  1223.  
  1224.   screen.__CurColor = screen.__ErrorColor
  1225.  
  1226.   prog.__I!QuietMode = prog.__QuietMode
  1227.                         /* turn quiet mode off                        */
  1228.   prog.__QuietMode = ''
  1229.  
  1230.                         /* init variables for printing the line       */
  1231.                         /* causing the error to the screen            */
  1232.   I!.__ThisSRCLine = ''
  1233.   I!.__ThisPrefix = ' *-* '
  1234.  
  1235.   call Log ''
  1236.   call I!.__LogSeparator
  1237.   call ShowString ' ' || I!.__pName || ' - ', I!.__ErrorName || ,
  1238.                   I!.__ErrorCondition || ' error detected!'
  1239.  
  1240.                         /* check, if the RC is meaningfull for this   */
  1241.                         /* error                                      */
  1242.   if pos( I!.__ErrorName, 'ERROR FAILURE SYNTAX' ) <> 0 then
  1243.   do
  1244.     if datatype(rc, "W") = 1 then
  1245.       if I!.__ErrorName = 'SYNTAX' then
  1246.          if rc > 0 & rc < 100 then
  1247.             call Log left( ' The error code is ' || rc || ,
  1248.                            ', the REXX error message is: ' || ,
  1249.                            errorText( rc ), ,
  1250.                            prog.__ScreenCols )
  1251.          else
  1252.            call log left( ' The error code ' || rc || ,
  1253.                           ', this error code is unknown.',,
  1254.                           prog.__ScreenCols )
  1255.       else
  1256.         call Log left( ' The RC is ' || rc || '.', prog.__ScreenCols )
  1257.   end /* if pos( ... */
  1258.  
  1259.   if value( 'I!.__IncActive' ) = 1 then
  1260.   do
  1261.                 /* error occured while interpreting an include file   */
  1262.     call ShowString 1, 'The error occured while executing the line ' || ,
  1263.                        I!.__IncLineNo || ' of the include file "' || ,
  1264.                        I!.__IncFileName || '".'
  1265.  
  1266.                         /* reset the file pointer of the include file */
  1267.                         /* to the start of the line causing the error */
  1268.     dummy = stream( I!.__IncFileName, 'c', 'SEEK =' || ,
  1269.                                                I!.__IncCurLinePos )
  1270.  
  1271.     I!.__SrcAvailable = stream( I!.__IncFileName, ,
  1272.                                    'c', 'QUERY EXIST' ) <> ''
  1273.   end
  1274.   else
  1275.   do
  1276.     call ShowString 1, 'The error occured in line ' ||,
  1277.                        I!.__errorLineNo || '.'
  1278.  
  1279.     I!.__thisLineNo = I!.__errorLineNo
  1280.  
  1281.                 /* error occured in this file                         */
  1282.                 /* check if the sourcecode is available               */
  1283.     SIGNAL ON SYNTAX   NAME I!.__NoSourceCode
  1284.     I!.__inMacroSpace = 1
  1285.     I!.__SrcAvailable = 0
  1286.     if sourceLine( I!.__errorLineNo ) <> '' then
  1287.       I!.__SrcAvailable = 1
  1288.  
  1289.     SIGNAL ON SYNTAX NAME I!.__ErrorAbort
  1290.     I!.__inMacroSpace = 0
  1291.  
  1292.   end /* else */
  1293.  
  1294.                         /* print the statement causing the error to   */
  1295.                         /* the screen                                 */
  1296.   if I!.__SrcAvailable = 1 then
  1297.   do
  1298.     call Log left( " The line reads: ", prog.__ScreenCols )
  1299.     I!.__InterpretVar = 0
  1300.  
  1301.                 /* read the line causing the error                    */
  1302.     call I!.__GetSourceLine
  1303.  
  1304.     I!.__FirstToken = strip(word( I!.__ThisSRCLine,1))
  1305.     if translate( I!.__FirstToken ) = 'INTERPRET' then
  1306.     do
  1307.       parse var I!.__ThisSRCLine (I!.__FirstToken) ,
  1308.                 I!.__interpretValue
  1309.       I!.__InterpretVar = 1
  1310.     end /* if I!.__thisLineNo = I!.__errorLineNo */
  1311.  
  1312.                         /* handle multi line statements               */
  1313.     do forever
  1314.       call ShowString I!.__ThisPrefix, I!.__ThisSRCLine
  1315.  
  1316.       if right( strip( I!.__ThisSRCLine),1 ) <> ',' then
  1317.         leave
  1318.  
  1319.       I!.__ThisPrefix = 5
  1320.  
  1321.       call I!.__GetSourceLine
  1322.  
  1323.     end /* do forever */
  1324.  
  1325.     if I!.__InterpretVar = 1 then
  1326.     do
  1327.       I!.__interpretValue = strip( word(I!.__interpretValue,1) )
  1328.  
  1329.       if symbol( I!.__interpretValue ) = 'VAR' then
  1330.       do
  1331.         call Log left( '', prog.__ScreenCols )
  1332.         call Log left( ' The value of "' || I!.__interpretValue || ,
  1333.                        '" is:', prog.__ScreenCols )
  1334.         call ShowString ' >V> ', value( I!.__interpretValue )
  1335.       end /* if symbol( I!.__interpretValue ) = 'VAR' then */
  1336.  
  1337.     end /* if I!.__InterpretVar = 1 */
  1338.  
  1339.   end /* if I!.__SrcAvailable = 1 then do */
  1340.   else
  1341.     call Log left( ' The sourcecode for this line is not available',,
  1342.                    prog.__ScreenCols )
  1343.  
  1344. I!.__NoSourceCode:
  1345.   SIGNAL ON SYNTAX NAME I!.__ErrorAbort
  1346.  
  1347.   if I!.__inMacroSpace = 1 then
  1348.   do
  1349.     parse source . . I!.__thisProgName
  1350.  
  1351.     if fileSpec( 'drive', I!.__thisProgName ) = '' then
  1352.       call ShowString 1, ' The sourcecode for this line is not' || ,
  1353.                          ' available because the program is in' || ,
  1354.                          ' the macro space.'
  1355.     else
  1356.       call ShowString 1, ' The sourcecode for this line is not' || ,
  1357.                          ' available because the program is unreadable.'
  1358.  
  1359.   end /* if I!.__inMacroSpace = 1 then */
  1360.  
  1361.   call I!.__LogSeparator
  1362.   call Log ''
  1363.  
  1364.   prog.__ExitCode = global.__ErrorExitCode
  1365.  
  1366.   if prog.__NoSound <> 1 then
  1367.   do
  1368.     call beep 137,300;  call beep 337,300;  call beep 137,300
  1369.   end /* if prog.__NoSound <> 1 then */
  1370.  
  1371.   if global.__verbose = 'DEBUG' then
  1372.   do
  1373.                         /* enter interactive debug mode               */
  1374.     trace ?a
  1375.     nop
  1376.   end /* if global.__verbose = 'DEBUG' then */
  1377.  
  1378.                         /* restore quiet mode status                  */
  1379.   prog.__QuietMode = prog.__I!QuietMode
  1380.  
  1381. SIGNAL I!.__programEnd
  1382.  
  1383. /* ------------------------------------------------------------------ */
  1384. /*-function: get the sourceline causing an error (subroutine of       */
  1385. /*           I!.__ErrorAbort)                                         */
  1386. /*                                                                    */
  1387. /*-call:     DO NOT CALL THIS IN YOUR CODE!!!                         */
  1388. /*                                                                    */
  1389. /*-returns:  ''                                                       */
  1390. /*                                                                    */
  1391. /*-Note:     -                                                        */
  1392. /*                                                                    */
  1393. I!.__GetSourceLine:
  1394.   if I!.__IncActive = 1 then
  1395.     I!.__ThisSRCLine = lineIn( I!.__IncFileName )
  1396.   else
  1397.   do
  1398.     I!.__ThisSRCLine = sourceLine( I!.__ThisLineNo )
  1399.     I!.__ThisLineNo = I!.__ThisLineNo + 1
  1400.   end /* else */
  1401. RETURN ''
  1402.  
  1403. /* ------------------------------------------------------------------ */
  1404. /*-function: error handler for user breaks                            */
  1405. /*                                                                    */
  1406. /*-call:     DO NOT CALL THIS ROUTINE BY HAND!!!                      */
  1407. /*                                                                    */
  1408. /*-returns:  nothing                                                  */
  1409. /*                                                                    */
  1410. /*-Note:     THIS FUNCTION ABORTS THE PROGRAM WITH A JUMP TO THE      */
  1411. /*           LABEL I!.__PROGRAMEND IF prog.__UserAbort IS NOT 0!!!    */
  1412. /*                                                                    */
  1413. /*           In exit routines you may test if the variable            */
  1414. /*           prog.__ExitCode is 254 to check if the program           */
  1415. /*           was aborted by the user.                                 */
  1416. /*                                                                    */
  1417. I!.__UserAbort:
  1418.                         /* reinstall the error handler                */
  1419.  
  1420.   CALL ON HALT        NAME I!.__UserAbort
  1421.  
  1422.                         /* check if user aborts are allowed           */
  1423.   if prog.__UserAbort = 0 then
  1424.     RETURN              /* CTRL-BREAK not allowed                     */
  1425.  
  1426.   prog.__I!QuietMode = prog.__QuietMode
  1427.  
  1428.                         /* turn quiet mode off                        */
  1429.   prog.__QuietMode = ''
  1430.  
  1431.   call Log ''
  1432.  
  1433.   screen.__CurColor = screen.__ErrorColor
  1434.   call I!.__LogSeparator
  1435.   call Log left( ' Program aborted by the user', prog.__ScreenCols )
  1436.   call I!.__LogSeparator
  1437.   screen.__CurColor = screen.__NormalColor
  1438.  
  1439.   prog.__ExitCode = 254
  1440.  
  1441.                         /* restore quiet mode status                  */
  1442.   prog.__QuietMode = prog.__I!QuietMode
  1443.  
  1444. SIGNAL I!.__ProgramEnd
  1445.  
  1446. /* ------------------------------------------------------------------ */
  1447. /*-function: get the no. of the first line with the user code         */
  1448. /*                                                                    */
  1449. /*-call:     DO NOT CALL THIS ROUTINE BY HAND!!!                      */
  1450. /*                                                                    */
  1451. /*-returns:  nothing                                                  */
  1452. /*                                                                    */
  1453. /*                                                                    */
  1454. I!.__GetUserCode:
  1455. /*** DO NOT CHANGE, ADD OR DELETE ONE OF THE FOLLOWING FOUR LINES!! ***/
  1456.   SIGNAL I!.__GetUserCode1
  1457. I!.__GetUserCode1:
  1458.   I!.__FirstUserCodeLine = sigl + 4
  1459. /*** DO NOT CHANGE, ADD OR DELETE ONE OF THE PRECEEDING FOUR LINES! ***/
  1460. RETURN
  1461.  
  1462. /********************** End of Runtime Routines ***********************/
  1463. /**********************************************************************/
  1464.  
  1465. /***        End of Part 3 of the source code of TEMPLATE.CMD        ***/
  1466.  
  1467.  
  1468. /***       Start of Part 4 of the source code of TEMPLATE.CMD       ***/
  1469.  
  1470. /* ------------------------------------------------------------------ */
  1471. /*-function: main procedure of the program                            */
  1472. /*                                                                    */
  1473. /*-call:     called by the runtime system with:                       */
  1474. /*           => call main parameter_of_the_program <=                 */
  1475. /*                                                                    */
  1476. /*-returns:  nothing                                                  */
  1477. /*                                                                    */
  1478. Main: PROCEDURE expose (exposeList)
  1479.  
  1480. /* ----------------------------- */
  1481.                         /* turn some error checking off               */
  1482.   SIGNAL off ERROR
  1483.  
  1484. /* ----------------------------- */
  1485.  
  1486.                         /* strings which should not be written in the */
  1487.                         /* log file                                   */
  1488.   prog.__LogExcludeWords = screen.__fgYellow screen.__highlight ,
  1489.                            screen.__fgRed screen.__AttrOff
  1490.  
  1491.                         /* get the parameter of the program           */
  1492.   parse arg sourceFiles TargetDir templateFile .
  1493.  
  1494.                         /* check the parameter                        */
  1495.   if sourceFiles = '' then
  1496.     sourceFiles = '.\*.SRC'     /* use default value                  */
  1497.  
  1498.   curDir = directory()
  1499.  
  1500.   if directory( sourceFiles ) <> '' then
  1501.     sourceFiles = directory() || '\*.SRC'
  1502.   else
  1503.     if stream( sourceFiles, 'c', 'QUERY EXIST' ) = '' then
  1504.       call ShowError global.__ErrorExitCode ,,
  1505.            'No source files found'
  1506.     else
  1507.       sourceFiles = stream( sourceFiles, 'c', 'QUERY EXIST' )
  1508.  
  1509.   if stream( sourceFiles, 'c', 'QUERY EXIST' ) = '' then
  1510.     call ShowError global.__ErrorExitCode ,,
  1511.          'No source files found'
  1512.  
  1513.   sourceDir =  dbrright( fileSpec( "drive", sourceFiles ) || ,
  1514.                          fileSpec( "path", sourceFiles ) , 1 )
  1515.  
  1516.   if length( sourceDir ) > 3 & right( sourceDir, 1 ) = '\' then
  1517.     sourceDir = dbrright( sourceDir, 1 )
  1518.  
  1519.   call directory curDir
  1520.  
  1521.   if targetDir = '' then
  1522.     targetDir = '..'            /* use default value                  */
  1523.   else
  1524.     if right( targetDir, 1 ) = '\' then
  1525.       targetDir = dbrright( targetDir,1 )
  1526.  
  1527.   if directory( targetDir ) = '' then
  1528.     call ShowError global.__ErrorExitCode ,,
  1529.          'The target directory "' || targetDir || '" does not exist'
  1530.   else
  1531.     targetDir = directory()
  1532.  
  1533.   call directory curDir
  1534.  
  1535.   if sourceDir = targetDir then
  1536.     call ShowError global.__ErrorExitCode ,,
  1537.                    'Source directory = target directory is not allowed'
  1538.  
  1539.   if templateFile = '' then
  1540.     templateFile = '.\TEMPLATE.CMD'     /* use default value          */
  1541.  
  1542.   testFile = stream( templateFile, 'c', 'QUERY EXIST' )
  1543.   if testFile = '' then
  1544.     call ShowError global.__ErrorExitCode ,,
  1545.                    'Can not find the template file "' || ,
  1546.                    templateFile || '"'
  1547.  
  1548.                         /* get the date of the template file          */
  1549.   templateDateString = GetDateString( templateFile )
  1550.  
  1551.                         /* string with the names of the files to      */
  1552.                         /* exclude                                    */
  1553.   global.__FilesToExclude = templateFile
  1554.   global.__FilesToCopy = ''
  1555.  
  1556.   if pos( '*', sourceFiles ) = 0 & pos( '?', sourceFiles ) = 0 then
  1557.     oneFileCompile = 1
  1558.   else
  1559.     oneFileCompile = 0
  1560.  
  1561.   if oneFileCompile = 0 then
  1562.   do
  1563.     call log ' The source directory is '
  1564.     call log '  ' || AddColor1( '"', sourceDir )
  1565.     call log ' The target directory is '
  1566.     call log '  ' || AddColor1( '"', targetDir )
  1567.     call log ' Using the template file '
  1568.     call log '  ' || AddColor1( '"', templateFile )
  1569.   end /* if oneFileCompile = 0 then */
  1570.  
  1571. /* ------------------------------ */
  1572.                         /* read the ini file if any exist             */
  1573.   call ReadIniFile sourceDir
  1574.  
  1575. /* ------------------------------ */
  1576.  
  1577.   call flushQueue
  1578.   prog.__ExitRoutines =  prog.__ExitRoutines || ' flushQueue '
  1579.  
  1580.   if oneFileCompile = 0 then
  1581.     call log '  Detecting the source files ' || ,
  1582.                 AddColor1( '"', convertName( SourceFiles ) ) || ' ...'
  1583.  
  1584.                         /* put a list of all files in the queue       */
  1585.   '@dir /b /A-d ' SourceFiles ' 2>NUL | rxqueue '
  1586.  
  1587.   CmdFiles.0 = 0
  1588.  
  1589.                         /* put the names of all cmd files to convert  */
  1590.                         /* in a stem                                  */
  1591.   do while queued() <> 0
  1592.     j = CmdFiles.0 + 1
  1593.     curCmdFile = strip( translate( lineIn( 'QUEUE:' ) ) )
  1594.  
  1595.                         /* check the filename                         */
  1596.     if curCmdFile <> '' then
  1597.       if pos( curCmdFile, global.__FilesToExclude ) = 0 then
  1598.       do
  1599.         CmdFiles.j = curCmdFile
  1600.         CmdFiles.0 = j
  1601.       end /* if  curCmdFile <> ... */
  1602.   end /* do while queued <> 0 */
  1603.  
  1604.   if CmdFiles.0 = 0 then
  1605.     call ShowError global.__ErrorExitCode ,,
  1606.                    'No sourcefiles found'
  1607.  
  1608.   if oneFileCompile = 0 then
  1609.   do
  1610.     call log ' ' || AddColor1( , CmdFiles.0 ) || ' files found.'
  1611.     call log ' Now checking and creating the target files ...'
  1612.   end /* if oneFileCompile = 0 then */
  1613.  
  1614.                         /* no of updated files                        */
  1615.   CMDFilesUpdated = 0
  1616.   FilesCopied = 0
  1617.  
  1618.                         /* read the template file if neccessary       */
  1619.   if ReadTemplateFile( templateFile ) <> 1 then
  1620.     call ShowError global.__ErrorExitCode ,,
  1621.          'The format of the template file "' || templateFile || '" is invalid'
  1622.  
  1623.   do j=1 to CmdFiles.0
  1624.                         /* name of the current file in the source dir */
  1625.     curFileName = cmdFiles.j
  1626.  
  1627.     sourceFile = sourceDir || '\' || curFileName
  1628.  
  1629.                         /* name of the current file without path and  */
  1630.                         /* extension                                  */
  1631.     if ( right( curFileName, 4) <> '.SRC' & right( curFileName, 4) <> '.CMD' ) |  ,
  1632.        pos( curFileName, global.__FilesToCopy ) <> 0 then
  1633.     do
  1634.       doCopyFile = 1
  1635.       targetFile = targetDir || '\' || curFileName
  1636.     end /* if right( ... */
  1637.     else
  1638.     do
  1639.       doCopyFile = 0
  1640.       targetFile = targetDir || '\' || dbrright( curFileName, 4 ) || '.CMD'
  1641.     end /* else */
  1642.  
  1643.     parse value stream( sourceFile, 'c' , 'QUERY DATETIME' ) WITH orgDate
  1644.     call log '  Checking the file ' || ,
  1645.                        AddColor1( '"',  convertName( curFileName ) ) || ,
  1646.                        ' (Date: ' || AddColor1( '"', orgDate ) || ') ...'
  1647.  
  1648.                     /* check the file format                          */
  1649.     firstMacroLine = lineIn( sourceFile )
  1650.     call stream sourceFile, 'c', 'CLOSE'
  1651.  
  1652.     if left( firstMacroLine, 2 ) <> '/* ' & doCopyFile = 0 then
  1653.     do
  1654.       call ShowWarning '   This file is NOT a REXX program.'
  1655.       DoCopyFile = 1
  1656.     end /* if left( ... */
  1657.  
  1658.                         /* test the target file                       */
  1659.     if stream( targetFile, 'c', 'QUERY EXIST' ) <> '' then
  1660.     do
  1661.       updateText = screen.__fgRed || screen.__Highlight  || ,
  1662.                    'File is out of date. Now updateing the file ...' || ,
  1663.                    screen.__AttrOff
  1664.  
  1665.       parse value stream( targetFile, 'c', 'QUERY DATETIME' ) WITH comDate
  1666.  
  1667.       sourceDateString = GetDateString( sourceFile )
  1668.       targetDateString = GetDateString( targetFile )
  1669.  
  1670.       fileOutOfDate = ( targetDateString < sourceDateString ) | ,
  1671.                       ( targetDateString < templateDateString )
  1672.  
  1673.     end /* if stream( ... */
  1674.     else
  1675.     do
  1676.       fileOutOfDate = 1
  1677.  
  1678.       updateText = screen.__fgRed || screen.__Highlight  || ,
  1679.                    'File does not exist. Now creating the file ...' || ,
  1680.                    screen.__AttrOff
  1681.     end /* else */
  1682.  
  1683.     if fileOutOfDate = 1 then
  1684.     do
  1685.  
  1686.                                   /* delete the old file if it exists   */
  1687.       if stream( targetFile, 'c', 'QUERY EXIST' ) <> '' then
  1688.       do
  1689.         'attrib -r ' targetFile prog.__LogAll
  1690.         'del ' targetFile prog.__LogAll
  1691.         if rc <> 0 then
  1692.           call ShowError global.__ErrorExitCode ,,
  1693.                'OS Error ' || rc || ' deleting the old file "' || ,
  1694.                targetfile || '"'
  1695.       end /* if stream( targetFile ... */
  1696.  
  1697.       if doCopyFile = 1 then
  1698.       do
  1699.         call log screen.__fgRed || screen.__highlight || ,
  1700.                  '   Copying the file ' || screen.__AttrOff || ,
  1701.                  AddColor1( '"', ConvertName( sourceFile ) ) || ,
  1702.                  ' ...'
  1703.         '@copy ' convertNameToOS( sourceFile ) convertNameToOS( targetFile ) prog.__LogAll
  1704.         if rc <> 0 then
  1705.           call ShowError global.__ErrorExitCode, ,
  1706.                'Error ' || rc || ' copying the file "' || sourceFile || ,
  1707.                ' to "' || targetFile || '"'
  1708.         FilesCopied = FilesCopied + 1
  1709.       end /* if doCopyFile = 1 then */
  1710.       else
  1711.       do
  1712.         call log '   ' || updateText
  1713.  
  1714.                                 /* create the target file             */
  1715.         if CreateTargetFile( sourceFile targetFile ) <> 1 then
  1716.           call ShowError global.__ErrorExitCode ,,
  1717.                'Error creating the targetFile "' || targetFile || '"'
  1718.          else           /* create the token image of the target file  */
  1719.            'cmd /c ' targetFile '//t'
  1720.  
  1721. /*        '@attrib +r ' targetFile prog.__LogAll */
  1722.  
  1723.         CMDFilesUpdated = CMDFilesUpdated + 1
  1724.       end /* else */
  1725.  
  1726.     end /* if fileOutOfDate = 1 then */
  1727.   end /* do j=1 to CmdFiles.0 */
  1728.  
  1729.   if oneFileCompile = 0 then
  1730.   do
  1731.     call log ' ' || AddColor1( , FilesCopied ) || ' cmd file(s) copied.'
  1732.     call log ' ' || AddColor1( , CMDFilesUpdated ) || ' cmd file(s) upgedated.'
  1733.   end /* if oneFileCompile = 0 then */
  1734.  
  1735.   prog.__ExitCode = global.__OKExitCode
  1736.  
  1737. /* ------------------------------ */
  1738.  
  1739. RETURN
  1740.  
  1741. /* ------------------------------------------------------------------ */
  1742.  
  1743. /*** INSERT FURTHER SUBROUTINES HERE ***/
  1744.  
  1745. /* ------------------------------------------------------------------ */
  1746. /* Function: add quote chars and color codes to a string              */
  1747. /*                                                                    */
  1748. /* call:     AddColor1( quoteChar ,myString )                         */
  1749. /*                                                                    */
  1750. /* where:    quoteChar - leading and trailing character for the       */
  1751. /*                       converted string (may be ommited)            */
  1752. /*           myString - string to convert                             */
  1753. /*                                                                    */
  1754. /* returns:  converted string                                         */
  1755. /*                                                                    */
  1756. AddColor1: PROCEDURE expose (exposeList)
  1757.   parse arg quoteChar, myString
  1758.  
  1759. return quoteChar || screen.__fgYellow || screen.__highlight || ,
  1760.        myString || ,
  1761.        screen.__AttrOff || quoteChar
  1762.  
  1763.  
  1764. /* ------------------------------------------------------------------ */
  1765. /* function: get the date of a file as string                         */
  1766. /*                                                                    */
  1767. /* call:     GetDateString thisFile                                   */
  1768. /*                                                                    */
  1769. /* where:    thisFile - file to get the date of                       */
  1770. /*                                                                    */
  1771. /* returns:  date of the file (as string) or '' if not detectable     */
  1772. /*                                                                    */
  1773. GetDateString: PROCEDURE expose (exposeList)
  1774.   parse arg thisFile
  1775.  
  1776.   fileDate = stream( thisFile, 'c', 'QUERY DATETIME' )
  1777.   parse var fileDate thisMonth '-' thisDay '-' thisYear thisHour ':' thisMinute ':' thisSecond
  1778.   fileDate = thisYear  || thisMonth || thisDay || thisHour || thisMinute || thisSecond
  1779. RETURN fileDate
  1780.  
  1781. /* ------------------------------------------------------------------ */
  1782. /* function: read an ini file if it exists                            */
  1783. /*                                                                    */
  1784. /* call:     ReadIniFile iniFileDir                                   */
  1785. /*                                                                    */
  1786. /* where:    iniFileDir - directory with the inifile                  */
  1787. /*                                                                    */
  1788. /* returns:  ''                                                       */
  1789. /*                                                                    */
  1790. ReadIniFile: PROCEDURE expose (exposeList)
  1791.   parse arg iniFileDir .
  1792.  
  1793.   myInIFile = iniFileDir || '\MAKECMD.INI'
  1794.  
  1795.   if stream( myIniFile, 'c', 'QUERY EXIST') <> '' then
  1796.   do
  1797.     call log ' Reading the ini file '
  1798.     call log '  ' || AddColor1( '"', myIniFile )
  1799.  
  1800.     do curLineNo = 1 while lines( myIniFile ) <> 0
  1801.       curLine = translate( strip( lineIn( myIniFile ) ) )
  1802.       if curLine = '' | left( curLine,1 ) = ';' then
  1803.         iterate
  1804.  
  1805.       parse upper var curLine curKeyWord ':' curKeyValue
  1806.       curKeyWord = strip( curKeyWord )
  1807.  
  1808.       select
  1809.         when curKeyWord = 'COPY' then
  1810.           global.__FilesToCopy = global.__FilesToCopy curKeyValue
  1811.         when curKeyWord = 'EXCLUDE' then
  1812.           global.__FilesToExclude = global.__FilesToExclude curKeyValue
  1813.         otherwise
  1814.           call ShowError global.__errorExitCode ,,
  1815.                'The line ' || curLineNo || ' of the file MAKECMD.INI is invalid'
  1816.       end /* select */
  1817.     end /* do while lines( myIniFile ) <> 0 */
  1818.  
  1819.                         /* close the ini file                         */
  1820.     call lineOut myIniFile
  1821.   end /* if stream( ... */
  1822. RETURN ''
  1823.  
  1824. /* ------------------------------------------------------------------ */
  1825. /* function: convert the file/dirname for a message                   */
  1826. /*                                                                    */
  1827. /* call:     ConvertName name                                         */
  1828. /*                                                                    */
  1829. /* where:    name - name of the file or directory                     */
  1830. /*                                                                    */
  1831. /* returns:  converted file or directory name                         */
  1832. /*                                                                    */
  1833. ConvertName: PROCEDURE expose (exposeList)
  1834.   parse arg thisName
  1835.   thisName = strip( thisName )
  1836.   i = length( thisName )
  1837.   if i > 30 then
  1838.   do
  1839.     thisName = substr( thisName, i - 27 )
  1840.     i = pos( '\', thisName )
  1841.     if i <> 0 then
  1842.       thisName = substr( thisName, i+1 )
  1843.     thisName = '...' || thisName
  1844.   end /* if i > 30 then */
  1845. RETURN thisName
  1846.  
  1847. /* ------------------------------------------------------------------ */
  1848. /*-function: read the template file                                   */
  1849. /*                                                                    */
  1850. /*-call:     ReadTemplateFile templateFile                            */
  1851. /*                                                                    */
  1852. /*-where:    templateFile - fully qualified name of the source file   */
  1853. /*                                                                    */
  1854. /*-returns:  1 - okay                                                 */
  1855. /*           0 - error reading the template file                      */
  1856. /*                                                                    */
  1857. /*-output:   global.__template - runtime system for the REXX programs */
  1858. /*                                                                    */
  1859. ReadTemplateFile: PROCEDURE expose (exposeList)
  1860.   parse arg templateFile .
  1861.  
  1862.   thisRC = 0
  1863.                         /* read the source file                       */
  1864.   call stream templateFile, 'c', 'OPEN'
  1865.   i0 = chars( templateFile )
  1866.   tempFile = charIn( templateFile, 1, i0 )
  1867.   call stream templateFile, 'c', 'CLOSE'
  1868.  
  1869.   if i0 <> 0 then
  1870.   do
  1871.     i1 = pos( 'End ' || 'of' || ' Part 1', tempFile )
  1872.     if i1 <> 0 then
  1873.     do
  1874.       i1 = pos( '***' || '/', tempFile, i1 ) +5
  1875.  
  1876.       i2 = pos( 'End ' || 'of' || ' Part 3', tempFile )
  1877.       if i2 <> 0 then
  1878.       do
  1879.         i2 = pos( '***' || '/', tempFile, i2 ) +5
  1880.  
  1881.         i3 = pos( '/* Based on TEMPLATE.CMD', tempFile )
  1882.         if i3 <> 0 then
  1883.         do
  1884.           i4 = pos( '*/', tempFile, i3 )
  1885.           if i1 <> 0 & i2 <> 0 & i3 <> 0 & i4 <> 0 then
  1886.           do
  1887.             global.__TemplateVersionLine = substr( tempFile, i3, i4-i3+2 )
  1888.  
  1889.             global.__template = substr( tempFile, i1, i2-i1+1 )
  1890.  
  1891.             thisRC = 1
  1892.           end /* if i1 <> 0 ... */
  1893.         end /* if i3 <> 0 then */
  1894.       end /* if i2 <> 0 then */
  1895.     end /* if i1 <> 0 then */
  1896.   end /* if i0 <> 0 then */
  1897.  
  1898. RETURN thisRC
  1899.  
  1900. /* ------------------------------------------------------------------ */
  1901. /*-function: CreateTargetFile                                         */
  1902. /*                                                                    */
  1903. /*-call:     CreateTargetFile sourceFile targetFile                   */
  1904. /*                                                                    */
  1905. /*-where:    sourceFile - fully qualified name of the source file     */
  1906. /*           targetFile - fully qualified name of the target file     */
  1907. /*                                                                    */
  1908. /*-returns:  1 - target file created                                  */
  1909. /*           0 - error creating the targetfile                        */
  1910. /*                                                                    */
  1911. /*                                                                    */
  1912. CreateTargetFile: PROCEDURE expose (exposeList)
  1913.   parse arg sourceFile targetFile .
  1914.   thisRC = 0
  1915.  
  1916.   call stream sourceFile, 'c', 'OPEN'
  1917.   i0 = chars( sourceFile )
  1918.   tempFile = charIn( sourceFile, 1, i0 )
  1919.   call stream sourceFile, 'c', 'CLOSE'
  1920.  
  1921.   if i0 <> 0 then
  1922.   do
  1923.     i1 = pos( 'End ' || 'of' || ' Part 1', tempFile )
  1924.     if i1 <> 0 then
  1925.     do
  1926.       i1 = pos( '***' || '/', tempFile, i1 ) +6
  1927.  
  1928.       i2 = pos( 'End ' || 'of' || ' Part 3', tempFile )
  1929.       if i2 <> 0 then
  1930.         i2 = pos( '***' || '/', tempFile, i2 ) +6
  1931.       else
  1932.         i2 = i1
  1933.  
  1934.       i3 = pos( '/' || '* Based on TEMPLATE.CMD', tempFile )
  1935.       if i3 <> 0 then
  1936.       do
  1937.         if i1 <> 0 & i2 <> 0 then
  1938.         do
  1939.           tempFile = overlay( global.__TemplateVersionLine, tempFile, i3 )
  1940.  
  1941.                         /* write the first part of the targetfile     */
  1942.           call charOut targetFile, substr( tempFile, 1, i1 )
  1943.  
  1944.                         /* write the second part of the targetfile    */
  1945.           call CharOut targetFile, global.__template
  1946.  
  1947.                         /* write the third part of the targetfile     */
  1948.           call CharOut targetFile, substr( tempFile, i2 )
  1949.  
  1950.           call stream targetFile, 'c', 'CLOSE'
  1951.  
  1952.           thisRC = 1
  1953.         end /* if i1 <> 0 & i2 <> 0 then */
  1954.       end /* if i3 <> 0 then */
  1955.     end /* if i1 <> 0 then */
  1956.   end /* if i0 <> 0 then */
  1957.  
  1958. RETURN thisRC
  1959.  
  1960. /* ------------------------------------------------------------------ */
  1961. /*-function: Show the invocation syntax                               */
  1962. /*                                                                    */
  1963. /*-call:     called by the runtime system with                        */
  1964. /*           => call ShowUsage <=                                     */
  1965. /*                                                                    */
  1966. /*-where:    -                                                        */
  1967. /*                                                                    */
  1968. /*-returns:  ''                                                       */
  1969. /*                                                                    */
  1970. /*                                                                    */
  1971. ShowUsage:
  1972.   call log 'Usage: MakeCmd {sourceFiles} {targetDir} {templateFile}'
  1973. RETURN ''
  1974.  
  1975. /***        End of Part 4 of the source code of TEMPLATE.CMD        ***/
  1976.  
  1977. /**********************************************************************/   
  1978.  
  1979.  
  1980.  
  1981.  
  1982.  
  1983.