home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 18 REXX / 18-REXX.zip / rc321.zip / rexxccm.cmd < prev    next >
OS/2 REXX Batch file  |  1997-09-13  |  124KB  |  2,559 lines

  1. /* ------------------------------------------------------------------ */
  2. /* REXXCCM.CMD - REXX program to create a token image of a REXX       */
  3. /*               program using the macro space                        */
  4. /*                                                                    */
  5. /* (c) 1997 Bernd Schemmer                                            */
  6. /*                                                                    */
  7. /* Author:                                                            */
  8. /*   Bernd Schemmer                                                   */
  9. /*   Baeckerweg 48                                                    */
  10. /*   D-60316 Frankfurt                                                */
  11. /*   Germany                                                          */
  12. /*   CompuServe: 100104,613                                           */
  13. /*                                                                    */
  14. /* Initial Release:                                                   */
  15. /*   09.09.1997 /bs                                                   */
  16. /* Last Update:                                                       */
  17. /*   10.09.1997 /bs                                                   */
  18. /*                                                                    */
  19. /* Usage:                                                             */
  20. /*                                                                    */
  21. /*  REXXCCM Source:sourceFile Target:targetDirectory                  */
  22. /*          {/L:logfile} {/H} {/Silent} {/NoSound} {/NoAnsi}          */
  23. /*          {/Trace}                                                  */
  24. /*                                                                    */
  25. /* Parameters:                                                        */
  26. /*                                                                    */
  27. /*   Source:sourceFile                                                */
  28. /*     The name of the source file                                    */
  29. /*     The name of the macro will be the name of the file without the */
  30. /*     extension.                                                     */
  31. /*     To change the name for the macro you can use the string        */
  32. /*                                                                    */
  33. /*         /* MACRONAME: myName */                                    */
  34. /*     or                                                             */
  35. /*         /* MACRONAME: "m y n a m e " */                            */
  36. /*                                                                    */
  37. /*     as first line of the file.                                     */
  38. /*                                                                    */
  39. /*     You can use this parameter as often as you like. All macros    */
  40. /*     will be in the image. But REXXCCM only creates a loader for    */
  41. /*     the first macro found in the parameters.                       */
  42. /*                                                                    */
  43. /*   Target:targetDirectory                                           */
  44. /*     Name of the target directory; the directory must exist.        */
  45. /*     The target directory can not be the directory with the         */
  46. /*     source file.                                                   */
  47. /*     Existing target file are always overwritten!                   */
  48. /*     The name of the target image file is the name of the first     */
  49. /*     source file with the extension ".IMC" for Classic REXX and     */
  50. /*     ".IMO" for Object REXX.                                        */
  51. /*     (depending on the current active REXX interpreter).            */
  52. /*     The name of the loader is the name of the first source file    */
  53. /*     with the extension ".CMD".                                     */
  54. /*                                                                    */
  55. /*                                                                    */
  56. /*   /L:logFile - logfile is the name of the logfile :-)              */
  57. /*                This parameter is case-sensitive!                   */
  58. /*                def.: do not use a logfile                          */
  59. /*                                                                    */
  60. /*   /H         - show usage, you may also use                        */
  61. /*                /h, /?, /HELP, -h, -H, -HELP or -?                  */
  62. /*                (MAIN is not called!)                               */
  63. /*                                                                    */
  64. /*   /Silent    - suppress all messages (except error messages)       */
  65. /*                You should also use the parameter /L:logfile if you */
  66. /*                use this parameter!                                 */
  67. /*                You may also set the environment variable SILENT to */
  68. /*                "1" to suppress all messages.                       */
  69. /*                                                                    */
  70. /*   /NoSound   - suppress all sounds. You may also set the           */
  71. /*                environment variable SOUND to "0" to suppress the   */
  72. /*                sounds.                                             */
  73. /*                                                                    */
  74. /*   /NoAnsi    - do not use ANSI codes. You may also set the         */
  75. /*                environment variable ANSI to "0" to suppress the    */
  76. /*                use of ANSI codes.                                  */
  77. /*                                                                    */
  78. /*   /Trace     - turn TRACE on before calling MAIN. You may also     */
  79. /*                set the environment variable RXTTRACE to ON to      */
  80. /*                turn the TRACE mode for MAIN on.                    */
  81. /*                                                                    */
  82. /* Notes:                                                             */
  83. /*                                                                    */
  84. /*  REXXCCM and the programs created with REXXCCM need the new        */
  85. /*  REXXUTIL.DLL from Object REXX.                                    */
  86. /*  Note that you can use this DLL also in Classic REXX.              */
  87. /*  To do this simply copy the Object REXX files REXXUTIL.DLL and     */ 
  88. /*  REXXCRT.DLL to the directory \OS2\DLL.                            */
  89. /*                                                                    */
  90. /*  If you do not want to use the new REXXUTIL DLL as default DLL,    */
  91. /*  copy the the new REXXUTIL DLL into the directory C:\OREXX and     */
  92. /*  only the DLL REXXCRT.DLL into a directory in the LIBPATH.         */
  93. /*  If you change the directory for the new REXXUTIL.DLL in this      */
  94. /*  case, you must also change the variable 'global.__REXXUTILLDLL'   */
  95. /*  below.                                                            */
  96. /*                                                                    */
  97. /*  REXXCCM always creates two files:                                 */
  98. /*                                                                    */
  99. /*    Either sourceFile.IMC or sourceFile.IMO                         */
  100. /*                                                                    */
  101. /*  and the loader to load the tokenized program called               */
  102. /*                                                                    */
  103. /*     sourceFile.CMD                                                 */
  104. /*                                                                    */
  105. /*  (where 'sourceFile' is the name of the first source file)         */
  106. /*  Note that you can't execute the created image without the         */
  107. /*  loader!                                                           */
  108. /*                                                                    */
  109. /*  REXXCCM always clears the complete macro space!                   */
  110. /*                                                                    */
  111. /*  To create REXX programs that run under Classic REXX and           */
  112. /*  Object REXX you should run REXXCCM once under both REXX           */
  113. /*  interpreters and distribute always both images.                   */
  114. /*  Note that the loader always loads the correct image.              */
  115. /*                                                                    */
  116. /*                                                                    */
  117. /* returncodes:                                                       */
  118. /*      0 - execution okay                                            */
  119. /*    240 ... 252                                                     */
  120. /*          reserved for the runtime system                           */
  121. /*    253 - syntax help called (parameter /h)                         */
  122. /*    254 - user break (CTRL-C)                                       */
  123. /*    255 - internal runtime system error                             */
  124. /*   else - program specific errors                                   */
  125. /*                                                                    */
  126. /*                                                                    */
  127. /*                                                                    */
  128. /* Environment variables used while running the program               */
  129. /*                                                                    */
  130. /* ■ ANSI                                                             */
  131. /*   - Set the environment variable 'ANSI' to "0" or "OFF" if you     */
  132. /*     don't want colors.                                             */
  133. /*                                                                    */
  134. /* ■ PATCHDRIVE                                                       */
  135. /*   - Set the environment variable 'PATCHDRIVE' to the drive with    */
  136. /*     a patched version of your program (if any exist, see the       */
  137. /*     routine 'I!.__CheckPatch' for the algorithm used ).            */
  138. /*                                                                    */
  139. /* ■ SILENT                                                           */
  140. /*   - Set the environment variable 'SILENT' to "1" or "ON" to        */
  141. /*     suppress all messages.                                         */
  142. /*                                                                    */
  143. /* ■ SOUND                                                            */
  144. /*   - Set the environment variable 'SOUND' to "0" or "OFF" if you    */
  145. /*     don't want sounds.                                             */
  146. /*                                                                    */
  147. /* ■ RXTTRACE                                                         */
  148. /*   - Set the environment variable 'RXTTRACE' to "MAIN" to turn the  */
  149. /*     trace mode for the function MAIN on.                           */
  150. /*                                                                    */
  151. /* ■ VERBOSE                                                          */
  152. /*   - Set the environment variable 'VERBOSE' to any value not equal  */
  153. /*     '' if you want debug information. If the value of the variable */
  154. /*     is 'DEBUG', the error handler turns interactive trace on if an */
  155. /*     error occured.                                                 */
  156. /*     Note that the error handler also turns interactive trace on if */
  157. /*     the environment variable RXTTRACE is set to 'MAIN' or if the   */
  158. /*     parameter '/TRACE' is specified.                               */
  159. /*                                                                    */
  160. /* Distribution                                                       */
  161. /*   This program is part of the REXXCC package. Please see the file  */
  162. /*   REXXCC.CMD for my distribution policy.                           */
  163. /*                                                                    */
  164. /* Based on TEMPLATE.CMD v3.06, TEMPLATE is (c) 1996 Bernd Schemmer,  */
  165. /* Baeckerweg 48, D-60316 Frankfurt, Germany, Compuserve: 100104,613  */
  166. /* ------------------------------------------------------------------ */
  167.  
  168.   call trace 'off'      /* turn interactive trace off                 */
  169.                         /* use this statement as the first statement  */
  170.                         /* in your program, to ignore the value of    */
  171.                         /* the environment variable RXTRACE.          */
  172.  
  173.                   global. = ''  /* init the stem global. with ''      */
  174.  
  175. /*** change the following values to your need                       ***/
  176.  
  177.                         /* additional parameter                 v3.06 */
  178.                         /* (string for the usage routine)       v3.06 */
  179.   global.__userUsage  = 'SOURCE:sourceFile TARGET:targetDirectory'
  180.  
  181.          global.__Version = 1.0          /* Version of YOUR program   */
  182.  
  183.        global.__SignOnMsg = 1   /* set to 0 if you do not want the    */
  184.                                 /* program start and end messages     */
  185.  
  186.                                 /* name & path of the REXXUTIL.DLL if */
  187.                                 /* it is NOT the default REXXUTIL DLL */
  188.      global.__REXXUTILDLL = 'C:\OREXX\REXXUTIL.DLL'
  189.  
  190.          global.__NeedCID = 1   /* set to 1 if you need CID support   */
  191.  
  192.       global.__NeedColors = 1   /* set to 1 if you want colored msgs  */
  193.  
  194.   global.__NeedPatchCheck = 1   /* set to 1 if you want the program   */
  195.                                 /* to search for a patched version of */
  196.                                 /* this program                       */
  197.  
  198.               /* set default values for EXPOSELIST if necessary       */
  199. /*             exposeList = ''                                        */
  200.  
  201.               /* name of the routine for the message handling         */
  202.               /* Note: Use '' for hardcoded messages                  */
  203. /*          global.__GetMsg = 'GETMSG'                                */
  204.  
  205.              /* base number for the message numbers (def.: 1000)      */
  206. /*          global.__BaseMsgNo = 1000                                 */
  207.  
  208.              /* note: set the variable prog.__STDOUT to "STDERR:"     */
  209.              /*       or "NUL" if your program is a filter program!   */
  210.  
  211.   prog.__STDOUT = 'STDOUT'        /* necessary for Object REXX        */
  212.   prog.__STDERR = 'STDOUT'        /* necessary for Object REXX        */
  213.                                                                    /*!*/
  214. /***                End of variables to change                      ***/
  215. /*      HINT: The further program code is in the function MAIN        */
  216.  
  217. /***        End of Part 1 of the source code of TEMPLATE.CMD        ***/
  218.  
  219. /***       Start of Part 2 of the source code of TEMPLATE.CMD       ***/
  220.  
  221. /*************** DO NOT CHANGE THE FOLLOWING LINES ********************/
  222.  
  223.                         /* names of the global variables, which all   */
  224.                         /* procedures must know                       */
  225.   exposeList = 'prog. screen. I!. global. exposeList ' exposeList
  226.  
  227.                         /* check the type of the base message number  */
  228.   if datatype( global.__BaseMsgNo, 'W' ) <> 1 then
  229.     global.__BaseMsgNo = 1000
  230.  
  231.                         /* init internal variables                    */
  232.   I!. = ''
  233.                         /* save default STDOUT and STDERR             */
  234.   if symbol( 'prog.__STDOUT' ) = 'VAR' then
  235.     I!.__2 = prog.__STDOUT
  236.   if symbol( 'prog.__STDERR' ) = 'VAR' then
  237.     I!.__3 = prog.__STDERR
  238.  
  239.                         /* init the stems prog. & screen.             */
  240.   parse value '' with prog. screen.
  241.  
  242.                         /* reset the timer                            */
  243.   call time 'R'
  244.  
  245.                         /* restore default STDOUT and STDERR          */
  246.   prog.__STDOUT = I!.__2;    prog.__STDERR = I!.__3
  247.  
  248.                         /* get the number of the first line with      */
  249.                         /* user code                                  */
  250.   call I!.__GetUserCode
  251.  
  252. /* ------------------------------------------------------------------ */
  253. /* install the error handler                                          */
  254.  
  255.                         /* break errors (CTRL-C)                      */
  256.   CALL ON HALT        NAME I!.__UserAbort
  257.                         /* syntax errors                              */
  258.   SIGNAL ON SYNTAX    NAME I!.__ErrorAbort
  259.                         /* using of not initialisized variables       */
  260.   SIGNAL ON NOVALUE   NAME I!.__ErrorAbort
  261.                         /* failure condition                          */
  262.   SIGNAL ON FAILURE   NAME I!.__ErrorAbort
  263.                         /* error condition                            */
  264.   SIGNAL ON ERROR     NAME I!.__ErrorAbort
  265.                         /* disk not ready condition                   */
  266.   SIGNAL ON NOTREADY  NAME I!.__ErrorAbort
  267.  
  268. /* ------------------------------------------------------------------ */
  269. /* init the variables                                                 */
  270.  
  271.                         /* get & save the parameter                   */
  272.   parse arg I!.__RealParam 1 prog.__Param
  273.  
  274.                         /* init the variables                         */
  275.  
  276.                         /* define exit code values                    */
  277.   global.__ErrorExitCode = 255
  278.      global.__OKExitCode = 0
  279.  
  280.                         /* init the compound variable prog.           */
  281.   call I!.__InitProgStem
  282.  
  283.                         /* define the variables for CID programs      */
  284.   call I!.__InitCIDVars
  285.  
  286.                         /* init the program exit code                 */
  287.   prog.__ExitCode = global.__OKExitCode
  288.  
  289.                         /* check the parameter and env. variables     */
  290.                         /* This must run before I!.__InitColorVars!   */
  291.   call I!.__chkPandE
  292.  
  293.                         /* define the color variables                 */
  294.   call I!.__InitColorVars
  295.  
  296.                         /* check if there is a logfile parameter      */
  297.   call I!.__SetLogVars
  298.  
  299. /* ------------------------------------------------------------------ */
  300. /* show program start message                                         */
  301.  
  302.   call I!.__SignMsg
  303.  
  304. /* ------------------------------------------------------------------ */
  305. /* check if there is a patched version of this program                */
  306.  
  307.   call I!.__CheckPatch
  308.  
  309. /* ------------------------------------------------------------------ */
  310.  
  311.                         /* check for a help parameter                 */
  312.   if pos( translate( word( prog.__Param,1 ) ), ,
  313.           '/?/H/HELP/-?-H-HELP' ) <> 0 then
  314.   do
  315.     prog.__exitCode = 253
  316.  
  317.     call I!.__CallUserProc 1, 'ShowUsage'
  318.  
  319.     SIGNAL I!.__programEnd
  320.  
  321.   end /* pos( translate( ... */
  322.  
  323. /* ------------------------------------------------------------------ */
  324.  
  325.                         /* call the main procedure                    */
  326.   call I!.__CallUserProc 2, 'main' strip( prog.__Param )
  327.  
  328.                         /* use the return code of 'main' as exitcode  */
  329.                         /* if a returncode was returned               */
  330.   if symbol( 'I!.__UserProcRC' ) == 'VAR' then
  331.     prog.__ExitCode = I!.__UserProcRC
  332.  
  333. /* ------------------------------------------------------------------ */
  334. /* house keeping                                                      */
  335.  
  336. I!.__ProgramEnd:
  337.  
  338.                                 /* call the exit routines             */
  339.   do while prog.__exitRoutines <> ''
  340.  
  341.                         /* delete the name of the routine from the    */
  342.                         /* list to avoid endless loops!               */
  343.     parse var prog.__ExitRoutines I!.__cer prog.__ExitRoutines
  344.  
  345.     call I!.__CallUserProc 1, I!.__cer
  346.  
  347.   end /* do while prog.__ExitRoutines <> '' */
  348.  
  349.                                 /* restore the current directory      */
  350.   if symbol( 'prog.__CurDir' ) == 'VAR' then
  351.     call directory prog.__CurDir
  352.  
  353.                                 /* show sign off message              */
  354.   call I!.__SignMsg 'E'
  355.  
  356. EXIT prog.__ExitCode
  357.  
  358. /* ------------------------------------------------------------------ */
  359. /* function: show the sign on or sign off message                     */
  360. /*                                                                    */
  361. /* call:     I!.__SignMsg which                                       */
  362. /*                                                                    */
  363. /* where:    which - 'E' - show the sign off message                  */
  364. /*                         else show the sign on message              */
  365. /*                                                                    */
  366. /* returns:  nothing                                                  */
  367. /*                                                                    */
  368. I!.__SignMsg: PROCEDURE expose (exposeList)
  369.   if global.__SignOnMsg <> 1 then
  370.     RETURN
  371.  
  372.                         /* default: program start message             */
  373.   i = 12
  374.  
  375.   if arg(1) = 'E' then
  376.   do
  377.     i = 13
  378.                         /* program end message                        */
  379.     i!.__rc1 = prog.__ExitCode
  380.  
  381.                                 /* check if the exit code is decimal  */
  382.                                 /* and convert it to hexadecimal if   */
  383.                                 /* possible                           */
  384.     if dataType( prog.__ExitCode, 'W' ) then
  385.     do
  386.       if prog.__ExitCode < 0 then
  387.         prog.__ExitCode = 65536 + prog.__ExitCode
  388.       i!.__rc2 = D2X( prog.__ExitCode )
  389.     end /* if .. */
  390.  
  391.   end /* if arg(1) = 'E' then */
  392.  
  393.   screen.__CurColor = screen.__SignOnColor
  394.   call Log I!.__GetMsg( i, prog.__Name, global.__Version, date(),,
  395.                         time(), i!.__rc1, i!.__rc2 )
  396.   screen.__CurColor = screen.__NormalColor
  397. RETURN
  398.  
  399. /* ------------------------------------------------------------------ */
  400. /* function: call a user defined routine                              */
  401. /*           (avoid errors if the routine is not defined)             */
  402. /*                                                                    */
  403. /* call:     I!.__CallUserProc errorAction, procName {procParameter}  */
  404. /*                                                                    */
  405. /* where:    errorAction - action, if procName is not defined         */
  406. /*                         0: do nothing (only set the RC)            */
  407. /*                         1: show a warning and set the RC           */
  408. /*                         2: abort the program                       */
  409. /*           procName - name of the procedure                         */
  410. /*           procParameter - parameter for the procedure              */
  411. /*                                                                    */
  412. /* returns:  1 - ok                                                   */
  413. /*           0 - procname not found                                   */
  414. /*                                                                    */
  415. /* output:   I!.__UserProcRC - Returncode of the called procedure     */
  416. /*                             (dropped if the proedure don't         */
  417. /*                             return a value)                        */
  418. /*                                                                    */
  419. I!.__CallUserProc: PROCEDURE expose (exposeList) result rc sigl
  420.   parse arg I!.__ErrorAction , I!.__ProcN I!.__ProcP
  421.  
  422.   I!.__thisRC = 0
  423.   drop I!.__UserProcRC
  424.  
  425.   iLine = 'call ' I!.__ProcN
  426.   if prog.__Trace = 1 & I!.__ProcN = 'main' then
  427.     iLine = 'trace ?a;'|| iLine
  428.  
  429. /** DO NOT CHANGE, ADD OR DELETE ONE OF THE FOLLOWING SEVEN LINES!!! **/
  430.   I!.__ICmdLine = GetLineNo()+2+(I!.__ProcP <> '')*2               /*!*/
  431.   if I!.__ProcP = '' then                                          /*!*/
  432.     interpret iLine                                                /*!*/
  433.   else                                                             /*!*/
  434.     interpret iLine "I!.__ProcP"                                   /*!*/
  435. /** DO NOT CHANGE, ADD OR DELETE ONE OF THE PRECEEDING SEVEN LINES!! **/
  436.  
  437. /* Caution: The CALL statement changes the variable RESULT!           */
  438.   I!.__0 = trace( 'off' )
  439.  
  440.   I!.__thisRC = 1
  441.   if symbol( 'RESULT' ) == 'VAR' then
  442.     I!.__UserProcRC = value( 'RESULT' )
  443.     
  444.                     /* this label is used if the interpret command    */
  445.                     /* ends with an error                             */
  446. I!.__CallUserProc2:
  447.  
  448.   if I!.__ThisRC = 0 then
  449.   do
  450.     if I!.__ErrorAction = 2 then
  451.       call ShowError global.__ErrorExitCode , ,
  452.                    I!.__GetMsg( 1, I!.__ProcN )
  453.  
  454.     if I!.__ErrorAction = 1 then
  455.       call ShowWarning I!.__GetMsg( 1 , I!.__ProcN )
  456.   end /* if I!.__thisRC = 0 then */
  457.  
  458. RETURN I!.__thisRC
  459.  
  460. /* ------------------------------------------------------------------ */
  461. /* function: set the variables for the logfile handling               */
  462. /*                                                                    */
  463. /* call:     I!.__SetLogVars                                          */
  464. /*                                                                    */
  465. /* input:    prog.__Param - parameter for the program                 */
  466. /*                                                                    */
  467. /* output:   prog.__LogFile     - name of the logfile (or NUL)        */
  468. /*           prog.__LogSTDERR   - string to direct STDERR into the    */
  469. /*                                logfile                             */
  470. /*           prog.__LogSTDOUT   - string to direct STDOUT into the    */
  471. /*                                logfile                             */
  472. /*           prog.__LogAll      - string to direct STDOUT and STDERR  */
  473. /*                                into the logfile                    */
  474. /*           prog.__LogFileParm - string to inherit the logfile       */
  475. /*                                parameter to a child CMD            */
  476. /*           prog.__Param       - program parameter without the       */
  477. /*                                logfile parameter                   */
  478. /*                                                                    */
  479. /* returns:  nothing                                                  */
  480. /*                                                                    */
  481. I!.__SetLogVars: PROCEDURE expose (exposeList)
  482.  
  483.   parse var prog.__Param prog.__param '/L:' logFileName ' ' rest
  484.   prog.__param = prog.__Param rest
  485.  
  486.                         /* avoid an error if the drive is not ready   */
  487.   SIGNAL OFF NOTREADY
  488.  
  489.                         /* default log device is the NUL device       */
  490.   prog.__LogFile = 'NUL'
  491.  
  492.   if logFileName <> '' then
  493.   do
  494.                         /* check if we can write to the logfile       */
  495.     logStatus = stream( logFileName, 'c', 'OPEN WRITE')
  496.     if logStatus <> 'READY:' then
  497.     do
  498.       prog.__LogFileParm = ''
  499.  
  500.       call ShowWarning I!.__GetMsg( 2, logFileName, logStatus )
  501.  
  502.     end /* if logStatus <> 'READY:' then */
  503.     else
  504.     do
  505.                         /* close the logfile                          */
  506.       call stream logFileName, 'c', 'CLOSE'
  507.  
  508.                         /* get the fully qualified name of the        */
  509.                         /* logfile                                    */
  510.                         /*                                      v3.04 */
  511.       parse upper value stream( logFileName, 'c', 'QUERY EXIST' ) WITH prog.__LogFile
  512.  
  513.       prog.__LogFileParm = '/L:' || prog.__LogFile
  514.     end /* else */
  515.   end /* if prog.__LogFile <> '' then */
  516.  
  517.                         /* variable to direct STDOUT of an OS/2       */
  518.                         /* program into the logfile                   */
  519.   prog.__LogSTDOUT = ' 1>>' || prog.__LogFile
  520.  
  521.                         /* variable to direct STDERR of an OS/2       */
  522.                         /* program into the logfile                   */
  523.   prog.__LogSTDERR = ' 2>>' || prog.__LogFile
  524.  
  525.                         /* variable to direct STDOUT and STDERR of    */
  526.                         /* an OS/2 program into the log file          */
  527.   prog.__LogALL = prog.__LogSTDERR || ' 1>>&2'
  528.  
  529. RETURN
  530.  
  531. /* ------------------------------------------------------------------ */
  532. /* function: check the parameter and the environment variables for    */
  533. /*           the runtime system                                       */
  534. /*                                                                    */
  535. /* call:     I!.__chkPandE                                            */
  536. /*                                                                    */
  537. /* input:    prog.__Param - parameter for the program                 */
  538. /*           prog.__env - name of the environment                     */
  539. /*                                                                    */
  540. /* output:   prog.__QuietMode - 1 if parameter '/Silent' found        */
  541. /*                              or environment variable SILENT set    */
  542. /*           prog.__NoSound   - 1 if parameter '/NoSound' found       */
  543. /*                              or environment variable SOUND set     */
  544. /*           screen.          - "" if parameter '/NoANSI' found       */
  545. /*                              or environment variable ANSI set      */
  546. /*           prog.__Param     - remaining parameter for the procedure */
  547. /*                              MAIN.                                 */
  548. /*           prog.__Trace     - 1 if parameter '/Trace' found         */
  549. /*                              or if the environment variable        */
  550. /*                              RXTTRACE is set to MAIN               */
  551. /*                                                                    */
  552. /* returns:  nothing                                                  */
  553. /*                                                                    */
  554. I!.__chkPandE: PROCEDURE expose (exposeList)
  555.  
  556.   global.__verbose = value( 'VERBOSE' ,, prog.__env )
  557.  
  558.   o!.0 = 4                              /* no. of known parameters    */
  559.                                         /* and environment variables  */
  560.  
  561.   o!.1.parm = '/SILENT'                 /* parameter name             */
  562.   o!.1.env  = 'SILENT'                  /* name of the env. var       */
  563.   o!.1.vals = 'ON 1'                    /* possible values for the    */
  564.                                         /* environment variable       */
  565.   o!.1.stmt = 'prog.__QuietMode=1'      /* statement to execute       */
  566.                                         /* if this parameter was      */
  567.                                         /* entered or the environment */
  568.                                         /* variable is set            */
  569.  
  570.   o!.2.parm = '/NOSOUND'                /* turn sound off             */
  571.   o!.2.env  = 'SOUND'
  572.   o!.2.vals = 'OFF 0'
  573.   o!.2.stmt = 'prog.__NoSound=1'
  574.  
  575.   o!.3.parm = '/NOANSI'                 /* turn ANSI support off      */
  576.   o!.3.env  = 'ANSI'
  577.   o!.3.vals = 'OFF 0'
  578.   o!.3.stmt = 'global.__NeedColors=0'
  579.  
  580.   o!.4.parm = '/TRACE'          /* exeucte MAIN in single step mode   */
  581.   o!.4.env  = 'RXTTRACE'
  582.   o!.4.vals = 'MAIN'
  583.   o!.4.stmt = 'prog.__Trace=1'
  584.  
  585.   do i = 1 to o!.0
  586.                         /* check the parameter                        */
  587.     j = wordPos( o!.i.parm, translate( prog.__Param ) )
  588.     if j = 0 then       /* no parameter found, check the env. var     */
  589.       j = wordPos( translate( value( o!.i.env ,, prog.__env ) ) ,,
  590.                     o!.i.vals )
  591.     else                /* parameter found, delete the parameter      */
  592.       prog.__Param = strip( delWord( prog.__Param, j,1 ) )
  593.  
  594.                         /* if j is not zero either the parameter was  */
  595.                         /* found or the environment variable is set   */
  596.     if j <> 0 then
  597.       interpret o!.i.stmt
  598.   end /* do i = 1 to o!.0 */
  599.  
  600. RETURN
  601.  
  602. /* ------------------------------------------------------------------ */
  603. /* function:  convert a file or directory name to OS conventions      */
  604. /*            by adding a leading and trailing double quote           */
  605. /*                                                                    */
  606. /* call:      convertNameToOS dir_or_file_name                        */
  607. /*                                                                    */
  608. /* where:     dir_or_file_name = name to convert                      */
  609. /*                                                                    */
  610. /* returns:   converted file or directory name                        */
  611. /*                                                                    */
  612. ConvertNameToOS: PROCEDURE expose (exposeList)
  613.   parse arg fn
  614. RETURN '"' || fn || '"'                                      /* v3.06 */
  615.  
  616. /* ------------------------------------------------------------------ */
  617. /* function: flush the default REXX queue                             */
  618. /*                                                                    */
  619. /* call:     FlushQueue                                               */
  620. /*                                                                    */
  621. /* returns:  ''                                                       */
  622. /*                                                                    */
  623. FlushQueue: /* PROCEDURE expose (exposeList) */
  624.   do while QUEUED() <> 0
  625.     parse pull
  626.   end /* do while QUEUED() <> 0 */
  627. RETURN ' '                                                   /* v3.03 */
  628.  
  629. /* ------------------------------------------------------------------ */
  630. /* function: include a file if it exists                              */
  631. /*                                                                    */
  632. /* call:     TryInclude( IncludeFile )                                */
  633. /*                                                                    */
  634. /* where:    IncludeFile = name of the file to include                */
  635. /*                                                                    */
  636. /* output:   prog.__rc = 0 - include file executed                    */
  637. /*           else: file not found                                     */
  638. /*                                                                    */
  639. /* returns:  ''                                                       */
  640. /*                                                                    */
  641. TryInclude:
  642.   parse upper arg I!.__IncFileName
  643.   prog.__rc = 1
  644.  
  645.   if I!.__IncFileName = '' then
  646.     RETURN ' '                                               /* v3.03 */
  647.  
  648.   if stream( I!.__IncFileName,'c','QUERY EXIST' ) = '' then
  649.     RETURN ' '                                               /* v3.03 */
  650.  
  651.   prog.__rc = 0
  652.  
  653.   /* execute INCLUDE */
  654.  
  655. /* ------------------------------------------------------------------ */
  656. /* function: include a file                                           */
  657. /*                                                                    */
  658. /* call:     Include( IncludeFile )                                   */
  659. /*                                                                    */
  660. /* where:    IncludeFile = name of the file to include                */
  661. /*                                                                    */
  662. /* returns:  ''                                                       */
  663. /*                                                                    */
  664. Include:
  665.   parse upper arg I!.__IncFileName
  666.  
  667.                         /* check if the include file exists           */
  668.   if stream( I!.__IncFileName, 'c', 'QUERY EXIST' ) == '' then
  669.     call ShowError global.__ErrorExitCode, ,
  670.                    I!.__GetMsg( 3, I!.__IncFileName )
  671.  
  672.                         /* read and interpret the include file        */
  673.   do I!.__IncLineNO = 1 while lines( I!.__IncFileName ) <> 0
  674.     I!.__IncCurLine = ''
  675.                         /* save the absolute position of the start of */
  676.                         /* this line for the error handler            */
  677.     I!.__IncCurLinePos = stream(I!.__IncFileName,'c','SEEK +0')
  678.  
  679.                         /* handle multi line statements               */
  680.     do forever
  681.       I!.__IncCurLine = I!.__IncCurLine ,
  682.                         strip( lineIn( I!.__IncFileName ) )
  683.  
  684.       if right( I!.__IncCurLine,1 ) <> ',' then
  685.         leave
  686.  
  687.                         /* statement continues on the next line       */
  688.       if lines( I!.__IncFileName ) == 0 then
  689.         call ShowError global.__ErrorExitCode ,,
  690.              I!.__GetMsg( 4, I!.__IncFileName )
  691.  
  692.                         /* the next lines is only executed if the IF */
  693.                         /* statement above is FALSE                  */
  694.       I!.__IncCurLine = substr( I!.__IncCurLine,1, ,
  695.                                 length( I!.__IncCurLine )-1 )
  696.  
  697.     end /* do forever */
  698.  
  699.     I!.__IncActive = 1
  700.     interpret I!.__IncCurLine
  701.     I!.__IncActive = 0
  702.  
  703.   end /* do I!.__IncLineNO = 1 while lines( I!.__IncFileName ) <> 0 ) */
  704.  
  705.                         /* close the include file!                    */
  706.   call stream I!.__IncFileName, 'c', 'CLOSE'
  707.  
  708.                     /* do NOT return a NULL string ('')!        v3.03 */
  709.                     /* Due to a bug in the CMD.EXE this will    v3.03 */
  710.                     /* cause the error SYS0008 after the 32nd   v3.03 */
  711.                     /* call of this function!                   v3.03 */
  712. RETURN ' '
  713.  
  714. /* ------------------------------------------------------------------ */
  715. /* function: init color variables                                     */
  716. /*                                                                    */
  717. /* call:     I!.__InitColorVars                                       */
  718. /*                                                                    */
  719. /* returns:  nothing                                                  */
  720. /*                                                                    */
  721. I!.__InitColorVars: /* PROCEDURE expose (exposeList) */
  722.  
  723.   if 1 == global.__NeedColors then
  724.   do
  725.     escC = '1B'x || '['                                      /* v3.04 */
  726.  
  727.     t1 = 'SAVEPOS RESTPOS ATTROFF' ,                         /* v3.05 */
  728.          'HIGHLIGHT NORMAL BLINK INVERS INVISIBLE'           /* v3.05 */
  729.  
  730.     t2 = 's u 0;m 1;m 2;m 5;m 7;m 8;m'                       /* v3.05 */
  731.  
  732.     screen.__DELEOL = escC || 'K'                            /* v3.05 */
  733.  
  734.     do i = 1 to 8                                            /* v3.05 */
  735.  
  736.       call value 'SCREEN.__' || word( t1, i ) ,,             /* v3.05 */
  737.                  escC || word( t2,i )                        /* v3.05 */
  738.  
  739.                                                              /* v3.05 */
  740.       s = word( 'BLACK RED GREEN YELLOW BLUE MAGNENTA CYAN WHITE', i )
  741.       call value 'SCREEN.__FG' || s,,                        /* v3.05 */
  742.                  escC || 29+i || ';m'                        /* v3.05 */
  743.       call value 'SCREEN.__BG' || s,,                        /* v3.05 */
  744.                  escC || 39+i || ';m'                        /* v3.05 */
  745.     end /* do i = 1 to 8 */                                  /* v3.05 */
  746.  
  747.     drop t1 t2 s i                                           /* v3.05 */
  748.  
  749. /* --------------------------- */
  750.                         /* define color variables                     */
  751.     screen.__ErrorColor  = screen.__AttrOff || screen.__Highlight || ,
  752.                            screen.__FGYellow || screen.__bgRed
  753.  
  754.     screen.__NormalColor = screen.__AttrOff ||                       ,
  755.                            screen.__fgWhite || screen.__bgBlack
  756.  
  757.     screen.__DebugColor  = screen.__AttrOff || screen.__Highlight || ,
  758.                            screen.__fgBlue || screen.__bgWhite
  759.  
  760.     screen.__PromptColor = screen.__AttrOff || screen.__Highlight || ,
  761.                            screen.__fgYellow || screen.__bgMagnenta
  762.  
  763. /* +++++++++++++++ DO NOT USE THE FOLLOWING COLORS! +++++++++++++++++ */
  764.     screen.__SignOnColor = screen.__AttrOff || screen.__Highlight || ,
  765.                            screen.__fggreen || screen.__bgBlack
  766.  
  767.     screen.__PatchColor  = screen.__AttrOff || screen.__Highlight || ,
  768.                            screen.__fgcyan || screen.__bgRed
  769. /* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
  770.  
  771.                             /* set the default color                  */
  772.     screen.__CurColor    = screen.__NormalColor
  773.  
  774.                             /* turn ANSI word wrapping on             */
  775.     if prog.__QuietMode <> 1 then
  776.       call CharOut prog.__STDOUT, '1B'x || '[7h'
  777.  
  778.   end /* if 1 == global.__NeedColors then */
  779.  
  780. RETURN
  781.  
  782. /* ------------------------------------------------------------------ */
  783. /* function: init the stem prog.                                      */
  784. /*                                                                    */
  785. /* call:     I!.__InitProgStem                                        */
  786. /*                                                                    */
  787. /* returns:  nothing                                                  */
  788. /*                                                                    */
  789. /* Note:     DO NOT ADD ANY CODE TO THIS ROUTINE!                     */
  790. /*                                                                    */
  791. I!.__InitProgStem: /* PROCEDURE expose (exposeList) */
  792.   prog.__Defparms = ' {/L:logfile} {/H} {/Silent} {/NoAnsi} {/NoSound} {/Trace}'
  793.  
  794.                         /* get drive, path and name of this program   */
  795.   parse upper source . . prog.__FullName
  796.         prog.__Drive = filespec( 'D', prog.__FullName )
  797.          prog.__Path = filespec( 'P',  prog.__FullName )
  798.          prog.__Name = filespec( 'N',  prog.__FullName )
  799.  
  800.                                                              /* v3.05 */
  801.  parse upper value 'V3.06 1 80 25 OS2ENVIRONMENT' directory() with ,
  802.              prog.__Version ,         /* version of template    v3.05 */
  803.              prog.__UserAbort ,       /* allow useraborts       v3.05 */
  804.              prog.__ScreenCols ,      /* def. screen cols       v3.05 */
  805.              prog.__ScreenRows ,      /* def. screen rows       v3.05 */
  806.              prog.__env ,             /* def. environment       v3.05 */
  807.              prog.__CurDir            /* current directory      v3.05 */
  808.  
  809.                                 /* install a local error handler      */
  810.   SIGNAL ON SYNTAX Name I!.__InitProgStem1
  811.                                 /* try to call SysTextScreenSize()    */
  812.   parse value SysTextScreenSize() with prog.__ScreenRows prog.__ScreenCols
  813.  
  814. I!.__InitProgStem1:
  815.  
  816. RETURN
  817.  
  818. /* ------------------------------------------------------------------ */
  819. /* function: init the variables for CID programs (only if the value   */
  820. /*           of the variable global.__NeedCID is 1)                   */
  821. /*                                                                    */
  822. /* call:     I!.__InitCIDVars                                         */
  823. /*                                                                    */
  824. /* returns:  nothing                                                  */
  825. /*                                                                    */
  826. /* Note:     DO NOT ADD ANY CODE TO THIS ROUTINE!                     */
  827. /*           Returncodes as defined by LCU 2.0                        */
  828. /*                                                                    */
  829. I!.__InitCIDVars: /* PROCEDURE expose (exposeList) exposeList CIDRC. */
  830.  
  831.   if 1 == global.__NeedCID then
  832.   do
  833.  
  834.     I!.__cidRCValues = ,                                     /* v3.05 */
  835.       '0000'x 'SUCCESSFUL_PROGRAM_TERMINATION',              /* v3.05 */
  836.       '0004'x 'SUCCESSFUL_LOG_WARNING_MESSAGE',              /* v3.05 */
  837.       '0008'x 'SUCCESSFUL_LOG_ERROR_MESSAGE',                /* v3.05 */
  838.       '0012'x 'SUCCESSFUL_LOG_SEVERE_ERROR',                 /* v3.05 */
  839.       '0800'x 'DATA_RESOURCE_NOT_FOUND',                     /* v3.05 */
  840.       '0804'x 'DATA_RESOURCE_ALREADY_IN_USE',                /* v3.05 */
  841.       '0808'x 'DATA_RESOURCE_NOAUTHORIZATION',               /* v3.05 */
  842.       '0812'x 'DATA_PATH_NOT_FOUND',                         /* v3.05 */
  843.       '0816'x 'PRODUCT_NOT_CONFIGURED',                      /* v3.05 */
  844.       '1200'x 'STORAGE_MEDIUM_EXCEPTION',                    /* v3.05 */
  845.       '1204'x 'DEVICE_NOT_READY',                            /* v3.05 */
  846.       '1208'x 'NOT_ENOUGH_DISKSPACE',                        /* v3.05 */
  847.       '1600'x 'INCORRECT_PROGRAM_INVOCATION',                /* v3.05 */
  848.       '1604'x 'UNEXPECTED_CONDITION',                        /* v3.05 */
  849.       'FE00'x 'SUCCESSFULL_REBOOT',                          /* v3.05 */
  850.       'FE04'x 'SUCCESSFULL_REBOOT_WITH_WARNING',             /* v3.05 */
  851.       'FE08'x 'SUCCESSFULL_REBOOT_WITH_ERRMSG',              /* v3.05 */
  852.       'FE12'x 'SUCCESSFULL_REBOOT_WITH_SERVER_ERRMSG',       /* v3.05 */
  853.                                                              /* v3.05 */
  854.     do i = 1 to words( I!.__cidRCValues ) by 2               /* v3.05 */
  855.       call value 'CIDRC.__' || word( I!.__cidRCValues,i+1 ),,
  856.                  c2d( word( I!.__cidRCValues,i ),2 )         /* v3.05 */
  857.                                                              /* v3.05 */
  858.     end /* do i = 1 to words( I!.__cidRCValues ) by 2 */     /* v3.05 */
  859.                                                              /* v3.05 */
  860.     drop I!.__cidRCValues                                    /* v3.05 */
  861.  
  862.  
  863.                         /* xx = next state of the program             */
  864. /*    CIDRC.__successfull_reboot_with_callback = C2D('FFxx'x, 2);     */
  865.  
  866.                         /* define exit code values                    */
  867.     global.__ErrorExitCode = CIDRC.__unexpected_condition
  868.        global.__OKExitCode = CIDRC.__successful_program_termination
  869.  
  870.                         /* add the stem CIDRC. to the exposeList      */
  871.     exposeList = exposeList 'CIDRC. '
  872.   end /* if 1 == global.__NeedCID then */
  873.  
  874. RETURN
  875.  
  876.  
  877. /***        End of Part 2 of the source code of TEMPLATE.CMD        ***/
  878.  
  879. /***       Start of Part 3 of the source code of TEMPLATE.CMD       ***/
  880.  
  881. /* ------------------------------------------------------------------ */
  882. /* function:  load a dll                                              */
  883. /*                                                                    */
  884. /* call:                                                              */
  885. /*   thisRC = LoadDll( registerFunction, dllName, entryPoint,         */
  886. /*                     ,{deRegisterFunction},{checkFunction}          */
  887. /*                     ,{IgnoreRxFuncAddRC},{RegisterErrorRC}         */
  888. /*                     ,{errorAction}                                 */
  889. /*                                                                    */
  890. /* where:                                                             */
  891. /*         registerFunc = name of the dll init function               */
  892. /*                        (e.g. "SysLoadFuncs")                       */
  893. /*              dllName = name of the dll                             */
  894. /*                        (e.g. "REXXUTIL")                           */
  895. /*           entryPoint = entryPoint for the dll init function        */
  896. /*                        (e.g. "SysLoadFuncs")                       */
  897. /*       deRegisterFunc = name of the dll exit function               */
  898. /*                        (e.g. "SysDropFuncs")                       */
  899. /*                        If this parameter is entered, the           */
  900. /*                        deRegisterFunction is automaticly called    */
  901. /*                        at program end if the loading of the dll    */
  902. /*                        was successfull.                            */
  903. /*            checkFunc = function which must be loaded if the dll is */
  904. /*                        loaded (def.: none -> always load the dll)  */
  905. /*                        Note:                                       */
  906. /*                        Do not use the registerFunction for this    */
  907. /*                        parameter! A good candidate for this        */
  908. /*                        parameter is the deRegisterFunction.        */
  909. /*    IgnoreRxFuncAddRC = 1: ignore the rc from rxFuncAdd             */
  910. /*                        0: do not ignore the rc from rxFuncAdd      */
  911. /*                        (def.: 0)                                   */
  912. /*                        Note: Always set this parameter to 1 if     */
  913. /*                              using the program under WARP.         */
  914. /*       RegisterErroRC = returncode of the dll init function         */
  915. /*                        indicating a load error                     */
  916. /*                        (def. none, -> ignore the returncode of the */
  917. /*                         dll init function)                         */
  918. /*           actionCode = 1: abort program if loading failed          */
  919. /*                        0: do not abort program if loading failed   */
  920. /*                        (def.: 1)                                   */
  921. /*                                                                    */
  922. /* returns:                                                           */
  923. /*   0 - loading failed                                               */
  924. /*   1 - dll loaded                                                   */
  925. /*   2 - dll already loaded                                           */
  926. /*                                                                    */
  927. /* Note:                                                              */
  928. /*   See the routine MAIN for some examples for using LoadDLL.        */
  929. /*   LoadDLL can only handle dlls with an init function to register   */
  930. /*   the further routines in the dll (like the function SysLoadFuncs  */
  931. /*   in the dll REXXUTIL).                                            */
  932. /*                                                                    */
  933. LoadDll:  PROCEDURE expose (exposeList)
  934.   parse arg regFunc , ,
  935.             dllName , ,
  936.             entryPoint , ,
  937.             deregFunc , ,
  938.             checkFunc , ,
  939.             ignoreRXFuncAddRC, ,
  940.             registerErrorRC, ,
  941.             errorAction
  942.  
  943.                         /* check the necessary parameters             */
  944.   if '' == entryPoint | '' == dllName | '' == regFunc then
  945.     call ShowError global.__ErrorExitCode, I!.__GetMsg( 6 )
  946.  
  947.   if '' == ignoreRXFuncAddRC then
  948.     ignoreRXFuncAddRc = 0
  949.  
  950.   if '' == errorAction then
  951.     errorAction = 1
  952.  
  953.   I!.__LoadDLLRc = 0
  954.                         /* if the 'checkFunc' is missing, we          */
  955.                         /* assume that the dll is not loaded          */
  956.   dllNotLoaded = 1
  957.   if ( checkFunc <> '' ) then
  958.     dllNotLoaded = rxFuncQuery( checkFunc )
  959.  
  960.   if dllNotLoaded then
  961.   do
  962.                         /* first deRegister the function        v3.01 */
  963.     call rxFuncDrop regFunc                                  /* v3.01 */
  964.  
  965.                         /* load the dll and register the init         */
  966.                         /* function of the dll                        */
  967.     rxFuncAddRC = rxFuncAdd( regFunc, dllName, entryPoint )
  968.  
  969.     if \ rxFuncAddRC | ignoreRxFuncAddRC then
  970.     do
  971.  
  972.       I!.__DllInitRC = 0
  973.       if I!.__CallUserProc( 0, regFunc ) == 0 then
  974.         I!.__DllInitRC = 'ERROR'
  975.  
  976.       if ( registerErrorRC <> '' & I!.__DLLInitRC == registerErrorRC ) | ,
  977.          ( I!.__DllInitRC == 'ERROR' ) then
  978.         nop
  979.       else
  980.       do
  981.                         /* add the dll deregister function to the     */
  982.                         /* program exit routine list                  */
  983.         if DeregFunc <> '' then
  984.           if \ rxFuncQuery( DeregFunc ) then
  985.             prog.__ExitRoutines = prog.__ExitRoutines || ' ' || ,
  986.                                   DeregFunc
  987.  
  988.         I!.__LoadDLLRc = 1
  989.       end /* else */
  990.     end /* if \ rxFuncAddRC | ignoreRxFuncAddRC then */
  991.   end /* if dllNotLoaded then */
  992.   else
  993.     I!.__LoadDLLRc = 2  /* dll is already loaded                      */
  994.  
  995.   if 1 == errorAction & 0 == I!.__LoadDLLRC then
  996.     call ShowError global.__ErrorExitCode,,
  997.                    I!.__GetMsg( 5, dllName )
  998.  
  999. RETURN I!.__LoadDLLRc
  1000.  
  1001. /* ------------------------------------------------------------------ */
  1002. /* function: show a string with word wrapping                         */
  1003. /*                                                                    */
  1004. /* call:     showString Prefix, thisString                            */
  1005. /*                                                                    */
  1006. /* where:                                                             */
  1007. /*           Prefix = prefix for the first line (e.g. "*-*" or "#" to */
  1008. /*                    use # leading blanks, # = 1 ... n )             */
  1009. /*           thisString - string to print                             */
  1010. /*                                                                    */
  1011. /* returns:  ''                                                       */
  1012. /*                                                                    */
  1013. ShowString: PROCEDURE EXPOSE (exposeList)
  1014.   parse arg Prefix, thisStr
  1015.  
  1016.   maxLineL = prog.__ScreenCols-4
  1017.  
  1018.   if datatype( prefix, 'W' ) == 1 then
  1019.     prefix = copies( ' ' , prefix )
  1020.  
  1021.   maxWordL = maxLineL - length( prefix )
  1022.  
  1023.   thisRC = 0
  1024.   curStr = ''
  1025.  
  1026.   do i = 1 to words( thisStr)
  1027.     pStr = 0
  1028.  
  1029.     curStr = curStr || word( thisStr, i ) || ' '
  1030.  
  1031.     if length( curStr || prefix ||  word( thisStr, i+1 ) ) > maxLineL then
  1032.       pStr = 1
  1033.  
  1034.     if 1 == pStr | i == words( thisStr ) then
  1035.     do
  1036.       if length( prefix || curStr ) > prog.__ScreenCols then
  1037.       do until curStr = ''
  1038.         parse var curStr curStr1 =(maxWordL) ,
  1039.                                   curStr
  1040.         call log left( prefix || curStr1, prog.__ScreenCols )
  1041.         prefix = copies( ' ', length( prefix ) )
  1042.       end /* if length( ... then do until */
  1043.       else
  1044.         call Log left( prefix || curStr, prog.__ScreenCols )
  1045.  
  1046.       curStr = ''
  1047.       prefix = copies( ' ', length( prefix ) )
  1048.     end /* if 1 == pStr | ... */
  1049.  
  1050.   end /* do i = 1 to words( thisStr */
  1051.  
  1052. RETURN ' '                                                   /* v3.03 */
  1053.  
  1054. /* ------------------------------------------------------------------ */
  1055. /* function: show a warning message                                   */
  1056. /*                                                                    */
  1057. /* call:     showWarning message                                      */
  1058. /*                                                                    */
  1059. /* where:    warningMessage - warning Message                         */
  1060. /*                                                                    */
  1061. /* returns:  ''                                                       */
  1062. /*                                                                    */
  1063. ShowWarning: PROCEDURE expose (exposeList)
  1064.   parse arg wMsg
  1065.  
  1066.   screen.__CurColor = screen.__ErrorColor
  1067.  
  1068.   call I!.__LogStart
  1069.  
  1070.   call ShowString I!.__GetMsg( 7 ) || ' ', wMsg || '!'
  1071.   call I!.__LogSeparator
  1072.  
  1073.   screen.__CurColor = screen.__NormalColor
  1074.   call Log
  1075.  
  1076. RETURN ' '                                                   /* v3.03 */
  1077.  
  1078. /* ------------------------------------------------------------------ */
  1079. /* function: show an error message and end the program                */
  1080. /*                                                                    */
  1081. /* call:     ShowError exitCode, errorMessage                         */
  1082. /*                                                                    */
  1083. /* where:    ExitCode - no of the error (= program exit code)         */
  1084. /*           errorMessage - error Message                             */
  1085. /*                                                                    */
  1086. /* returns:  nothing                                                  */
  1087. /*                                                                    */
  1088. /* Note:     THIS ROUTINE WILL NOT COME BACK!!!                       */
  1089. /*                                                                    */
  1090. ShowError: PROCEDURE expose (exposeList)
  1091.   parse arg prog.__ExitCode, I!.__errMsg
  1092.  
  1093.   I!.__QM = prog.__QuietMode
  1094.                         /* turn quiet mode off                        */
  1095.   prog.__QuietMode = ''
  1096.  
  1097.   screen.__CurColor = screen.__ErrorColor
  1098.  
  1099.   call I!.__LogStart
  1100.  
  1101.   call Log left( I!.__GetMsg( 8, prog.__Name , prog.__ExitCode ) ,,
  1102.                  prog.__ScreenCols )
  1103.   call ShowString 1, I!.__errMsg || '!'
  1104.  
  1105.   call I!.__LogSeparator
  1106.   call Log
  1107.                         /* restore quiet mode status                  */
  1108.   prog.__QuietMode = I!.__QM
  1109.  
  1110.   if prog.__NoSound <> 1 then
  1111.   do
  1112.     call beep 537,300
  1113.     call beep 237,300
  1114.     call beep 537,300
  1115.   end /* if prog.__NoSound <> 1 then */
  1116.  
  1117. SIGNAL I!.__ProgramEnd
  1118.  
  1119. RETURN
  1120.  
  1121. /* ------------------------------------------------------------------ */
  1122. /* function: log a debug message and clear the rest of the line       */
  1123. /*                                                                    */
  1124. /* call:     logDebugMsg message                                      */
  1125. /*                                                                    */
  1126. /* where:    message - message to show                                */
  1127. /*                                                                    */
  1128. /* returns:  ''                                                       */
  1129. /*                                                                    */
  1130. /* Note:     You do not need the 'call' keyword to use this routine.  */
  1131. /*                                                                    */
  1132. LogDebugMsg: PROCEDURE expose (exposeList)
  1133.   if global.__verbose <> '' then
  1134.   do
  1135.     parse arg dMsg
  1136.     screen.__CurColor = screen.__DebugColor
  1137.     call Log '+++' dMsg
  1138.     screen.__CurColor = screen.__NormalColor
  1139.   end /* if global.__verbose <> '' then */
  1140. RETURN ' '                                                   /* v3.03 */
  1141.  
  1142. /* ------------------------------------------------------------------ */
  1143. /* function: write a CR/LF and a separator line to the screen and to  */
  1144. /*           the logfile                                              */
  1145. /*                                                                    */
  1146. /* call:     I!.__LogStart                                            */
  1147. /*                                                                    */
  1148. /* returns:  nothing                                                  */
  1149. /*                                                                    */
  1150.  
  1151. /* ------------------------------------------------------------------ */
  1152. /* function: write a separator line to the screen and to the logfile  */
  1153. /*                                                                    */
  1154. /* call:     I!.__LogSeparator                                        */
  1155. /*                                                                    */
  1156. /* returns:  nothing                                                  */
  1157. /*                                                                    */
  1158. I!.__LogStart:
  1159.   call log
  1160. I!.__LogSeparator:
  1161.   call Log ' ' || left('-', prog.__ScreenCols-2, '-' ) || ' '
  1162. RETURN
  1163.  
  1164. /* ------------------------------------------------------------------ */
  1165. /* function: log a message and clear the rest of the line             */
  1166. /*                                                                    */
  1167. /* call:     log message                                              */
  1168. /*                                                                    */
  1169. /* where:    message - message to show                                */
  1170. /*                                                                    */
  1171. /* returns:  ''                                                       */
  1172. /*                                                                    */
  1173. /* Note:     You do not need the 'call' keyword to use this routine.  */
  1174. /*                                                                    */
  1175. Log: PROCEDURE expose (exposeList)
  1176.   parse arg msg
  1177.  
  1178.   logmsg = msg
  1179.   do i = 1 to words( prog.__LogExcludeWords )
  1180.     curWord = word( prog.__LogExcludeWords, i )
  1181.    
  1182.     do until j = 0
  1183.       j = Pos( curWord, logmsg )
  1184.       if j <> 0 then
  1185.         logmsg = delstr( logmsg, j, length( curWord ) )
  1186.     end /* do until j = 0 */
  1187.   end /* do i = 1 to words( prog.__LogExcludeWords ) */
  1188.  
  1189.   if prog.__QuietMode <> 1 then
  1190.   do
  1191.  
  1192.     if length( logmsg ) == prog.__ScreenCols  then
  1193.       call charout prog.__STDOUT, screen.__CurColor || ,
  1194.                                   msg || screen.__AttrOff
  1195.     else
  1196.       call lineOut prog.__STDOUT, screen.__CurColor || ,
  1197.                                   msg || screen.__AttrOff ||,
  1198.                                   screen.__DelEOL
  1199.  
  1200.   end /* if prog.__Quietmode <> 1 then */
  1201.  
  1202.   if symbol( 'prog.__LogFile' ) == 'VAR' then
  1203.     if prog.__LogFile <> '' then
  1204.     do
  1205.       call lineout prog.__LogFile, logmsg
  1206.  
  1207.                                 /* close the logfile                  */
  1208.       call stream prog.__LogFile, 'c', 'CLOSE'
  1209.     end /* if prog.__LogFile <> '' then */
  1210.  
  1211. RETURN ' '                                                   /* v3.03 */
  1212.  
  1213. /* ------------------------------------------------------------------ */
  1214. /* function: check if there is a patched version of this program      */
  1215. /*                                                                    */
  1216. /* call:     I!.__CheckPatch                                          */
  1217. /*                                                                    */
  1218. /* returns:  nothing                                                  */
  1219. /*                                                                    */
  1220. /* Note:     I!.__RealParam must contain the parameters for           */
  1221. /*           this program.                                            */
  1222. /*           The variables prog.__Path and prog.__Name must be set!   */
  1223. /*           This procedure ends the program with an EXIT command!    */
  1224. /*                                                                    */
  1225. I!.__CheckPatch: PROCEDURE expose (exposeList)
  1226.  
  1227.                         /* get the drive with patch cmd files         */
  1228.                         /*                                      v3.04 */
  1229.   parse upper value value( 'PATCHDRIVE',, prog.__env ) with pLW
  1230.  
  1231.   if global.__NeedPatchCheck <> 0 & ( pLW <> '' & pLW <> prog.__Drive ) then
  1232.   do
  1233.  
  1234.     pVer = pLW || prog.__Path || prog.__Name
  1235.  
  1236.                         /* check if a patched program version exists  */
  1237.     if stream( pVer, 'c', 'QUERY EXIST' ) <> '' then
  1238.     do
  1239.       pCmd = pVer || ' ' || I!.__RealParam
  1240.  
  1241.       screen.__CurColor = screen.__PatchColor
  1242.       call Log left( I!.__GetMsg( 9, pver ), prog.__ScreenCols )
  1243.       screen.__CurColor = screen.__AttrOff
  1244.       call I!.__LogSeparator
  1245.  
  1246.       '@cmd /c ' pCmd
  1247.  
  1248.       screen.__CurColor = screen.__AttrOff
  1249.       call I!.__LogSeparator
  1250.       screen.__CurColor = screen.__PatchColor
  1251.       call Log left( I!.__GetMsg( 10, rc ), prog.__ScreenCols )
  1252.  
  1253.       exit rc
  1254.     end /* if stream( ... */
  1255.   end /* if pLW <> '' */
  1256. RETURN
  1257.  
  1258. /* ------------------------------------------------------------------ */
  1259. /* function: error handler for unexpected errors                      */
  1260. /*                                                                    */
  1261. /* call:     DO NOT CALL THIS ROUTINE BY HAND!!!                      */
  1262. /*                                                                    */
  1263. /* returns:  nothing                                                  */
  1264. /*                                                                    */
  1265. /* input:    I!.__IncActive:                                          */
  1266. /*             if 1 the error occured while executing an include file */
  1267. /*             statement. In this case the following variables are    */
  1268. /*             also used (Note that this variables are automaticly    */
  1269. /*             set by the routine INCLUDE()):                         */
  1270. /*               I!.__IncLineNo                                       */
  1271. /*                 Line no. of the include file                       */
  1272. /*               I!.__IncFileName:                                    */
  1273. /*                 Name of the include file                           */
  1274. /*               I!.__IncCurLinePos:                                  */
  1275. /*                 Fileposition of the first char of the line causing */
  1276. /*                 the error                                          */
  1277. /*                                                                    */
  1278. /* Note:     THIS FUNCTION ABORTS THE PROGRAM WITH A JUMP TO THE      */
  1279. /*           LABEL I!.__PROGRAMEND!!!                                 */
  1280. /*                                                                    */
  1281. I!.__ErrorAbort:
  1282.  
  1283.                             /* turn ANSI word wrap on                 */   
  1284.   if screen.__CurColor <> '' then
  1285.     call CharOut prog.__STDOUT, '1B'x || '[7h'
  1286.  
  1287.                         /* check if the error occured in the error    */
  1288.                         /* handler                                    */
  1289.   if I!.__errorLineNo == sigl then
  1290.   do
  1291.     call charout 'STDERR:',,
  1292.                                                             '0D0A'x  ,
  1293.        'Fatal Error: Error in the error handler detected!'  '0D0A'x  ,
  1294.                                                             '0D0A'x  ,
  1295.        'Linenumber:       ' || sigl                         '0D0A'x  ,
  1296.        'Errorname:        ' || condition('C')               '0D0A'x  ,
  1297.        'Errordescription: ' || condition('D')               '0D0A'x  ,
  1298.                                                             '0D0A'x  ,
  1299.        'The program exit routines were not called!'         '0D0A'x  ,
  1300.        'Check if "(EXPOSELIST)" is included in the ' || ,
  1301.        'expose lists of all procedures!'                    '0D0A'x
  1302.  
  1303.     call beep 637,300 ; call beep 437,300 ; call beep 637,300
  1304.     exit 255
  1305.  
  1306.   end /* if I!.__errorLineNo == sigl then */
  1307.  
  1308.                         /* get the number of the line causing the     */
  1309.                         /* error                                      */
  1310.   I!.__errorLineNo = sigl
  1311.  
  1312.                         /* get the name of this error                 */
  1313.   I!.__ErrorName = condition('C')
  1314.  
  1315.                         /* get further information for this error     */
  1316.                         /* if available                               */
  1317.   I!.__ErrorCondition = condition('D')
  1318.   if I!.__ErrorCondition <> '' then
  1319.     I!.__ErrorCondition = ' (Desc.: "' || I!.__ErrorCondition || '")'
  1320.  
  1321.   if datatype( prog.__ScreenCols, 'W' ) <> 1 then
  1322.     prog.__ScreenCols = 80
  1323.  
  1324.   if SYMBOL( 'prog.__Name' ) <> 'VAR' | value( 'prog.__Name' ) == '' then
  1325.     if I!.__errorLineNO < I!.__FirstUserCodeLine then
  1326.       I!.__pName = '**Runtime**'
  1327.     else
  1328.       I!.__pName = '***???***'
  1329.   else
  1330.     i!.__pName = prog.__Name
  1331.  
  1332.                         /* reInstall the error handler                */
  1333.   INTERPRET  'SIGNAL ON ' value(condition('C')) ' NAME I!.__ErrorAbort'
  1334.  
  1335.                         /* check, if we should ignore the error       */
  1336.   if value( 'sigl' ) == value( 'I!.__ICmdLine' ) then
  1337.   do
  1338.     I!.__errorLineNo = 0
  1339.     SIGNAL I!.__CallUserProc2
  1340.   end /* if value( ... */
  1341.  
  1342.   screen.__CurColor = screen.__ErrorColor
  1343.  
  1344.   I!.__QM = prog.__QuietMode
  1345.                         /* turn quiet mode off                        */
  1346.   prog.__QuietMode = ''
  1347.  
  1348.                         /* init variables for printing the line       */
  1349.                         /* causing the error to the screen            */
  1350.   I!.__ThisSRCLine = ''
  1351.   I!.__ThisPrefix = ' *-* '
  1352.  
  1353.   call I!.__LogStart
  1354.  
  1355.   call ShowString ' ' || I!.__pName || ' - ', I!.__ErrorName || ,
  1356.                   I!.__ErrorCondition || ' error detected!'
  1357.  
  1358.                         /* check, if the RC is meaningfull for this   */
  1359.                         /* error                                      */
  1360.   if pos( I!.__ErrorName, 'ERROR FAILURE SYNTAX' ) <> 0 then
  1361.   do
  1362.     if datatype(rc, 'W' ) == 1 then
  1363.       if 'SYNTAX' == I!.__ErrorName then
  1364.          if rc > 0 & rc < 100 then
  1365.             call Log left( ' The error code is ' || rc || ,
  1366.                            ', the REXX error message is: ' || ,
  1367.                            errorText( rc ), ,
  1368.                            prog.__ScreenCols )
  1369.          else
  1370.            call log left( ' The error code is ' || rc || ,
  1371.                           ', this error code is unknown.',,
  1372.                           prog.__ScreenCols )
  1373.       else
  1374.         call Log left( ' The RC is ' || rc || '.', prog.__ScreenCols )
  1375.   end /* if pos( ... */
  1376.  
  1377.   if value( 'I!.__IncActive' ) == 1 then
  1378.   do
  1379.                 /* error occured while interpreting an include file   */
  1380.     call ShowString 1, 'The error occured while executing the line ' || ,
  1381.                        I!.__IncLineNo || ' of the include file "' || ,
  1382.                        I!.__IncFileName || '".'
  1383.  
  1384.                         /* reset the file pointer of the include file */
  1385.                         /* to the start of the line causing the error */
  1386.     call stream I!.__IncFileName, 'c', 'SEEK =' || ,
  1387.                                                    I!.__IncCurLinePos
  1388.  
  1389.     I!.__SrcAvailable = stream( I!.__IncFileName, ,
  1390.                                    'c', 'QUERY EXIST' ) <> ''
  1391.   end
  1392.   else
  1393.   do
  1394.     call ShowString 1, 'The error occured in line ' ||,
  1395.                        I!.__errorLineNo || '.'
  1396.  
  1397.     I!.__thisLineNo = I!.__errorLineNo
  1398.  
  1399.                 /* error occured in this file                         */
  1400.                 /* check if the sourcecode is available               */
  1401.     SIGNAL ON SYNTAX   NAME I!.__NoSourceCode
  1402.     I!.__inMacroSpace = 1
  1403.     I!.__SrcAvailable = 0
  1404.     if sourceLine( I!.__errorLineNo ) <> '' then
  1405.       I!.__SrcAvailable = 1
  1406.  
  1407.     SIGNAL ON SYNTAX NAME I!.__ErrorAbort
  1408.     I!.__inMacroSpace = 0
  1409.  
  1410.   end /* else */
  1411.  
  1412.                         /* print the statement causing the error to   */
  1413.                         /* the screen                                 */
  1414.   if 1 == I!.__SrcAvailable then
  1415.   do
  1416.     call Log left( ' The line reads: ', prog.__ScreenCols )
  1417.     I!.__InterpretVar = 0
  1418.  
  1419.                 /* read the line causing the error                    */
  1420.     call I!.__GetSourceLine
  1421.  
  1422.     I!.__FirstToken = strip(word( I!.__ThisSRCLine,1))
  1423.     if translate( I!.__FirstToken ) == 'INTERPRET' then
  1424.     do
  1425.       parse var I!.__ThisSRCLine (I!.__FirstToken) ,
  1426.                 I!.__interpretValue
  1427.       I!.__InterpretVar = 1
  1428.     end /* if I!.__thisLineNo = I!.__errorLineNo */
  1429.  
  1430.                         /* handle multi line statements               */
  1431.     do forever
  1432.       call ShowString I!.__ThisPrefix, I!.__ThisSRCLine
  1433.  
  1434.       if right( strip( I!.__ThisSRCLine),1 ) <> ',' then
  1435.         leave
  1436.  
  1437.       I!.__ThisPrefix = 5
  1438.  
  1439.       call I!.__GetSourceLine
  1440.     end /* do forever */
  1441.  
  1442.     if 1 == I!.__InterpretVar then
  1443.     do
  1444.       I!.__interpretValue = strip( word(I!.__interpretValue,1) )
  1445.  
  1446.       if symbol( I!.__interpretValue ) == 'VAR' then
  1447.       do
  1448.         call Log left( '', prog.__ScreenCols )
  1449.         call Log left( ' The value of "' || I!.__interpretValue || ,
  1450.                        '" is:', prog.__ScreenCols )
  1451.         call ShowString ' >V> ', value( I!.__interpretValue )
  1452.       end /* if symbol( I!.__interpretValue ) = 'VAR' then */
  1453.  
  1454.     end /* if 1 == I!.__InterpretVar */
  1455.  
  1456.   end /* if 1 == I!.__SrcAvailable  then do */
  1457.   else
  1458.     call Log left( ' The sourcecode for this line is not available',,
  1459.                    prog.__ScreenCols )
  1460.  
  1461. I!.__NoSourceCode:
  1462.   SIGNAL ON SYNTAX NAME I!.__ErrorAbort
  1463.  
  1464.   if 1 == I!.__inMacroSpace then
  1465.   do
  1466.     parse source . . I!.__thisProgName
  1467.  
  1468.     if fileSpec( 'D', I!.__thisProgName ) == '' then
  1469.       call ShowString 1, ' The sourcecode for this line is not' || ,
  1470.                          ' available because the program is in' || ,
  1471.                          ' the macro space.'
  1472.     else
  1473.       call ShowString 1, ' The sourcecode for this line is not' || ,
  1474.                          ' available because the program is unreadable.'
  1475.   end /* if 1 == I!.__inMacroSpace then */
  1476.  
  1477.   call I!.__LogSeparator
  1478.   call Log
  1479.  
  1480.   prog.__ExitCode = global.__ErrorExitCode
  1481.  
  1482.   if prog.__NoSound <> 1 then
  1483.   do
  1484.     call beep 137,300;  call beep 337,300;  call beep 137,300
  1485.   end /* if prog.__NoSound <> 1 then */
  1486.  
  1487.   if 'DEBUG' == global.__verbose | prog.__Trace = 1 then
  1488.   do
  1489.                         /* enter interactive debug mode               */
  1490.     trace ?a
  1491.     nop
  1492.   end /* if 'DEBUG' == global.__verbose | ... */
  1493.  
  1494.                         /* restore quiet mode status                  */
  1495.   prog.__QuietMode = I!.__QM
  1496.  
  1497. SIGNAL I!.__programEnd
  1498.  
  1499. /* ------------------------------------------------------------------ */
  1500. /* function: get the sourceline causing an error (subroutine of       */
  1501. /*           I!.__ErrorAbort)                                         */
  1502. /*                                                                    */
  1503. /* call:     DO NOT CALL THIS IN YOUR CODE!!!                         */
  1504. /*                                                                    */
  1505. /* returns:  nothing                                                  */
  1506. /*                                                                    */
  1507. /* Note:     -                                                        */
  1508. /*                                                                    */
  1509. I!.__GetSourceLine:
  1510.   if 1 == I!.__IncActive then
  1511.     I!.__ThisSRCLine = lineIn( I!.__IncFileName )
  1512.   else
  1513.   do
  1514.     I!.__ThisSRCLine = sourceLine( I!.__ThisLineNo )
  1515.     I!.__ThisLineNo = I!.__ThisLineNo + 1
  1516.   end /* else */
  1517. RETURN
  1518.  
  1519. /* ------------------------------------------------------------------ */
  1520. /* function: error handler for user breaks                            */
  1521. /*                                                                    */
  1522. /* call:     DO NOT CALL THIS ROUTINE BY HAND!!!                      */
  1523. /*                                                                    */
  1524. /* returns:  nothing                                                  */
  1525. /*                                                                    */
  1526. /* Note:     THIS FUNCTION ABORTS THE PROGRAM WITH A JUMP TO THE      */
  1527. /*           LABEL I!.__PROGRAMEND IF prog.__UserAbort IS NOT 0!!!    */
  1528. /*                                                                    */
  1529. /*           In exit routines you may test if the variable            */
  1530. /*           prog.__ExitCode is 254 to check if the program           */
  1531. /*           was aborted by the user.                                 */
  1532. /*                                                                    */
  1533. I!.__UserAbort:
  1534.   I!.__sSigl = sigl
  1535.  
  1536.                         /* reinstall the error handler                */
  1537.   CALL ON HALT NAME I!.__UserAbort
  1538.  
  1539.                         /* check if user aborts are allowed           */
  1540.   if 0 == prog.__UserAbort then
  1541.     RETURN              /* CTRL-BREAK not allowed                     */
  1542.  
  1543.   I!.__QM = prog.__QuietMode
  1544.  
  1545.                         /* turn quiet mode off                        */
  1546.   prog.__QuietMode = ''
  1547.  
  1548.   call Log
  1549.  
  1550.   screen.__CurColor = screen.__ErrorColor
  1551.   call I!.__LogSeparator
  1552.   call Log left( I!.__GetMsg( 11, I!.__sSigl ), prog.__ScreenCols )
  1553.   call I!.__LogSeparator
  1554.   screen.__CurColor = screen.__NormalColor
  1555.  
  1556.   prog.__ExitCode = 254
  1557.  
  1558.                         /* restore quiet mode status                  */
  1559.   prog.__QuietMode = I!.__QM
  1560.  
  1561. SIGNAL I!.__ProgramEnd
  1562.  
  1563. /* ------------------------------------------------------------------ */
  1564. /* function: get a message                                            */
  1565. /*                                                                    */
  1566. /* call:     I!.__GetMsg msgNo {,msgP1} {...,msgP9}                   */
  1567. /*                                                                    */
  1568. /* returns:  the message or an empty string                           */
  1569. /*                                                                    */
  1570. /* note:     This routines calls the external routine which name is   */
  1571. /*           saved in the variable 'global.__GetMsg' if this variable */
  1572. /*           is not equal ''.                                         */
  1573. /*                                                                    */
  1574. /*           I!.__GetMsg adds global.__BaseMsgNo to the msgNo.        */
  1575. /*                                                                    */
  1576. I!.__GetMsg: PROCEDURE expose (exposeList)
  1577.   parse arg msgNo, mP1 , mP2 , mP3, mP4, mP5, mP6, mP7, mP8, mP9
  1578.  
  1579.   f = 0
  1580.   t = ''
  1581.  
  1582.   if symbol( 'global.__GetMsg' ) = 'VAR' then
  1583.     if global.__GetMsg <> '' then
  1584.     do
  1585.             /* first check if there's a user defined GetMsg routine   */
  1586.  
  1587.                         /* install a local error handler              */
  1588.       SIGNAL ON SYNTAX Name I!.__GetMsg1
  1589.  
  1590.                     /* try to call the user defined GetMsg routine    */
  1591.       interpret 'call ' global.__GetMsg ' msgNo+global.__BaseMsgNo,,' ,
  1592.                 ' mP1, mP2, mP3, mP4, mP5, mP6, mP7, mP8, mP9 '
  1593.       f = 1
  1594.     end /* if global.__GetMsg <> '' then */
  1595.  
  1596. I!.__GetMsg1:
  1597.  
  1598.   if f = 1 then
  1599.   do
  1600.                         /* user defined GetMsg routine found -- use   */
  1601.                         /* the result                                 */
  1602.     if symbol( 'RESULT' ) == 'VAR' then
  1603.       t = result
  1604.   end /* if result = 0 then */
  1605.   else
  1606.   do
  1607.                         /* user defined GetMsg routine not found --   */
  1608.                         /* use the hardcoded message strings          */
  1609.       msgString =  ,
  1610. /* 1001 */      'Routine_"@1"_not_found',
  1611. /* 1002 */      'Can_not_write_to_the_logfile_"@1",_the_status_of_the_logfile_is_"@2"._Now_using_the_NUL_device_for_logging',
  1612. /* 1003 */      'Include_file_"@1"_not_found' ,
  1613. /* 1004 */      'Unexpected_EOF_detected_while_reading_the_include_file_"@1"' ,
  1614. /* 1005 */      'Error_loading_the_DLL_"@1"' ,
  1615. /* 1006 */      'Invalid_call_to_LOADDLL' ,
  1616. /* 1007 */      '_Warning:' ,
  1617. /* 1008 */      '_@1_-_Error_@2_detected!_The_error_message_is_',
  1618. /* 1009 */      '_Calling_the_patched_version_@1_...' ,
  1619. /* 1010 */      '_..._the_patched_version_endet_with_RC_=_@1' ,
  1620. /* 1011 */      '_Program_aborted_by_the_user_(sigl=@1)' ,
  1621. /* 1012 */      '@1_@2_started_on_@3_at_@4_...' ,
  1622. /* 1013 */      '@1_@2_ended_on_@3_at_@4_with_RC_=_@5_(=''@6''x)' ,
  1623. /* 1014 */      '_Usage:'
  1624.  
  1625.                     /* get the message and translate all underscores  */
  1626.                     /* to blanks                                      */
  1627.     t = translate( word( msgString, msgNo ), ' ', '_'  )
  1628.  
  1629.                     /* replace place holder                           */
  1630.     i = 1
  1631.     do until i > 9
  1632.      j = pos( '@' || i, t )
  1633.      if j <> 0 then
  1634.        t = insert( arg( i+1 ), delStr(t, j, 2) , j-1 )
  1635.      else
  1636.        i = i +1
  1637.     end /* do until i > 9 */
  1638.   end /* else */
  1639. return t
  1640.  
  1641. /* ------------------------------------------------------------------ */
  1642. /* function: get the line no of the call statement of this routine    */
  1643. /*                                                                    */
  1644. /* call:     GetLineNo                                                */
  1645. /*                                                                    */
  1646. /* returns:  the line number                                          */
  1647. /*                                                                    */
  1648. /*                                                                    */
  1649. GetLineNo:
  1650.   RETURN sigl
  1651.  
  1652. /* ------------------------------------------------------------------ */
  1653. /* function: get the no. of the first line with the user code         */
  1654. /*                                                                    */
  1655. /* call:     DO NOT CALL THIS ROUTINE BY HAND!!!                      */
  1656. /*                                                                    */
  1657. /* returns:  nothing                                                  */
  1658. /*                                                                    */
  1659. /*                                                                    */
  1660. I!.__GetUserCode:
  1661.   I!.__FirstUserCodeLine = GetLineNo()+2
  1662. RETURN
  1663.  
  1664. /********************** End of Runtime Routines ***********************/
  1665. /**********************************************************************/
  1666.  
  1667. /***        End of Part 3 of the source code of TEMPLATE.CMD        ***/
  1668.  
  1669. /***       Start of Part 4 of the source code of TEMPLATE.CMD       ***/
  1670.                                                                    /*!*/
  1671.  
  1672. /* ------------------------------------------------------------------ */
  1673. /* function: main procedure of the program                            */
  1674. /*                                                                    */
  1675. /* call:     called by the runtime system with:                       */
  1676. /*           => call main parameter_of_the_program <=                 */
  1677. /*                                                                    */
  1678. /* returns:  program return code                                      */
  1679. /*           If no return code is returned, the value of the variable */
  1680. /*           prog.__ExitCode is returned to the calling program.      */
  1681. /*                                                                    */
  1682. /* Note:     YOU MUST FILL THIS ROUTINE WITH CODE.                    */
  1683. /*           If you want to add further global variables you SHOULD   */
  1684. /*           add them to the expose list of the procedure MAIN!       */
  1685. /*                                                                    */
  1686. Main: PROCEDURE expose (exposeList)
  1687.  
  1688.                     /* strings which should not be written into       */
  1689.                     /* the log file                                   */
  1690.   prog.__LogExcludeWords = screen.__fgYellow screen.__highlight ,
  1691.                            screen.__AttrOff
  1692.  
  1693.                     /* init the variables for the filenames and       */
  1694.                     /* directory names                                */
  1695.   sourceFiles. = ''
  1696.   sourceFiles.0 = 0
  1697.   targetFile = ''
  1698.   targetDirectory = ''
  1699.  
  1700.                     /* get the parameter of the program               */
  1701.   parse arg thisparameter
  1702.   call SplitParameter thisParameter , ':'
  1703.  
  1704.   do i = 1 to argv.0
  1705.  
  1706.     select
  1707.  
  1708.       when argv.i.__keyWord = 'SOURCE' then
  1709.       do
  1710.         k = sourceFiles.0+1
  1711.         sourceFiles.k = argv.i.__keyValue
  1712.         sourceFiles.0 = k
  1713.       end /* when */
  1714.  
  1715.       when argv.i.__keyWord = 'TARGET' then
  1716.       do
  1717.         if targetDirectory = '' then
  1718.           targetDirectory = argv.i.__KeyValue
  1719.         else
  1720.           call ShowError CIDRC.__unexpected_condition,,
  1721.                  'Duplicate parameter "' || argv.i.__KeyWord || '" found'
  1722.       end /* when */
  1723.  
  1724.       otherwise
  1725.       do
  1726.         call ShowError CIDRC.__unexpected_condition,,
  1727.                'Unknown parameter "' || argv.i.__keyword,
  1728.                                         argv.i.__keyvalue || '" found'
  1729.       end /* otherwise */
  1730.     end /* select */
  1731.   end /* do i = 1 to argv.i */
  1732.  
  1733.                     /* check the parameter                            */
  1734.   if sourceFiles.0 = 0 then
  1735.     call ShowError CIDRC.__unexpected_condition,,
  1736.            'Parameter "SOURCE:sourceFile" missing!'
  1737.  
  1738.   if targetDirectory = '' then
  1739.     call ShowError CIDRC.__unexpected_condition,,
  1740.            'Parameter "TARGET:targetDirectory" missing!'
  1741.  
  1742.                     /* check if the source files exist                */
  1743.                     /* also check for duplicate macronames            */
  1744.   do i = 1 to sourceFiles.0
  1745.                     /* add the extension if necessary                 */
  1746.     if fileSpec( 'E', sourceFiles.i ) = '' then
  1747.       sourceFiles.i = sourceFiles.i || '.CMD'
  1748.  
  1749.     tFileName = stream( sourceFiles.i, 'c', 'QUERY EXISTS' )
  1750.     if tFileName = '' then
  1751.       call ShowError CIDRC.__unexpected_condition,,
  1752.              'Can not find the source file "' || sourceFiles.i || '"'
  1753.     else
  1754.     do
  1755.                     /* get & check the macro name                     */
  1756.       sourceFiles.i = tFileName
  1757.       curMacroName = translate( GetMacroName( tFileName ) )
  1758.  
  1759.       if curMacroName = '' then
  1760.         call ShowError CIDRC.__unexpected_condition,,
  1761.              'Can not detect the name for the macro!'
  1762.  
  1763.       do k = 1 to i-1
  1764.         if curMacroName = sourceFiles.k.__MacroName then
  1765.           call ShowError CIDRC.__unexpected_condition,,
  1766.              'Duplicate macro found.' ,
  1767.              'The macroname is "' || curMacroName || '", filename 1 is "' || ,
  1768.              sourceFiles.k || '", filename 2 is "' || sourceFiles.i || '"'
  1769.       end /* do k = 1 to i-1 */
  1770.  
  1771.       sourceFiles.i.__MacroName = curMacroName
  1772.     end /* else */
  1773.   end /* do i = 1 to sourceFiles.0 */
  1774.  
  1775.   BaseSourceFile = sourceFiles.1
  1776.   BaseSourceDirectory = translate( FileSpec( 'H', BaseSourceFile ) )
  1777.  
  1778.                     /* check if the target directory exists           */
  1779.   if right( targetDirectory, 1 ) = '\' then
  1780.     targetDirectory = dbrright( targetDirectory, 1 )
  1781.  
  1782.   tTargetName = translate( DirExist( targetDirectory ) )
  1783.   if tTargetName = '' then
  1784.     call ShowError CIDRC.__unexpected_condition,,
  1785.          'The target directory "' || targetDirectory || '" does not exist'
  1786.  
  1787.   targetDirectory = tTargetName
  1788.  
  1789.                     /* determine the extension for the target image   */
  1790.   parse version rexxVersion .
  1791.   if rexxVersion = 'OBJREXX' then
  1792.      newExtension = '.IMO'
  1793.   else
  1794.      newExtension = '.IMC'
  1795.  
  1796.                     /* create the names for the target files          */
  1797.   targetBaseName = targetDirectory || '\' || fileSpec( 'B', BaseSourceFile )
  1798.   targetImgFile = targetBaseName || newExtension
  1799.   targetCmdFile = targetBasename || '.CMD'
  1800.  
  1801.  
  1802.   call log 'Creating the image file '
  1803.   call log ' ' || AddColor1( '"', targetImgFile )
  1804.   call log 'The target CMD file (loader) is '
  1805.   call log ' ' || AddColor1( '"', targetCmdFile )
  1806.   call log 'The base source file is'
  1807.   call log ' ' || AddColor1( '"', BaseSourceFile )
  1808.   call log 'The base source directory is'
  1809.   call log ' ' || AddColor1( '"', BaseSourceDirectory )
  1810.  
  1811.   if targetDirectory = BaseSourceDirectory then
  1812.     call ShowError CIDRC.__unexpected_condition,,
  1813.             'The target directory can not be equal to the base source directory!'
  1814.  
  1815.                     /* load the DLL functions to work on the macro    */
  1816.                     /* space                                          */
  1817.   if LoadMacroSpaceFunctions() <> 0 then
  1818.     call ShowError CIDRC.__unexpected_condition,,
  1819.            'Can not load the DLL functions to work with' ,
  1820.            'the macrospace functions'
  1821.  
  1822.   call log 'Creating the IMG file ...'
  1823.  
  1824.                     /* first clear the macro space                    */
  1825.   curClearRC = SysClearREXXMacroSpace()
  1826.   if curClearRC <> 0 & curClearRC <> 2 then
  1827.     call ShowError CIDRC.__unexpected_condition,,
  1828.            'Error ' || curClearRC || ' (' || ,
  1829.             GetMacroDllErrorMessage( curClearRC ) || ,
  1830.             ') clearing the macro space.'
  1831.  
  1832.                     /* clear the macro space at the end of the        */
  1833.                     /* program in all cases                           */
  1834.   prog.__exitRoutines = prog.__exitRoutines ' SysClearREXXMacroSpace '
  1835.  
  1836.                     /* load the macros into the macro space           */
  1837.   do i = 1 to sourceFiles.0
  1838.     curSourceFile = sourceFiles.i
  1839.     curMacroName =  sourceFiles.i.__MacroName
  1840.  
  1841.     if i = 1 then
  1842.       baseMacroName = curMacroName
  1843.  
  1844.     call log '  Loading the file ' || AddColor1( '"', curSourceFile )
  1845.     call log '    (The name of the macro is ' || AddColor1( '"', curMacroName ) || ')'
  1846.  
  1847.     if SysQueryRexxMacro( curMacroName ) <> '' then
  1848.       call ShowError CIDRC.__unexpected_condition,,
  1849.            'Duplicate macro found (Macro is already loaded)'
  1850.  
  1851.                     /* now load the REXX programs into the macro      */
  1852.                     /* space                                          */
  1853.     curLoadRC = SysAddRexxMacro( curMacroName,,
  1854.                                  curSourceFile ,,
  1855.                                  'B' )
  1856.     if curLoadRC <> 0 then
  1857.       call ShowError CIDRC.__unexpected_condition,,
  1858.            'Error ' || curLoadRC || ' (' || ,
  1859.             GetMacroDllErrorMessage( curLoadRC ) || ,
  1860.             ') loading the program into the macro space.'
  1861.  
  1862.   end /* do i = 1 to sourceFiles.0 */
  1863.  
  1864.                     /* now save the macro space into the target file  */
  1865.   curSaveImgRC = SysSaveRexxMacroSpace( targetImgFile )
  1866.   if curSaveImgRC <> 0 then
  1867.     call ShowError CIDRC.__unexpected_condition,,
  1868.            'Error ' || curSaveImgRC || ' (' || ,
  1869.             GetMacroDllErrorMessage( curSaveImgRC ) || ,
  1870.             ') saving the macro space into the target image file'
  1871.  
  1872.                     /* and last, clear the macro space again          */
  1873.   curClearRC = SysClearREXXMacroSpace()
  1874.   if curClearRC <> 0 & curClearRC <> 2 then
  1875.     call ShowWarning ,
  1876.            'Error ' || curClearRC || ' (' || ,
  1877.             GetMacroDllErrorMessage( curClearRC ) || ,
  1878.             ') clearing the macro space.'
  1879.  
  1880.   call log '... IMG file successfully created.'
  1881.  
  1882.                     /* and last, create the loader CMD file           */
  1883.   call log 'Creating the CMD file ...'
  1884.  
  1885.   call InitLoaderVariable baseMacroName
  1886.  
  1887.   if stream( targetCmdFile, 'c', 'QUERY EXISTS' ) <> '' then
  1888.     '@del ' targetCmdFile '2>NUL 1>NUL'
  1889.  
  1890.   call stream targetCmdFile, 'c', 'OPEN WRITE'
  1891.  
  1892.   thisRC = LineOut( targetCmdFile, loaderSourceCode )
  1893.  
  1894.   call stream targetCmdFile, 'c', 'CLOSE'
  1895.  
  1896.   if thisRC <> 0 then
  1897.     call ShowError CIDRC.__unexpected_condition,,
  1898.            'Error creating the CMD file'
  1899.  
  1900.   call log 'Target files succesfully created.'
  1901. exit 0
  1902.  
  1903.  
  1904. /* ------------------------------ */
  1905.  
  1906.                         /* exit the program                           */
  1907. RETURN
  1908.  
  1909. /* ------------------------------------------------------------------ */
  1910.  
  1911. /*** INSERT FURTHER SUBROUTINES HERE ***/
  1912.  
  1913. /*** Note: Do not forget the string 'EXPOSELIST' in the exposeList  ***/
  1914. /***       of ALL procedures!                                       ***/
  1915.  
  1916. /* ------------------------------------------------------------------ */
  1917. /* function: get the message for an error number from the macro       */
  1918. /*           functions                                                */
  1919. /*                                                                    */
  1920. /* call:     GetMacroDLLErrorMessage errorNo                          */
  1921. /*                                                                    */
  1922. /* where:    errorNo - error number                                   */
  1923. /*                                                                    */
  1924. /* returns:  error message                                            */
  1925. /*                                                                    */
  1926. GetMacroDllErrorMessage: PROCEDURE expose (exposeList)
  1927.   parse arg thisErrorNo .
  1928.  
  1929.   select
  1930.  
  1931.     when thisErrorNo = 1 then
  1932.       thisErrorMessage =  'Not enough memory'
  1933.  
  1934.     when thisErrorNo = 2 then
  1935.       thisErrorMessage =  'Macro not found'
  1936.  
  1937.     when thisErrorNo = 3 then
  1938.       thisErrorMessage =  'Extension required'
  1939.  
  1940.     when thisErrorNo = 4 then
  1941.       thisErrorMessage =  'Macro already exist'
  1942.  
  1943.     when thisErrorNo = 5 then
  1944.       thisErrorMessage =  'File error'
  1945.  
  1946.     when thisErrorNo = 6 then
  1947.       thisErrorMessage =  'Signatur error'
  1948.  
  1949.     when thisErrorNo = 7 then
  1950.       thisErrorMessage =  'Sourcefile not found'
  1951.  
  1952.     when thisErrorNo = 8 then
  1953.       thisErrorMessage =  'Invalid position'
  1954.  
  1955.     otherwise
  1956.       thisErrorMessage = 'Unknwon error'
  1957.  
  1958.   end /* select */
  1959.  
  1960. RETURN thisErrorMessage
  1961.  
  1962. /* ------------------------------------------------------------------ */
  1963. /* function: load the functions to process the macro space            */
  1964. /*                                                                    */
  1965. /* call:     thisRC = LoadMacroSpaceFunctions()                       */
  1966. /*                                                                    */
  1967. /* where:    -                                                        */
  1968. /*                                                                    */
  1969. /* returns:  0 =  okay                                                */
  1970. /*           else error                                               */
  1971. /*                                                                    */
  1972. /*                                                                    */
  1973. LoadMacroSpaceFunctions: PROCEDURE expose (exposeList)
  1974.                     /* init the stem with the macro function names    */
  1975.  
  1976.                     /* functions from the new REXXUTIL DLL            */
  1977.   i = 0; newFunctions.0 = i;
  1978.   i=i+1; newFunctions.i = 'SysQueryRexxMacro'
  1979.   i=i+1; newFunctions.i = 'SysAddRexxMacro'
  1980.   i=i+1; newFunctions.i = 'SysClearRexxMacroSpace'
  1981.   i=i+1; newFunctions.i = 'SysdropRexxMacro'
  1982.   i=i+1; newFunctions.i = 'SysLoadRexxMacroSpace'
  1983.   i=i+1; newFunctions.i = 'SysSaveRexxMacroSpace'
  1984.          newFunctions.0 = i
  1985.  
  1986.                     /* name of the DLL with the functions             */
  1987.   DLLtoUse = ''
  1988.  
  1989.                     /* possible names of the DLL to use               */
  1990.   possibleDLLS = 'REXXUTIL ' global.__REXXUTILDLL
  1991.  
  1992.   do i = 1 to words( possibleDLLs ) while DLLToUse = ''
  1993.     curDLLName = word( possibleDLLs, i )
  1994.  
  1995.                     /* try to load the first function                 */
  1996.     call rxFuncAdd newFunctions.1, curDLLName, newFunctions.1
  1997.  
  1998.                     /* check if the call was successfull              */
  1999.     if FunctionLoaded( newFunctions.1, '"dummy"' ) = 0 then
  2000.       DLLToUse = curDLLName
  2001.     else
  2002.       call rxFuncDrop newFunctions.1
  2003.   end /* do i = 1 to ... */
  2004.  
  2005.   if DLLToUse <> '' then
  2006.   do
  2007.     thisRC = 0
  2008.                     /* load the other functions                       */
  2009.     do i = 2 to newFunctions.0
  2010.       call rxFuncAdd newFunctions.i, DLLToUse, newFunctions.i
  2011.     end /* do i = 2 to newFunctions.0 */
  2012.   end /* if */
  2013.   else
  2014.     thisRC = 1
  2015.  
  2016. RETURN thisRC
  2017.  
  2018. /* ------------------------------------------------------------------ */
  2019. /* function: Check if a function is loaded                            */
  2020. /*                                                                    */
  2021. /* call:     thisRC = FunctionLoaded( Name {,parm1} {...} {,parm#}    */
  2022. /*                                                                    */
  2023. /* where:    name - name of the function                              */
  2024. /*           parm1 ... parm#                                          */
  2025. /*              parameter for the function                            */
  2026. /*                                                                    */
  2027. /* returns:  0 - okay, function is loaded                             */
  2028. /*           else error: either the function is not loaded or the     */
  2029. /*                       parameter are invalid                        */
  2030. /*                                                                    */
  2031. FunctionLoaded: PROCEDURE expose (exposeList)
  2032.  
  2033.                     /* init the return code                           */
  2034.   thisRC = 1
  2035.                     /* install a local error handler                  */
  2036.   signal on syntax name functionLoadedEnd
  2037.  
  2038.                     /* create the statement to call the function      */
  2039.   stmt = 'functionRC = ' || arg(1) || '('
  2040.  
  2041.   do i = 2 to arg()
  2042.     stmt = stmt arg( i )
  2043.   end /* do i = 1 to arg() */
  2044.  
  2045.   stmt = stmt || ')'
  2046.  
  2047.                     /* execute the statement                          */
  2048.   interpret stmt
  2049.  
  2050.                     /* the next statement is only executed if there's */
  2051.                     /* no error                                       */
  2052.   thisRC = 0
  2053.  
  2054. FunctionLoadedEnd:
  2055.  
  2056. return thisRC
  2057.  
  2058. /* ------------------------------------------------------------------ */
  2059. /* function: Check if a directory exist                               */
  2060. /*                                                                    */
  2061. /* call:     DirExist( testDir )                                      */
  2062. /*                                                                    */
  2063. /* where:    testDir - name of the directory to test                  */
  2064. /*                                                                    */
  2065. /* returns:  full name of the directory or "" if the directory        */
  2066. /*           don't exist                                              */
  2067. /*                                                                    */
  2068. DirExist: PROCEDURE
  2069.   parse arg testDir .
  2070.  
  2071.                         /* init the return code                       */
  2072.   thisRC = ""
  2073.  
  2074.                         /* install a temporary error handler to check */
  2075.                         /* if the drive with the directory to test is */
  2076.                         /* ready                                      */
  2077.   SIGNAL ON NOTREADY NAME DirDoesNotExist
  2078.  
  2079.                         /* check if the drive is ready                */
  2080.   call stream testDir || "\*", "D"
  2081.  
  2082.  
  2083.                         /* save the current directory of the current  */
  2084.                         /* drive                                      */
  2085.   curDir = directory()
  2086.  
  2087.                         /* save the current directory of the drive    */
  2088.                         /* with the directory to test                 */
  2089.   curDir1 = directory( fileSpec( "drive", testDir ) )
  2090.  
  2091.  
  2092.                         /* test if the directory exist                */
  2093.   thisRC = directory( testDir )
  2094.  
  2095.                         /* restore the current directory of the drive */
  2096.                         /* with the directory to test                 */
  2097.   call directory curDir1
  2098.  
  2099.                         /* restore the current directory of the       */
  2100.                         /* current drive                              */
  2101.   call directory curDir
  2102. DirDoesNotExist:
  2103.  
  2104. return thisRC
  2105.  
  2106. /* ------------------------------------------------------------------ */
  2107. /* function: Extended FILESPEC function                               */
  2108. /*                                                                    */
  2109. /* call:     FileSpec option,fileName                                 */
  2110. /*                                                                    */
  2111. /* where:    option                                                   */
  2112. /*                                                                    */
  2113. /*             - E{xtension}                                          */
  2114. /*               return the extension of the file                     */
  2115. /*                                                                    */
  2116. /*             - B{asename}                                           */
  2117. /*               returns the name of the file without extension       */
  2118. /*                                                                    */
  2119. /*             - H{ome]                                               */
  2120. /*               returns the fully qualified path of the file         */
  2121. /*               (including the drive specifier; without the trailing */
  2122. /*               backslash)                                           */
  2123. /*                                                                    */
  2124. /*             All other values for "option" are processed by the     */
  2125. /*             original FILESPEC function.                            */
  2126. /*                                                                    */
  2127. /*           fileName                                                 */
  2128. /*             - name of the file                                     */
  2129. /*                                                                    */
  2130. /* returns:  if option = E{xtension}:                                 */
  2131. /*             the extension of the fileName or "" if none            */
  2132. /*           else                                                     */
  2133. /*             if option = B{asename}:                                */
  2134. /*               the name of the file without the path and extension  */
  2135. /*             else                                                   */
  2136. /*               the return code of the original FILESPEC function    */
  2137. /*               or "SYNTAX ERROR" if called with invalid parameter   */
  2138. /*                                                                    */
  2139. /* note:     To call the original FILESPEC function direct use        */
  2140. /*             myResult = "FILESPEC"( option, fileName )              */
  2141. /*                                                                    */
  2142. /* history:                                                           */
  2143. /*           RXT&T v1.90 /bs                                          */
  2144. /*            - added the option B{asename}                           */
  2145. /*           RXT&T v2.30 /bs                                          */
  2146. /*            - added the option H{ome}                               */
  2147. /*                                                                    */
  2148. FileSpec: PROCEDURE
  2149.   parse arg option, fileName
  2150.  
  2151.                         /* init the return code                       */
  2152.   rc = "SYNTAX ERROR"
  2153.                         /* install a local error handler              */
  2154.  
  2155.   SIGNAL ON SYNTAX NAME FileSpecError
  2156.  
  2157.   fileName = strip( fileName )                               /* v2.30 */
  2158.   option = translate( strip( option ) )
  2159.  
  2160.                         /* check the option code                      */
  2161.   select
  2162.  
  2163.     when abbrev( "EXTENSION", option ) = 1 then
  2164.     do
  2165.                         /* process the new added option code          */
  2166.       i = lastPos( ".", fileName )
  2167.       if i > lastPos( "\", fileName ) then
  2168.         rc = substr( fileName, i )
  2169.       else
  2170.         rc = ""
  2171.     end /* when */
  2172.  
  2173.     when abbrev( "BASENAME", option ) = 1 then               /* v1.90 */
  2174.     do                                                       /* v1.90 */
  2175.                         /* call the original FILESPEC function  v1.90 */
  2176.                         /* to get the filename                  v1.90 */
  2177.       rc = "FILESPEC"( "N", fileName )                       /* v1.90 */
  2178.       i = lastpos( ".", rc )                                 /* v1.90 */
  2179.       if i <> 0 then                                         /* v1.90 */
  2180.         rc = substr( rc,1, i-1 )                             /* v1.90 */
  2181.     end /* when */                                           /* v1.90 */
  2182.  
  2183.     when abbrev( "HOME", option ) = 1 then                   /* v2.30 */
  2184.     do                                                       /* v2.30 */
  2185.       rc = "FILESPEC"( "D", fileName ) ||,                   /* v2.30 */
  2186.            "FILESPEC"( "P", fileName )                       /* v2.30 */
  2187.       if right( rc,1 ) = "\" then                            /* v2.30 */
  2188.         rc = dbrright( rc,1 )                                /* v2.30 */
  2189.     end /* when */                                           /* v2.30 */
  2190.  
  2191.     otherwise
  2192.     do
  2193.                         /* call the original FILESPEC function        */
  2194.       rc = "FILESPEC"( option, fileName )
  2195.     end /* otherwise */
  2196.  
  2197.   end /* select */
  2198.  
  2199. FileSpecError:
  2200.  
  2201. RETURN rc
  2202.  
  2203.  
  2204.  
  2205. /* ------------------------------------------------------------------ */
  2206. /* function: Show the invocation syntax                               */
  2207. /*                                                                    */
  2208. /* call:     called by the runtime system with                        */
  2209. /*           => call ShowUsage <=                                     */
  2210. /*                                                                    */
  2211. /* where:    -                                                        */
  2212. /*                                                                    */
  2213. /* returns:  ''                                                       */
  2214. /*                                                                    */
  2215. /* Note:     YOU SHOULD FILL THIS ROUTINE WITH CODE.                  */
  2216. /*           You may change the return code for your program in this  */
  2217. /*           routine. The default for the return code is 253.         */
  2218. /*           (The variable for the return code is prog.__ExitCode)    */
  2219. /*                                                                    */
  2220. /*                                                                    */
  2221. ShowUsage: PROCEDURE expose (exposeList)
  2222.   call ShowString I!.__GetMsg( 14 ) || ' ' ,,                /* v3.06 */
  2223.                   prog.__name ,                              /* v3.06 */
  2224.                   global.__userUsage prog.__DefParms         /* v3.06 */
  2225.  
  2226. RETURN ' '                                                   /* v3.03 */
  2227.  
  2228.  
  2229. /* ------------------------------------------------------------------ */
  2230. /* Function: add quote chars and color codes to a string              */
  2231. /*                                                                    */
  2232. /* call:     AddColor1( quoteChar ,myString )                         */
  2233. /*                                                                    */
  2234. /* where:    quoteChar - leading and trailing character for the       */
  2235. /*                       converted string (may be ommited)            */
  2236. /*           myString - string to convert                             */
  2237. /*                                                                    */
  2238. /* returns:  converted string                                         */
  2239. /*                                                                    */
  2240. /* note:     Add the color codes used in this routine to the          */
  2241. /*           variable 'prog.__LogExcludeWords' if you don't want      */
  2242. /*           them in the logfile. Example:                            */
  2243. /*                                                                    */
  2244. /*               prog.__LogExcludeWords = screen.__fgYellow ,         */
  2245. /*                                        screen.__highlight ,        */
  2246. /*                                        screen.__AttrOff            */
  2247. /*                                                                    */
  2248. /*           This should be one of the first statements in the        */
  2249. /*           routine main.                                            */
  2250. /*                                                                    */
  2251. AddColor1: PROCEDURE expose (exposeList)
  2252.   parse arg quoteChar, myString
  2253.  
  2254. return quoteChar || screen.__fgYellow || screen.__highlight || ,
  2255.        myString || ,
  2256.       screen.__AttrOff || quoteChar
  2257.  
  2258.  
  2259. /* ------------------------------------------------------------------ */
  2260. /* function: split a string into separate arguments                   */
  2261. /*                                                                    */
  2262. /* call:     call SplitParameter Parameter_string, separator          */
  2263. /*                                                                    */
  2264. /* where:    parameter_string - string to split                       */
  2265. /*           separator - separator character to split a parameter     */
  2266. /*                       into keyword and keyvalue                    */
  2267. /*                                                                    */
  2268. /* returns:  the number of arguments                                  */
  2269. /*           The arguments are returned in the stem argv.:            */
  2270. /*             argv.0 = number of arguments                           */
  2271. /*             argv.n.__keyword = keyword                             */
  2272. /*             argv.n.__keyValue = keyValue                           */
  2273. /*                                                                    */
  2274. /* note:     handles arguments in quotes and double quotes also       */
  2275. /*                                                                    */
  2276. /*                                                                    */
  2277. SplitParameter: PROCEDURE EXPOSE (exposeList) argv.
  2278.  
  2279.                     /* get the parameter                              */
  2280.   parse arg thisArgs, thisSeparator
  2281.  
  2282.                     /* init the result stem                           */
  2283.   argv.0 = 0
  2284.  
  2285.   do while thisargs <> ''
  2286.  
  2287.     parse value strip( thisArgs, "B" ) with curArg thisArgs
  2288.  
  2289.     parse var curArg tc +1 .
  2290.     if tc = '"' | tc = "'" then
  2291.       parse value curArg thisArgs with (tc) curArg (tc) ThisArgs
  2292.  
  2293.     parse var curArg '' -1 lastChar 1 argType (thisSeparator) argValue
  2294.  
  2295.     parse var argValue tc +1 .
  2296.     if tc = '"' | tc = "'" then
  2297.       parse value argValue thisArgs with (tc) argValue (tc) ThisArgs
  2298.  
  2299.     argtype  = strip( argType  )
  2300.     argValue = strip( argValue )
  2301.  
  2302.     i = argv.0 + 1
  2303.  
  2304.     argv.i.__keyword = translate( argType )
  2305.     argv.i.__KeyValue = argValue
  2306.  
  2307.     argv.0 = i
  2308.  
  2309.   end /* do while thisArgs <> '' */
  2310.  
  2311. RETURN argv.0
  2312.  
  2313. /* ------------------------------------------------------------------ */
  2314. /* function: get the name for a macro                                 */
  2315. /*                                                                    */
  2316. /* call:     curMacroName = GetMacroName( curMacroCMDFile )           */
  2317. /*                                                                    */
  2318. /* where:    curMacroCMDFile - name of the file with the macro        */
  2319. /*                                                                    */
  2320. /* returns:  the name of the macro or ''                              */
  2321. /*                                                                    */
  2322. /* notes:    GetMacroName first tries to get the macro name form the  */
  2323. /*           first line of the file. Is this fails, it uses the name  */
  2324. /*           of the file without the extension as macro name.         */
  2325. /*                                                                    */
  2326. GetMacroName: PROCEDURE expose (exposeList)
  2327.   parse arg CurMacroCMDFile
  2328.  
  2329.                     /* init the return code                           */
  2330.   curMacroName = ''
  2331.  
  2332.   if curMacroCMDFile <> '' then
  2333.   do
  2334.                     /* check the filetype                             */
  2335.     if stream( curMacroCMDFile, 'c', 'QUERY EXISTS' ) <> '' then
  2336.     do
  2337.       curMacroSignatur = charIn( curMacroCMDFile, 1,2 )
  2338.  
  2339.                     /* close the file                                 */
  2340.       call stream curMacroCMDFile, 'c', 'CLOSE'
  2341.  
  2342.       if length( curMacroSignatur ) = 2 then
  2343.       do
  2344.         if curMacroSignatur = '/' || '*' then
  2345.         do
  2346.                     /* get the name for the macro                     */
  2347.           firstMacroLine = lineIn( curMacroCMDFile )
  2348.  
  2349.                     /* close the macro file                           */
  2350.           call stream curMacroCmdFile, 'c', 'CLOSE'
  2351.  
  2352.           parse upper var firstMacroLine . 'MACRONAME:' curMacroName .
  2353.           curMacroName = strip( curMacroName )
  2354.           parse var curMacroName tc +1 .
  2355.           if tc = '"' | tc = "'" then
  2356.             parse var firstMacroLine . 'MACRONAME:' (tc) curMacroName (tc)
  2357.           else
  2358.             curMacroName = strip( word( curMacroName, 1 ) )
  2359.         end /* if */
  2360.  
  2361.         if curMacroName = '' then
  2362.         do
  2363.           curMacroName = fileSpec( "name", curMacroCMDFile )
  2364.           if lastPos( '.', curMacroName ) <> 0 then
  2365.             curMacroName = substr( curMacroName, 1,,
  2366.                            lastPos( '.', curMacroName )-1 )
  2367.         end /* if curMacroName = '' then */
  2368.       end /* if length( curMacroSignatur ) = 2 then */
  2369.     end /* if stream( curMacroCMDFile, 'c', 'QUERY EXISTS' ) <> '' then */
  2370.   end /* if curMacroCMDFile <> '' then */
  2371.  
  2372. return curMacroName
  2373.  
  2374. /* ------------------------------------------------------------------ */
  2375. /* function: Init the variable with the source for the loader         */
  2376. /*                                                                    */
  2377. /* call:     call InitLoaderVariable curMacorName                     */
  2378. /*                                                                    */
  2379. /* where:    curMacroName - name of the base macro                    */
  2380. /*                                                                    */
  2381. /* returns:  nothing                                                  */
  2382. /*                                                                    */
  2383. /* notes:    The variable 'LoaderSourceCode' holds the source code    */
  2384. /*           after executing this routine.                            */
  2385. /*                                                                    */
  2386. InitLoaderVariable: PROCEDURE expose (exposeList) LoaderSourceCode
  2387.   parse arg curMacroName
  2388.  
  2389. LoaderSourceCode = ,
  2390. '/* ------------------------------------------------------------------ */' || '0D0A'x || ,
  2391. '/* loader to load a saved macro space image into the macro space,     */' || '0D0A'x || ,
  2392. '/* execute it there and clear the macro space afterwards              */' || '0D0A'x || ,
  2393. '/*                                                                    */' || '0D0A'x || ,
  2394. '                                                                        ' || '0D0A'x || ,
  2395. '  signal on syntax Name FunctionNotFound                                ' || '0D0A'x || ,
  2396. '  parse arg programParameter                                            ' || '0D0A'x || ,
  2397. '                                                                        ' || '0D0A'x || ,
  2398. '  call rxFuncAdd "SysLoadFuncs", "REXXUTIL", "SysLoadFuncs"             ' || '0D0A'x || ,
  2399. '  call SysLoadFuncs                                                     ' || '0D0A'x || ,
  2400. '                                                                        ' || '0D0A'x || ,
  2401. '  parse version rexxVersion .                                           ' || '0D0A'x || ,
  2402. '  if rexxVersion = "OBJREXX" then                                       ' || '0D0A'x || ,
  2403. '    extension = ".IMO"                                                  ' || '0D0A'x || ,
  2404. '  else                                                                  ' || '0D0A'x || ,
  2405. '    extension = ".IMC"                                                  ' || '0D0A'x || ,
  2406. '                                                                        ' || '0D0A'x || ,
  2407. '  parse source . . thisFile                                             ' || '0D0A'x || ,
  2408. '                                                                        ' || '0D0A'x || ,
  2409. '  i = lastPos( "\", thisFile )                                          ' || '0D0A'x || ,
  2410. '  j = lastPos( ".", thisFile )                                          ' || '0D0A'x || ,
  2411. '                                                                        ' || '0D0A'x || ,
  2412. '  imgFile = substr( thisFile, 1, j-1 ) || extension                     ' || '0D0A'x || ,
  2413. '                                                                        ' || '0D0A'x || ,
  2414. '  if stream( imgFile, "c", "QUERY EXISTS" ) = "" then                   ' || '0D0A'x || ,
  2415. '  do                                                                    ' || '0D0A'x || ,
  2416. '    say "Error: Can not find the image "                                ' || '0D0A'x || ,
  2417. '    say "       " || imgFile                                            ' || '0D0A'x || ,
  2418. '    say "Please check the installation!"                                ' || '0D0A'x || ,
  2419. '    exit 3                                                              ' || '0D0A'x || ,
  2420. '  end                                                                   ' || '0D0A'x || ,
  2421. '                                                                        ' || '0D0A'x || ,
  2422. '  thisRC = SysClearRexxMacroSpace()                                     ' || '0D0A'x || ,
  2423. '  if thisRC <> 0 & thisRC <> 2 then                                     ' || '0D0A'x || ,
  2424. '  do                                                                    ' || '0D0A'x || ,
  2425. '    say "Error " || thisRC || " clearing the macro space!"              ' || '0D0A'x || ,
  2426. '    exit 1                                                              ' || '0D0A'x || ,
  2427. '  end                                                                   ' || '0D0A'x || ,
  2428. '                                                                        ' || '0D0A'x || ,
  2429. '  thisRC = SysLoadRexxMacroSpace( imgFile )                             ' || '0D0A'x || ,
  2430. '  if thisRC <> 0 then                                                   ' || '0D0A'x || ,
  2431. '  do                                                                    ' || '0D0A'x || ,
  2432. '    say "Error " || thisRC || " loading the image into the macro space!"' || '0D0A'x || ,
  2433. '    exit 1                                                              ' || '0D0A'x || ,
  2434. '  end                                                                   ' || '0D0A'x || ,
  2435. '                                                                        ' || '0D0A'x || ,
  2436. '  call ' || curMacroName || ' programParameter                          ' || '0D0A'x || ,
  2437. '  if symbol( "result" ) = "VAR" then                                    ' || '0D0A'x || ,
  2438. '    programRC = result                                                  ' || '0D0A'x || ,
  2439. '  else                                                                  ' || '0D0A'x || ,
  2440. '    programRC = 0                                                       ' || '0D0A'x || ,
  2441. '                                                                        ' || '0D0A'x || ,
  2442. '  thisRC = SysClearRexxMacroSpace()                                     ' || '0D0A'x || ,
  2443. '                                                                        ' || '0D0A'x || ,
  2444. 'exit result                                                             ' || '0D0A'x || ,
  2445. '                                                                        ' || '0D0A'x || ,
  2446. 'FunctionNotFound:                                                       ' || '0D0A'x || ,
  2447. '  say "Syntax error in line " || sigl || ,                              ' || '0D0A'x || ,
  2448. '      " (condition("D") is "" || condition(D) || "")."                  ' || '0D0A'x || ,
  2449. '  say "Maybe you are using an invalid REXXUTIL DLL:"                    ' || '0D0A'x || ,
  2450. '  say "  This program needs the REXXUTIL DLL from Object REXX."         ' || '0D0A'x || ,
  2451. 'exit 255                                                                ' || '0D0A'x || ,
  2452. '                                                                        ' || '0D0A'x || ,
  2453. '/* ------------------------------------------------------------------ */' || '0D0A'x || ,
  2454. '                                                                        ' || '0D0A'x || ,
  2455. ''
  2456. return
  2457.  
  2458. /* ------------------------------------------------------------------ */
  2459. /* NOTE: You must uncomment this routines before using them!!!        */
  2460.  
  2461. /*** DEBUGGING SUBROUTINES ***/
  2462.  
  2463. /**DEBUG** Delete this line before using the debugging routines!!! */
  2464.  
  2465.  
  2466. /* ------------------------------------------------------------------ */
  2467. /* function: show all variables defined for the routine calling       */
  2468. /*           this routine.                                            */
  2469. /*                                                                    */
  2470. /* call:     ShowDefinedVariables {N}, {varMask}                      */
  2471. /*                                                                    */
  2472. /* where:    N - no pause if the screen is full                       */
  2473. /*           varMask - mask for the variables                         */
  2474. /*                                                                    */
  2475. /* returns:  nothing                                                  */
  2476. /*                                                                    */
  2477. /* note:     This routine needs the Dave Boll's DLL RXU.DLL!          */
  2478. /*           Be aware that the special REXX variables SIGL, RC and    */
  2479. /*           RESULT are changed if you call this routine!             */
  2480. /*                                                                    */
  2481. /*                                                                    */
  2482. ShowDefinedVariables:
  2483.   parse upper arg SDV.__pauseMode, SDV.__varMask
  2484.  
  2485.  
  2486.                                 /* install a local error handler      */
  2487.   signal on syntax name SDV.__RXUNotFound
  2488.  
  2489.                                 /* load the necessary DLL function    */
  2490.   call rxFuncDrop 'RxVLIst'
  2491.   call rxFuncAdd 'RxVlist', 'RXU', 'RxVList'
  2492.  
  2493.   call rxFuncDrop 'RxPullQueue'
  2494.   call rxFuncAdd 'RxPullQueue', 'RXU', 'RxPullQueue'
  2495.  
  2496.                                 /* create a queue for the variables   */
  2497.   SDV.__newQueue = rxqueue( 'create' )
  2498.  
  2499.                                 /* the 'D' parameter of the RxVList   */
  2500.                                 /* functions won't pause if the       */
  2501.                                 /* screen is full                     */
  2502.   SDV.__thisRC = RxVList( SDV.__varMask, 'V' , SDV.__newQueue )
  2503.  
  2504.                                 /* ignore local variables of this     */
  2505.                                 /* routine                            */
  2506.   SDV.__thisRC = SDV.__thisRC
  2507.  
  2508.   say '  ' || copies( '─',76 )
  2509.  
  2510.   if SDV.__thisRC <> 0 then
  2511.   do
  2512.  
  2513.     say '  Defined variable(s) and their values:'
  2514.     SDV.__i = 0
  2515.  
  2516.     do SDV.__n = 1 to SDV.__ThisRC
  2517.       if SDV.__i >= 23 & ,
  2518.          SDV.__pauseMode <> 'N' then
  2519.       do
  2520.         ADDRESS 'CMD' 'PAUSE'
  2521.         SDV.__i = 0
  2522.       end /* if */
  2523.       SDV.__varName = RxPullQueue( SDV.__newQueue, 'Nowait', 'SDV.__dummy' )
  2524.       SDV.__varValue = RxPullQueue( SDV.__newQueue, 'Nowait', 'SDV.__dummy' )
  2525.  
  2526.                                 /* ignore local variables of this     */
  2527.                                 /* routine                            */
  2528.       if left( SDV.__varName, 6 ) <> 'SDV.__' then
  2529.       do
  2530.         say '     ' || SDV.__varName || ' = "' || SDV.__varValue || '"'
  2531.         SDV.__i = SDV.__i+1
  2532.       end /* if right( ... */
  2533.  
  2534.     end /* do */
  2535.  
  2536.                         /* delete the queue for the variables         */
  2537.     call rxqueue 'Delete', SDV.__newQueue
  2538.   end
  2539.   else
  2540.     say '  No variables defined.'
  2541.  
  2542.   say '  ' || copies( '─',76 )
  2543.  
  2544.                         /* delete local variables                     */
  2545.   drop SDV.
  2546. RETURN ' '                                                   /* v3.03 */
  2547.  
  2548.                         /* error exit for ShowDefinedVariables        */
  2549. SDV.__RXUNotFound:
  2550.   say 'ShowDefinedVariables: RXU.DLL not found'
  2551. RETURN 255
  2552.  
  2553. /*   Delete this line before using the debugging routines!!!    **DEBUG**/
  2554.  
  2555. /***        End of Part 4 of the source code of TEMPLATE.CMD        ***/
  2556. /**********************************************************************/
  2557.    
  2558.  
  2559.