home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 18 REXX / 18-REXX.zip / rxtmp2.zip / TEMPLATE.CMD < prev   
OS/2 REXX Batch file  |  1995-01-08  |  107KB  |  2,015 lines

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