home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 18 REXX
/
18-REXX.zip
/
rxtmp2.zip
/
TEMPLATE.CMD
< prev
Wrap
OS/2 REXX Batch file
|
1995-01-08
|
107KB
|
2,015 lines
/* ------------------------------------------------------------------ */
/* TEMPLATE.CMD - Template for a REXX program */
/* */
/* (c) Copyright Bernd Schemmer 1994,1995 */
/* */
/*-Author: */
/* Bernd Schemmer */
/* Baeckerweg 48 */
/* D-60316 Frankfurt am Main */
/* Germany */
/* Compuserve: 100104,613 */
/* */
/*-History: */
/* 01.07.1994 /bs v1.00 */
/* - initial release */
/* 09.12.1994 /bs v2.51 */
/* - first public release */
/* 01.01.1995 /bs v2.52 */
/* - corrected a bug in the logfile routine */
/* (no message was written to the logfile) */
/* - added some more comments (requested by some users) */
/* - converted all esc chars to '1B'x */
/* - added the environment variable 'SOUND' */
/* - changed the error handler: */
/* Only the error handler for the trapped condition is now */
/* reinstalled. The runtime system does now never change */
/* the error handling if it was changed in MAIN. */
/* - made some optimisations to shrink the needed memory for the */
/* token image */
/* */
/*-Distribution: */
/* This code may be distributed freely and used in other programs. */
/* Please give credit where credit is due. */
/* If you need further help, you may write me a message. */
/* */
/*-Description: */
/* TEMPLATE.CMD is a template for a REXX program containing a */
/* "runtime system" for the REXX program. */
/* TEMPLATE.CMD ... */
/* - supports INCLUDE() and TRYINCLUDE() (see source) */
/* - contains an extended error handler (much better than the */
/* default error handler, see routine 'I!.__ErrorAbort') */
/* - supports patched version */
/* - supports CID conventions */
/* - supports colored messages */
/* - supports execution in the REXX macro space */
/* - supports executions as "compiled" REXX program (**) */
/* - supports logging of program messages, STDOUT messages and/or */
/* STDERR messages of OS/2 programs */
/* - contains a debugging mechanism */
/* - contains an exit routine handler */
/* - contains many predefined variables (for example the program */
/* name, drive and path) */
/* - contains very useful predefined routines, for example */
/* LoadDll - load a DLL, for example REXXUTIL or VREXX */
/* ShowString - show a string with prefix and word wrapping */
/* Include - execute an include file */
/* TryInclude - execute an include file only if it exists */
/* and much more. */
/* */
/* (**) You may use my program REXXCC to "compile" your REXX */
/* programs. You can get REXXCC at the same source as this */
/* file. The name of the archiv with REXXCC is "REXXCnnn.EXE" */
/* where nnn is the version of REXXCC. REXXCC is freeware. */
/* */
/*-CAUTION: READ THIS COMMENTS CAREFULLY BEFORE (!) USING THIS CODE!! */
/* */
/*-Usage: */
/* Copy this file to a new file, example: */
/* => COPY TEMPLATE.CMD MYPROG.CMD <= */
/* Change the variables after this comments to your need. */
/* Insert your main code after the label */
/* => MAIN: <= */
/* in the new file MYPROG.CMD. */
/* Insert your subroutines behind the line */
/* /*** INSERT FURTHER SUBROUTINES HERE ***/ */
/* in the new file MYPROG.CMD. */
/* That's all - but do not forget to read the comments below!!! */
/* */
/*-Predefined parameter: */
/* TEMPLATE {/L:logfile} {/H} {/Silent} */
/* */
/*-where: */
/* /L:logFile - logfile is the name of the logfile :-) */
/* This Parameter is case-sensitive! */
/* def.: do not use a logfile */
/* /H - show usage, you may also use -H, /?, -? or /HELP. */
/* (MAIN is not called!) */
/* /Silent - suppress all messages (except error messages) */
/* You should also use the parameter /L if you use */
/* this parameter! */
/* */
/* NOTE: */
/* The predefined parameters are processed by the runtime system. */
/* The procedure MAIN will never see them! */
/* The length of the parameters must not exceed 248 characters! */
/* This is due to a restriction of REXX. */
/* You can only use quotes (') or double quotes (") in parameters */
/* but you must not mix quotes and double quotes in the parameters! */
/* This will lead to the error message */
/* 'Can not find the routine "main"'! */
/* An unbalanced quote or double quote will also cause this error */
/* message. */
/* */
/* HINT: */
/* Do not define a parameter beginning with '/Q'! '/Q' in the */
/* parameters is always interpretet by the CMD - your program will */
/* never see that part of the parameter! */
/* */
/*-predefined returncodes: */
/* 0 - execution okay */
/* 240 ... 252 */
/* reserved for the runtime system */
/* 253 - syntax help called (parameter /h) */
/* 254 - user break (CTRL-C) */
/* 255 - internal runtime system error */
/* else - program specific errors */
/* */
/*-Notes: */
/* */
/* #======================== !!! IMPORTANT !!! =====================# */
/* # DO NOT DEFINE VARIABLES FOR THE STEM 'I!.'! # */
/* # DO NOT USE ANY OF THE VARIABLES BEGINNING WITH 'I!.' IN YOUR # */
/* # CODE! # */
/* # DO NOT USE ANY OF THE ROUTINES BEGINNING WITH 'I!.' IN YOUR # */
/* # CODE! # */
/* # DO NOT DEFINE VARIABLES WHICH NAMES BEGIN WITH TWO UNDERSCORES # */
/* # ('__') IN YOUR CODE! # */
/* #================================================================# */
/* */
/* #======================== !!! IMPORTANT !!! =====================# */
/* # DO NOT CHANGE, ADD OR DELETE CODE BETWEEN THE LINES # */
/* # # */
/* # ...********** DO NOT CHANGE THE FOLLOWING LINES ***********... # */
/* # # */
/* # and # */
/* # # */
/* # ...********************************************************... # */
/* # # */
/* #================================================================# */
/* */
/* #======================== !!! HINT !!! =====================# */
/* # Do NOT change, add or delete the lines # */
/* # # */
/* # ... start of part n of the source code of TEMPLATE.CMD ... # */
/* # # */
/* # and # */
/* # # */
/* # ... end of part n of the source code of TEMPLATE.CMD ... # */
/* # # */
/* # where n =1,2,3 or 4 if you want to use MAKECMD.CMD to update # */
/* # the runtime system of your programs if you get a new version # */
/* # of TEMPLATE.CMD. # */
/* # # */
/* #================================================================# */
/* predefined variables (All values are in uppercase. IMPORTANT: */
/* DO NOT CHANGE THIS VARIABLES!) */
/* */
/* prog.__drive = drive of the program (e.g. "D:") */
/* This variable is '' if the program is in the */
/* macro space. */
/* prog.__path = path of the program (e.g. "\CODESERV\CMD") */
/* This variable is '' if the program is in the */
/* macro space. */
/* prog.__name = name of the program (e.g. "MYPROG.CMD") */
/* prog.__FullName = fully qualified name of the program */
/* (e.g. "D:\CODESERV\CMD\MYPROG.CMD") */
/* This variable contains only the program name */
/* if the program is in the macro space */
/* prog.__env = OS/2 environment (use for VALUE() commands!) */
/* prog.__Version = version of TEMPLATE.CMD (e.g. "V1.00") */
/* prog.__QuietMode = suppress all messages if not '' */
/* This variable is set to 1, if the parameter */
/* /SILENT was enterd. */
/* */
/* prog.__Logfile = name of the logfile (or "" if none) */
/* prog.__LogSTDERR = String to direct STDERR into the logfile */
/* prog.__LogSTDOUT = String to direct STDOUT into the logfile */
/* prog.__LogALL = String to direct STDOUT and STDERR into the */
/* logfile. */
/* prog.__LogFileParm = log-Parameter for child cmds (or "" if no */
/* logfile is defined), usage: */
/* => call child.cmd {...} prog.__LogFileParm <=*/
/*-NOTE: If no log file is defined, the output is directed to the */
/* NUL-Device. See below for examples using the logfile */
/* variables. */
/* */
/* global.__ErrorExitCode */
/* = return code if an unknown error occured */
/* (255) */
/* global.__OKExitCode */
/* = return code if the execution was ok */
/* (0) */
/* */
/* CIDRC. = return codes for the CID process (only */
/* defined if global.__NeedCID is 1, see */
/* the procedure I!.__InitCIDVars) */
/* */
/*-predefined variables (may be changed): */
/* */
/* exposeList = Name(s) of the the global variables ALL */
/* procedures must know! */
/* You may add further variable names to this */
/* string but you must not delete any name from */
/* this variable! */
/* IMPORTANT: */
/* DO ONLY ADD STEM VARIABLES TO THIS VARIABLE! */
/* */
/* prog.__NoSound = 1 - turn sounds off */
/* else: turn sounds on (default) */
/* TEMPLATE use sounds only in case of an error */
/* You may also set the environment */
/* variable SOUND to "NO" if you don't want */
/* sounds. */
/* */
/* prog.__LogExcludeWords = */
/* This variable contains strings, which you */
/* want to output on the screen but not in */
/* the logfile (via the procedure log). You */
/* may use this variable for example for color */
/* codes which you might use in your messages. */
/* The default for prog.__LogExcludeWords is '' */
/* */
/* prog.__UserAbort = 0 - do not allow CTRL-BREAK */
/* 1 - allow CTRL-BREAK (default) */
/* */
/* prog.__ExitCode = return code of the program */
/* Note that 'prog.__ExitCode' should be a */
/* whole number. (def.: 0) */
/* Further note: */
/* Do not define the return codes 0 and 240 */
/* to 255. This return codes are used by the */
/* runtime system. */
/* */
/* prog.__ExitRoutines = routines, which should be executed at */
/* program end (def.: NONE) */
/* Usage example: see below */
/* */
/* prog.__CurDir = working directory at program start */
/* Note that the working directory at program */
/* start is restored at program end automaticly */
/* To avoid this use 'drop prog.__CurDir'. */
/* */
/* prog.__ScreenCols = number of screen columns */
/* (default: 80, or the real number of colums */
/* if REXXUTIL is loaded before the program */
/* starts) */
/* */
/* prog.__ScreenRows = number of screen rows */
/* (default: 25, or the real number of rows */
/* if REXXUTIL is loaded before the program */
/* starts) */
/* */
/* screen. = stem variables for foreground and background */
/* colors, some examples: */
/* */
/* screen.__CurColor = current color for messages */
/* screen.__CurColor = current color for messages */
/* screen.__ErrorColor = color for error and warning messages */
/* screen.__NormalColor= color for normal messages */
/* screen.__DebugColor = color for debug messages */
/* screen.__PromptColor= color for input prompts */
/* (see also the procedure */
/* I!.__InitColorVars for further vars.) */
/* */
/* global.__verbose = show debug messages if not equal '' */
/* You may set the environment variable */
/* VERBOSE to the value for global.__verbose */
/* before running the program. */
/* Note: There is no debug code in the runtime */
/* system. */
/* */
/* variables for conditional addons (may only be changed BEFORE */
/* I!.__InitVars is called!): */
/* */
/* global.__SignOnMsg = set to 0 if you do not want a program */
/* start and end message (def.: 1) */
/* global.__Version = version of the program (e.g. "V1.00") */
/* global.__NeedCID = set to 1 if you need CID support */
/* (def.: 0) */
/* global.__NeedColors = set to 0 if you do not want colored */
/* messages (def.: 1) */
/* You may also set the environment */
/* variable ANSI to "NO" if you don't want */
/* colors. This environment variable over- */
/* writes the variable global.__NeedColors */
/* while running the program. */
/* CAUTION: ANSI must be ON to use colors! */
/* global.__NeedPatchCheck */
/* = set to 0 if you do not want to search */
/* the program for a patched version of the */
/* program (def.: 1) */
/* */
/* */
/* Routines called by the runtime system */
/* */
/* ■ Main */
/*-function: */
/* This is the main routine of the program. */
/*-parameter: */
/* The parameter for this routine are the program parameter */
/* without the parameter handled by the runtime system. */
/*-returns: */
/* nothing */
/* YOU MUST FILL THIS ROUTINE WITH CODE! */
/* */
/* ■ ShowUsage */
/*-function: */
/* This routine is called, if the program is invoked with one of */
/* the parameters /H, /h, /?, /HELP, -h, -H, -HELP or -?. */
/*-parameter: */
/* none */
/*-returns: */
/* nothing */
/* YOU SHOULD FILL THIS ROUTINE WITH CODE! */
/* */
/* */
/* Predefined routines (you may use this routines in your code. See */
/* the source for the invocation parameters and the return codes): */
/* */
/* ■ LoadDll parameter */
/* - load a dll */
/* */
/* ■ ConvertNameToOS {filenName|dirName} */
/* - convert the name of a file or directory to the format of OS/2 */
/* by adding a leading and a trailing quote or double quote to */
/* the name. */
/* Example: */
/* => my1stFileName="This is a 'valid' HPFS filename" <= */
/* => my2ndFileName='This is a "valid" HPFS filename' <= */
/* => say convertNameToOS( my1stFileName ) <= */
/* => say convertNameToOS( my2ndFileName ) <= */
/* Output: */
/* "This is a 'valid' HPFS filename" */
/* 'This is a "valid" HPFS filename' */
/* Hint: You should always save the names of files and directorys */
/* without leading and trailing quotes or double quotes */
/* because the REXX functions don't like quotes or double */
/* quotes surrounding file and directory names. */
/* */
/* ■ ShowString prefix, string */
/* - show a string with word wrapping and write it also to the */
/* logfile if defined */
/* 'prefix' is the prefix for the first line. This can be a */
/* string like '*-* ' or a number. If 'prefix' is a number, */
/* ShowString uses this number of blanks as prefix. */
/* Note: Do not use ShowString for strings with color codes! */
/* */
/* ■ ShowWarning message */
/* - show the warning message 'message' and write it also to the */
/* logfile if defined */
/* Note: Do not use color codes in the message! */
/* */
/* ■ ShowError exitCode, errorMessage */
/* - show the error message 'errorMessage', write it also to the */
/* logfile if defined and exit the program with the return code */
/* 'exitCode' */
/* Note: Do not use color codes in the errorMessage! */
/* */
/* ■ Log message */
/* - show the message 'message' and write the message also to the */
/* logfile if defined */
/* You may use colors in the message. */
/* */
/* ■ LogDebugMsg message */
/* - show the message 'message' in the color for debug messages and */
/* write the message also to the logfile if defined (only if the */
/* variable 'global.__verbose' is not equal '') */
/* */
/* ■ FlushQueue */
/* - flush the current REXX queue */
/* */
/* ■ Include fileName */
/* - execute the include file 'fileName' */
/* Usage: */
/* => Include( fileName ) <= */
/* (no call statement neccessary) */
/* */
/* ■ TryInclude fileName */
/* - execute the include file 'fileName' if it exists */
/* Usage: */
/* => TryInclude( fileName ) <= */
/* (no call statement neccessary) */
/* */
/* #======================= !!! CAUTION: !!! =======================# */
/* # Read the part about the 'INTERPRET' command in the Online help # */
/* # of REXX carefully before writing and using include files!!! # */
/* # Hint: You can use multi line statements in include files. # */
/* # (Exception: Multi line comments are not allowed.) # */
/* # Note: You can NOT define subroutines in an include file # */
/* # because the statements in the include file are executed # */
/* # imediately! # */
/* #================================================================# */
/* */
/* Do NOT use the following names for functions or routines: */
/* */
/* ShowString ShowWarning ShowError */
/* Log LogDebugMsg */
/* include tryInclude LoadDll */
/* FlushQueue ConvertNameToOS */
/* */
/* */
/* Environment variables used while running the program */
/* */
/* ■ VERBOSE */
/* - Set the environment variable 'VERBOSE' to any value not equal */
/* '' if you want debug information. If the value of the variable */
/* is 'DEBUG', the error handler turns interactive trace on if an */
/* error occured. */
/* */
/* ■ ANSI */
/* - Set the environment variable 'ANSI' to "0" or "OFF" if you */
/* don't want colors. */
/* */
/* ■ SOUND */
/* - Set the environment variable 'SOUND' to "0" or "OFF" if you */
/* don't want sounds. */
/* */
/* ■ PATCHDRIVE */
/* - Set the environment variable 'PATCHDRIVE' to the drive with */
/* a patched version of your program (if any exist, see routine */
/* 'I!.__CheckPatch'). */
/* */
/*-Hints: */
/* */
/* In the default TEMPLATE catches ALL error conditions (SYNTAX, */
/* NOVALUE, HALT, FAILURE, NOTREADY and ERROR). To change this */
/* behaviour, add one or more 'SIGNAL OFF condition' - statements */
/* at the begin of the procedure MAIN. */
/* */
/* All routines declared with 'PROCEDURE' must have an 'EXPOSE' list! */
/* You MUST add the string '(EXPOSELIST)' to the expose lists of ALL */
/* procedures! */
/* If you get an internal error in the error routine, check if */
/* '(EXPOSELIST)' is included in the expose lists of ALL routines! */
/* */
/* Use only */
/* => call Log message <= */
/* to print messages on the screen. */
/* */
/* Use only */
/* => call LogDebugMsg message <= */
/* to print debugging messages on the screen. */
/* */
/* Define all global variables as 'GLOBAL.varName'. */
/* Note: If you want to define another stem with global variables */
/* you MUST add the name of the stem to the expose list of the */
/* routine 'MAIN'! */
/* */
/* Append the names of all routines, which should be executed at */
/* program end to the variable 'PROG.__EXITROUTINES'. */
/*-Example: */
/* */
/* if the program should execute the routine 'DelTempFile' */
/* at program end use the following statement: */
/* */
/* => prog.__ExitRoutines = prog.__ExitRoutines ' DelTempFile' <= */
/* */
/* Note that you can't use parameters for the routines saved in */
/* the variable 'PROG.__EXITROUTINES'! */
/* Note further that the routines are executed in the order they */
/* are saved in the variable 'PROG.__EXITROUTINES'. */
/* And last but not least: */
/* You can add new entrys to this variable in an exit routine. You */
/* can also change or delete any entry from the variable in an */
/* exit routine. */
/* You may check the variable 'PROG.__EXITCODE' in an exit routine */
/* to determine what caused the program end (see predefined */
/* return codes above) */
/* */
/* Use the following code sequence to inherit a log file to a */
/* child cmd file: */
/* */
/* => 'cmd /c ' ChildName ChildParameter prog.__logFileParm <= */
/* */
/* Use the variable 'prog.__LogALL' to direct STDOUT and STDERR */
/* of an OS/2 program into the logfile. */
/*-Example: */
/* */
/* => '@attrib ' thisFile || prog.__LogALL <= */
/* */
/* Use the variable 'prog.__LogSTDERR' to direct only STDERR of an */
/* OS/2 program into the logfile. */
/* Example: */
/* */
/* => '@attrib ' thisFile || prog.__LogSTDERR <= */
/* */
/* Use the variable 'PROG.__LogSTDOUT' to direct only STDOUT of an */
/* OS/2 program into the logfile. */
/*-Example: */
/* */
/* => '@attrib ' thisFile || prog.__LogSTDOUT <= */
/* */
/* Do NOT use 'PROG.__LogSTDERR' and 'PROG.__LogSTDOUT' in the same */
/* command (use 'PROG.__LogALL' instead) */
/* */
/* Use the variable 'global.__verbose' if you want to add debug code */
/* to your program. */
/*-Example: */
/* */
/* => if global.__verbose <> '' then <= */
/* => do <= */
/* => {debug code} <= */
/* => end <= */
/* */
/* Use the variable 'PROG.__ENV' if you want to set or get an */
/* environment variable. */
/*-Example: */
/* */
/* => MaintDrive = value( 'MaintDrive',, prog.__env ) <= */
/* */
/* */
/* REPORT ANY ERRORS and SUGGESTIONS to the author of this code. */
/* */
/* DELETE THE COMMENTS ABOVE THIS LINE IN YOUR FILES! */
/* */
/* -------------- function header prototype following --------------- */
/* ?name? - ?description? */
/* */
/* Usage: */
/* ? */
/* */
/* where: */
/* ? */
/* */
/* returns: */
/* 0 - okay */
/* else error */
/* */
/* Notes: */
/* ? */
/* */
/* History: */
/* 01.01.1980 v1.00 */
/* - initial release */
/* */
/* */
/* */
/* */
/* Based on TEMPLATE.CMD v2.52, TEMPLATE is (c) 1995 Bernd Schemmer, */
/* Baeckerweg 48, D-60316 Frankfurt, Germany, Compuserve: 100104,613 */
/* */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/*** change the following values to your need ***/
global. = '' /* init the stem global. with '' */
global.__Version = 1.0 /* Version of YOUR program */
global.__SignOnMsg = 1 /* set to 0 if you do not want the */
/* program start and end messages */
global.__NeedCID = 0 /* set to 1 if you need CID support */
global.__NeedColors = 1 /* set to 1 if you want colored msgs */
global.__NeedPatchCheck = 1 /* set to 1 if you want the program */
/* to search for a patched version of */
/* this program */
/*** End of variables to change ***/
/* HINT: The further program code is in the function MAIN */
/*** End of Part 1 of the source code of TEMPLATE.CMD ***/
/*** Start of Part 2 of the source code of TEMPLATE.CMD ***/
/*************** DO NOT CHANGE THE FOLLOWING LINES ********************/
/* names of the global variables, which all */
/* procedures must know */
exposeList = 'prog. screen. I!. global. exposeList '
/* init all global stems */
parse value '' with prog. screen. I!.
/* get the number of the first line with */
/* user code */
call I!.__GetUserCode
/* ------------------------------------------------------------------ */
/* install the error handler */
/* break errors (CTRL-C) */
CALL ON HALT NAME I!.__UserAbort
/* syntax errors */
SIGNAL ON SYNTAX NAME I!.__ErrorAbort
/* using of not initialisized variables */
SIGNAL ON NOVALUE NAME I!.__ErrorAbort
/* */
SIGNAL ON FAILURE NAME I!.__ErrorAbort
/* */
SIGNAL ON ERROR NAME I!.__ErrorAbort
/* */
SIGNAL ON NOTREADY NAME I!.__ErrorAbort
/* ------------------------------------------------------------------ */
/* init the variables */
parse arg I!.__RealParameter
prog.__QParm = '/SILENT'
/* check for the parameter /SILENT */
if pos( prog.__QParm, translate( I!.__RealParameter ) ) <> 0 then
do
parse var I!.__RealParameter prog.__Param (prog.__QParm) I!.__rest
prog.__Param = prog.__Param I!.__Rest
prog.__QuietMode = 1
end /* if pos( ... */
else
prog.__Param = I!.__RealParameter
call I!.__InitVars
/* ------------------------------------------------------------------ */
/* show program start message */
if global.__SignOnMsg = 1 then
do
screen.__CurColor = screen.__SignOnColor
call Log prog.__Name || " " || global.__version || " started on " || ,
date() || ' at ' || time() || ' ...'
screen.__CurColor = screen.__NormalColor
end /* if global.__SignOnMsg = 1 then */
/* ------------------------------------------------------------------ */
/* check if there is a patched version of */
/* this program */
if global.__NeedPatchCheck <> 0 then
call I!.__CheckPatch
/* ------------------------------------------------------------------ */
/* check for a help parameter */
if pos( translate( word( prog.__Param,1 ) ), ,
'/?/H/HELP/-?-H-HELP' ) <> 0 then
do
prog.__exitCode = 253
call I!.__CallUserProc 1, 'ShowUsage'
SIGNAL I!.__programEnd
end /* pos( translate( ... */
/* ------------------------------------------------------------------ */
/* call the main procedure */
call I!.__CallUserProc 2, 'main' prog.__Param
/* set prog.__ExitCode to the return */
/* code of the function main, if any */
/* returned */
if symbol( 'I!.__UserProcRC' ) = 'VAR' then
prog.__ExitCode = I!.__UserProcRC
/* ------------------------------------------------------------------ */
/* house keeping */
I!.__ProgramEnd:
/* call exit routines */
do while strip( prog.__exitRoutines ) <> ''
I!.__CurExitRoutine = word( prog.__ExitRoutines,1 )
/* delete the name of the routine from the */
/* list to avoid endless loops! */
prog.__ExitRoutines = substr( prog.__ExitRoutines , ,
Pos( I!.__CurExitRoutine, ,
prog.__ExitRoutines ) + ,
length( I!.__CurExitRoutine ) )
call I!.__CallUserProc 1, I!.__CurExitRoutine
end /* do while strip( prog.__ExitRoutines ) <> '' */
/* reset the current directory */
if symbol( 'prog.__CurDir' ) = 'VAR' then
call directory prog.__CurDir
if global.__SignOnMsg = 1 then
do
/* check if the exit code is decimal */
if dataType( prog.__ExitCode, "W" ) then
do
/* convert exit code to hexadecimal */
if prog.__ExitCode < 0 then
prog.__ExitCode = 65536 + prog.__ExitCode
prog.__hexExitCode = " ('" || D2X( prog.__ExitCode ) || "'x)"
end /* if .. */
else
prog.__hexExitCode = ''
/* show program end message */
screen.__CurColor = screen.__SignOnColor
call Log prog.__Name || " " || global.__Version || " ended on " || ,
date() || ' at ' || time() || ' with RC = ' || ,
prog.__ExitCode || prog.__hexExitCode
screen.__CurColor = screen.__NormalColor
end /* if global.__SignOnMsg = 1 then */
EXIT prog.__ExitCode
/* ------------------------------------------------------------------ */
/*-function: call a user defined routine */
/* (avoid errors if the routine is not defined) */
/* */
/*-call: I!.__CallUserProc errorAction, procName {prcoParameter} */
/* */
/*-where: errorAction - action, if procName is not defined */
/* 0: do nothing (only set the RC) */
/* 1: show a warning and set the RC */
/* 2: abort the program */
/* procName - name of the procedure */
/* procParameter - parameter for the procedure */
/* */
/*-returns: 1 - ok */
/* 0 - procname not found */
/* */
/*-output: I!.__UserProcRC - Returncode of the called procedure */
/* (uninitialisied if the proedure didn't */
/* reeturn a value) */
/* */
I!.__CallUserProc: PROCEDURE expose (exposeList) result rc sigl
parse arg I!.__ErrorAction , I!.__procName I!.__procParameter
I!.__thisRC = 0
drop I!.__UserProcRC
iLine = 'call ' I!.__procName
if I!.__procParameter <> '' then
do
if pos( '"' , I!.__procParameter ) = 0 then
iLine = iLine || ' "' I!.__procParameter '"'
else
iLine = iLine || " '" I!.__procParameter "'"
end /* if I!.__procParameter <> '' then */
/* I!.__MaxLength = 263 */
if length( iLine ) > 263 then
call ShowError global.__ErrorExitCode ,,
'To many parameters defined for the call of the routine "' || ,
I!.__procName || '" (The max. length for the parameter is ' || ,
263 - length( I!.__procName ) -11 || ')'
/* drop I!.__maxLength */
/*** DO NOT CHANGE, ADD OR DELETE ONE OF THE FOLLOWING FOUR LINES!! ***/
SIGNAL I!.__CallUserProc1
I!.__CallUserProc1:
I!.__InterpretCMDLine = sigl + 3
interpret iLine
/*** DO NOT CHANGE, ADD OR DELETE ONE OF THE PRECEEDING FOUR LINES! ***/
I!.__thisRC = 1
if symbol( 'RESULT' ) = 'VAR' then
I!.__UserProcRC = value( 'RESULT' )
I!.__CallUserProc2:
if I!.__ThisRC = 0 then
select
when I!.__ErrorAction = 0 then
nop
when I!.__ErrorAction = 1 then
call ShowWarning 'Can not find the routine "' || ,
I!.__procName || '"'
when I!.__ErrorAction = 2 then
call ShowError global.__ErrorExitCode , ,
'Can not find the routine "' || I!.__procName || '"'
end /* select */
RETURN I!.__thisRC
/* ------------------------------------------------------------------ */
/*-function: set the variables for the logfile handling */
/* */
/*-call: I!.__SetLogVars */
/* */
/*-input: prog.__Param - parameter for the program */
/* */
/*-output: prog.__LogFile - name of the logfile (or NUL) */
/* prog.__LogSTDERR - string to direct STDERR into the */
/* logfile */
/* prog.__LogSTDOUT - string to direct STDOUT into the */
/* logfile */
/* prog.__LogAll - string to direct STDOUT and STDERR */
/* into the logfile */
/* prog.__LogFileParm - string to inherit the logfile */
/* parameter to a child CMD */
/* prog.__Param - program parameter without the */
/* logfile parameter */
/* */
/*-returns: '' */
/* */
I!.__SetLogVars: PROCEDURE expose (exposeList)
parse var prog.__Param prog.__param "/L:" logFileName " " rest
prog.__param= prog.__Param rest
/* avoid an error if the drive is not ready */
SIGNAL OFF NOTREADY
if logFileName <> '' then
do
/* check if we can write to the logfile */
logStatus = stream( logFileName, 'c', 'OPEN WRITE')
if logStatus <> 'READY:' then
do
prog.__LogFile = 'NUL'
prog.__LogFileParm = ''
call ShowWarning 'Can not write to the logfile "' || logFileName || ,
'", the status of the logfile is "' || ,
logStatus || ,
'". Now using the NUL device for logging'
end /* if logStatus <> 'READY' then */
else
do
/* close the logfile */
call stream logFileName, 'c', 'CLOSE'
/* get the full name (incl. the path) of the */
/* logfile */
prog.__LogFile = stream( logFileName, 'c', 'QUERY EXIST' )
prog.__LogFileParm = '/L:' || prog.__LogFile
end /* else */
end /* if prog.__LogFile <> '' then */
else
prog.__LogFile = 'NUL'
prog.__LogFile = translate( prog.__LogFile )
/* variable to direct STDOUT of an OS/2 */
/* program into the logfile */
prog.__LogSTDOUT = ' 1>>' || prog.__LogFile
/* variable to direct STDERR of an OS/2 */
/* program into the logfile */
prog.__LogSTDERR = ' 2>>' || prog.__LogFile
/* variable to direct STDOUT and STDERR of */
/* an OS/2 program into the log file */
prog.__LogALL = ' 2>>' || prog.__LogFile || ' 1>>&2'
RETURN ''
/* ------------------------------------------------------------------ */
/*-function: check some environment variables */
/* */
/*-call: I!.__CheckEnvVars */
/* */
/*-where: - */
/* */
/*-returns: '' */
/* */
I!.__CheckEnvVars: PROCEDURE expose (exposeList)
/* check if we should show the debug information */
global.__verbose = value( 'verbose' ,, prog.__env )
/* check if we should not use colors */
testV = translate( value( 'ANSI' ,, prog.__env ) )
if testV = "OFF" | testV = 0 then
screen. = ''
/* check if we should not use sounds */
testV = translate( value( 'SOUND' ,, prog.__env ) )
if testV = "OFF" | testV = 0 then
prog.__noSound = 1
RETURN ''
/* ------------------------------------------------------------------ */
/*-function: convert a file or directory name to OS conventions */
/* by adding a leading and trailing quote or double quote */
/* */
/*-call: convertNameToOS dir_or_file_name */
/* */
/*-where: dir_or_file_name = name to convert */
/* */
/*-returns: converted file or directory name */
/* */
ConvertNameToOS: PROCEDURE expose (exposeList)
parse arg fn
if pos( '"', fn ) = 0 then
fn = '"' || fn || '"'
else if pos( "'", fn ) = 0 then
fn = "'" || fn || "'"
RETURN fn
/* ------------------------------------------------------------------ */
/*-function: flush the default REXX queue */
/* */
/*-call: FlushQueue */
/* */
/*-returns: '' */
/* */
FlushQueue: PROCEDURE expose (exposeList)
do while( QUEUED() <> 0 )
pull i
end /* do while( QUEUED() <> 0 ) */
RETURN ''
/* ------------------------------------------------------------------ */
/*-function: include a file if it exists */
/* */
/*-call: TryInclude( IncludeFile ) */
/* */
/*-where: IncludeFile = name of the file to include */
/* */
/*-output: prog.__rc = 0 - include file executed */
/* else: file not found */
/* */
/*-returns: '' */
/* */
/*-Note: You do not need the 'call' keyword to use this routine. */
/* */
TryInclude:
parse arg I!.__TryIncludeFile
prog.__rc = 1
if I!.__TryIncludeFile <> '' then
if stream( I!.__TryIncludeFile, 'c', 'QUERY EXIST' ) <> '' then
do
prog.__rc = 0
call Include I!.__TryIncludeFile
end /* if stream( ... */
drop I!.__TryIncludeFile
RETURN ''
/* ------------------------------------------------------------------ */
/*-function: include a file */
/* */
/*-call: Include( IncludeFile ) */
/* */
/*-where: IncludeFile = name of the file to include */
/* */
/*-returns: '' */
/* */
/*-Note: You do not need the 'call' keyword to use this routine. */
/* */
Include:
parse upper arg I!.__IncFileName
/* check if the include file exists */
if stream( I!.__IncFileName, 'c', 'QUERY EXIST') = '' then
call ShowError global.__ErrorExitCode, ,
'Can not find the include file "' || ,
I!.__IncFileName || '"'
/* read and interpret the include file */
do I!.__IncLineNO = 1 while lines( I!.__IncFileName ) <> 0
I!.__IncCurLine = ''
/* save the absolute position of the start of */
/* this line for the error handler */
I!.__IncCurLinePos = stream(I!.__IncFileName,'c','SEEK +0')
/* handle multi line statements */
do forever
I!.__IncCurLine = I!.__IncCurLine ,
strip( lineIn( I!.__IncFileName ) )
if right( I!.__IncCurLine,1 ) = ',' then
do
/* statement continues on the next line */
if lines( I!.__IncFileName ) = 0 then
call ShowError global.__ErrorExitCode ,,
'Unexpected EOF detected while reading the include file "' ||,
I!.__IncFileName || '"'
else
I!.__IncCurLine = substr( I!.__IncCurLine,1, ,
length( I!.__IncCurLine )-1 )
end /* if right( ... */
else
leave
end /* do forever */
I!.__IncActive = 1
interpret I!.__IncCurLine
I!.__IncActive = 0
end /* do I!.__IncLineNO = 1 while lines( I!.__IncFileName ) <> 0 ) */
/* close the include file! */
call stream I!.__IncFileName 'c' 'CLOSE'
RETURN ''
/* ------------------------------------------------------------------ */
/*-function: init color variables */
/* */
/*-call: I!.__InitColorVars */
/* */
/*-returns: '' */
/* */
I!.__InitColorVars: PROCEDURE expose (exposeList)
if global.__NeedColors = 1 then
do
/* delete rest of the line */
screen.__DelEOL = '1B'x || '[K'
/* save the cursor position */
screen.__SavePos = '1B'x || '[s'
/* restore the cursor position */
screen.__RestPos = '1B'x || '[u'
/* define color attributes */
screen.__AttrOff = '1B'x || '[0;m'
screen.__Highlight = '1B'x || '[1;m'
screen.__normal = '1B'x || '[2;m'
screen.__blink = '1B'x || '[5;m'
screen.__invers = '1B'x || '[7;m'
screen.__invisible = '1B'x || '[8;m'
/* define foreground color variables */
screen.__fgBlack = '1B'x || '[30;m'
screen.__fgRed = '1B'x || '[31;m'
screen.__fgGreen = '1B'x || '[32;m'
screen.__fgYellow = '1B'x || '[33;m'
screen.__fgBlue = '1B'x || '[34;m'
screen.__fgMagnenta = '1B'x || '[35;m'
screen.__fgCyan = '1B'x || '[36;m'
screen.__fgWhite = '1B'x || '[37;m'
/* define background color variables */
screen.__bgBlack = '1B'x || '[40;m'
screen.__bgRed = '1B'x || '[41;m'
screen.__bgGreen = '1B'x || '[42;m'
screen.__bgYellow = '1B'x || '[43;m'
screen.__bgBlue = '1B'x || '[44;m'
screen.__bgMagnenta = '1B'x || '[45;m'
screen.__bgCyan = '1B'x || '[46;m'
screen.__bgWhite = '1B'x || '[47;m'
/* define color variables */
screen.__ErrorColor = screen.__AttrOff || screen.__Highlight || ,
screen.__FGYellow || screen.__bgRed
screen.__NormalColor = screen.__AttrOff || ,
screen.__fgWhite || screen.__bgBlack
screen.__DebugColor = screen.__AttrOff || screen.__Highlight || ,
screen.__fgBlue || screen.__bgWhite
screen.__PromptColor = screen.__AttrOff || screen.__Highlight || ,
screen.__fgYellow || screen.__bgMagnenta
/* +++++++++++++++ DO NOT USE THE FOLLOWING COLORS! +++++++++++++++++ */
screen.__SignOnColor = screen.__AttrOff || screen.__Highlight || ,
screen.__fggreen || screen.__bgBlack
screen.__PatchColor = screen.__AttrOff || screen.__Highlight || ,
screen.__fgcyan || screen.__bgRed
/* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
/* set the default color */
screen.__CurColor = screen.__NormalColor
end /* if global.__NeedColors = 1 then */
else
do
/* init all color variables with '' */
screen. = ''
end /* else */
RETURN ''
/* ------------------------------------------------------------------ */
/*-function: init the stem prog. */
/* */
/*-call: I!.__InitProgStem */
/* */
/*-returns: '' */
/* */
/*-Note: DO NOT ADD ANY CODE TO THIS ROUTINE! */
/* */
I!.__InitProgStem: PROCEDURE expose (exposeList)
/* get drive, path and name of this program */
parse upper source . . prog.__FullName
prog.__Drive = filespec( "drive", prog.__FullName )
prog.__Path = filespec( "path", prog.__FullName )
prog.__Name = filespec( "name", prog.__FullName )
prog.__Env = 'OS2ENVIRONMENT'
prog.__CurDir = translate( directory() )
/* version of TEMPLATE.CMD */
prog.__Version = 'V2.52'
prog.__ExitCode = 0
prog.__UserAbort = 1 /* allow user aborts */
prog.__ExitRoutines = '' /* list of routines to execute at */
/* program end */
prog.__ScreenCols = 80
prog.__ScreenRows = 25
if I!.__CallUserProc( 0, 'SysTextScreenSize' ) = 1 then
if symbol( 'I!.__UserProcRC' ) = 'VAR' then
parse var I!.__UserProcRC prog.__ScreenRows prog.__ScreenCols
RETURN ''
/* ------------------------------------------------------------------ */
/*-function: init the variables for CID programs (only if the value */
/* of the variable global.__NeedCID is 1) */
/* */
/*-call: I!.__InitCIDVars */
/* */
/*-returns: '' */
/* */
/*-Note: DO NOT ADD ANY CODE TO THIS ROUTINE! */
/* Returncodes as defined by LCU 2.0 */
/* */
I!.__InitCIDVars: PROCEDURE expose (exposeList) exposeList CIDRC.
if global.__NeedCID = 1 then
do
/* define return codes for CID programs */
CIDRC.__successful_program_termination = C2D('0000'x, 2);
CIDRC.__successful_log_warning_message = C2D('0004'x, 2);
CIDRC.__successful_log_error_Message = C2D('0008'x, 2);
CIDRC.__successful_log_severe_error = C2D('0012'x, 2);
CIDRC.__data_resource_not_found = C2D('0800'x, 2);
CIDRC.__data_resource_already_in_use = C2D('0804'x, 2);
CIDRC.__data_resource_Noauthorization = C2D('0808'x, 2);
CIDRC.__data_path_not_found = C2D('0812'x, 2);
CIDRC.__product_not_configured = C2D('0816'x, 2);
CIDRC.__storage_medium_exception = C2D('1200'x, 2);
CIDRC.__device_Not_Ready = C2D('1204'x, 2);
CIDRC.__not_enough_diskspace = C2D('1208'x, 2);
CIDRC.__incorrect_program_invocation = C2D('1600'x, 2);
CIDRC.__unexpected_condition = C2D('1604'x, 2);
CIDRC.__successfull_reboot = C2D('FE00'x, 2);
CIDRC.__successfull_reboot_with_warning = C2D('FE04'x, 2);
CIDRC.__successfull_reboot_with_errmsg = C2D('FE08'x, 2);
CIDRC.__successfull_reboot_with_server_errMsg = C2D('FE12'x, 2);
/* xx = next state of the program */
/* CIDRC.__successfull_reboot_with_callback = C2D('FFxx'x, 2); */
/* define exit code values */
global.__ErrorExitCode = CIDRC.__unexpected_condition
global.__OKExitCode = CIDRC.__successful_program_termination
/* add the stem CIDRC. to the exposeList */
exposeList = exposeList || ' CIDRC. '
end /* if global.__NeedCID = 1 then */
RETURN ''
/* ------------------------------------------------------------------ */
/*-function: init program vars */
/* */
/*-call: I!.__InitVars */
/* */
/*-returns: '' */
/* */
/*-Note: DO NOT ADD ANY CODE TO THIS ROUTINE! */
/* */
I!.__InitVars:
/* define exit code values */
global.__ErrorExitCode = 255
global.__OKExitCode = 0
/* define the stem prog. */
call I!.__InitProgStem
/* define the color variables */
call I!.__InitColorVars
/* define the variables for CID programs */
call I!.__InitCIDVars
/* check some environment variables */
call I!.__CheckEnvVars
/* check if there is a logfile parameter */
call I!.__SetLogVars
/* init the program exit code */
prog.__ExitCode = global.__OKExitCode
RETURN ''
/*** End of Part 2 of the source code of TEMPLATE.CMD ***/
/*** Start of Part 3 of the source code of TEMPLATE.CMD ***/
/* ------------------------------------------------------------------ */
/*-function: load a dll */
/* */
/*-call: */
/* thisRC = LoadDll( registerFunction, dllName, entryPoint, */
/* ,{deRegisterFunction},{checkFunction} */
/* ,{IgnoreRxFuncAddRC},{RegisterErrorRC} */
/* ,{errorAction} */
/* */
/*-where: */
/* registerFunction = name of the dll init function */
/* (e.g. "SysLoadFuncs") */
/* dllName = name of the dll */
/* (e.g. "REXXUTIL") */
/* entryPoint = entryPoint for the dll init function */
/* (e.g. "SysLoadFuncs") */
/* deRegisterFunction = name of the dll exit function */
/* (e.g. "SysDropFuncs") */
/* If this parameter is entered, the */
/* deRegisterFunction is automaticly called */
/* at program end if the loading of the dll */
/* was successfull. */
/* checkFunction = function which must be loaded if the dll is */
/* loaded (def.: none -> always load the dll) */
/* Note: */
/* Do not use the registerFunction for this */
/* parameter! A good candidate for this */
/* parameter is the deRegisterFunction. */
/* IgnoreRxFuncAddRC = 1: ignore the rc from rxFuncAdd */
/* 0: do not ignore the rc from rxFuncAdd */
/* (def.: 0) */
/* RegisterErroRC = returncode of the dll init function */
/* indicating a load error */
/* (def. none, -> ignore the returncode of the */
/* dll init function) */
/* actionCode = 1: abort program if loading failed */
/* 0: do not abort program if loading failed */
/* (def.: 1) */
/* */
/*-returns: */
/* 0 - loading failed */
/* 1 - dll loaded */
/* 2 - dll already loaded */
/* */
/*-Note: */
/* See the routine MAIN for some examples for using LoadDLL. */
/* LoadDLL can only handle dlls with an init function to register */
/* the further routines in the dll (like the function SysLoadFuncs */
/* in the dll REXXUTIL). */
/* */
LoadDll: PROCEDURE expose (exposeList)
parse arg registerFunction , ,
dllName , ,
entryPoint , ,
deRegisterFunction , ,
checkFunction , ,
ignoreRXFuncAddRC, ,
registerErrorRC, ,
errorAction
/* check the neccessary parameters */
if entryPoint = '' | dllName = '' | registerFunction = '' then
call ShowError global.__ErrorExitCode, 'Invalid call to LOADDLL'
if ignoreRXFuncAddRC = '' then
ignoreRXFuncAddRc = 0
if errorAction = '' then
errorAction = 1
I!.__LoadDLLRc = 0
/* if the 'checkFunction' is missing, we */
/* assume that the dll is not loaded */
if ( CheckFunction <> '' ) then
do
/* check if the dll is loaded */
dllNotLoaded = rxFuncQuery( CheckFunction )
end /* if checkFunction <> '' then */
else
dllNotLoaded = 1
if dllNotLoaded then
do
/* load the dll and register the init */
/* function of the dll */
rxFuncAddRC = rxFuncAdd( RegisterFunction, dllName, entryPoint )
if \ rxFuncAddRC | ignoreRxFuncAddRC then
do
if I!.__CallUserProc( 0, RegisterFunction ) = 0 then
I!.__DllInitRC = 'ERROR'
else
I!.__DllInitRC = 0
if ( registerErrorRC <> '' & I!.__DLLInitRC = registerErrorRC ) | ,
( I!.__DllInitRC = 'ERROR' ) then
do
nop
end /* if ( registerErrorRC <> '' & ... */
else
do
/* add the dll deregister function to the */
/* program exit routine list */
if DeRegisterFunction <> '' then
if \ rxFuncQuery( DeRegisterFunction ) then
prog.__ExitRoutines = prog.__ExitRoutines || ' ' || ,
DeRegisterFunction
I!.__LoadDLLRc = 1
end /* else */
end /* if \ rxFuncAddRC | ignoreRxFuncAddRC then */
end /* if dllNotLoaded then */
else
do
/* dll is already loaded */
I!.__LoadDLLRc = 2
end /* else */
if errorAction = 1 & I!.__LoadDLLRC = 0 then
call ShowError global.__ErrorExitCode, 'Can not load the dll "' || ,
dllName || '"'
RETURN I!.__LoadDLLRc
/* ------------------------------------------------------------------ */
/*-function: show a string with word wrapping */
/* */
/*-call: showString Prefix, thisString */
/* */
/*-where: */
/* Prefix = prefix for the first line (e.g. "*-*" or "#" to */
/* use # leading blanks, # = 1 ... n ) */
/* thisString - string to print */
/* */
/*-returns: '' */
/* */
ShowString: PROCEDURE EXPOSE (exposeList)
parse arg Prefix, StringToShow
maxLineLength = prog.__ScreenCols-4
if datatype( prefix, 'W' ) = 1 then
prefix = copies( ' ' , prefix )
maxWordLength = maxLineLength - length( prefix )
thisRC = 0
SE.thisString = ''
do i = 1 to words( StringToShow)
printString = 0
SE.thisString = SE.thisString || word( StringToShow, i ) || ' '
if length( SE.thisString ) + ,
length( word( StringToShow, i+1 ) ) > maxLineLength then
printString = 1
if printString = 1 | i = words( StringToShow ) then
do
if length( prefix || SE.ThisString ) > prog.__ScreenCols then
do
do until SE.thisString = ''
parse var SE.thisString SE.thisString1 =(maxWordLength) ,
SE.thisString
call log left( prefix || SE.thisString1, prog.__ScreenCols )
prefix = copies( ' ', length( prefix ) )
end /* do until SE.thisString = '' */
end /* if length( ... */
else
call Log left( prefix || SE.thisString, prog.__ScreenCols )
SE.thisString = ''
prefix = copies( ' ', length( prefix ) )
end /* if length( ... */
end /* do i = 1 to words( StringToShow */
RETURN ''
/* ------------------------------------------------------------------ */
/*-function: show a warning message */
/* */
/*-call: showWarning message */
/* */
/*-where: warningMessage - warning Message */
/* */
/*-returns: '' */
/* */
ShowWarning: PROCEDURE expose (exposeList)
parse arg warningMessage
screen.__CurColor = screen.__ErrorColor
warningMessage = warningMessage || '!'
call Log ''
call I!.__LogSeparator
call ShowString ' Warning: ', warningMessage
call I!.__LogSeparator
screen.__CurColor = screen.__NormalColor
call Log ''
RETURN ''
/* ------------------------------------------------------------------ */
/*-function: show an error message and end the program */
/* */
/*-call: ShowError exitCode, errorMessage */
/* */
/*-where: ExitCode - no of the error (= program exit code) */
/* errorMessage - error Message */
/* */
/*-returns: nothing */
/* */
/*-Note: THIS ROUTINE WILL NOT COME BACK!!! */
/* */
ShowError: PROCEDURE expose (exposeList)
parse arg prog.__ExitCode, prog.__errorMessage
prog.__I!QuietMode = prog.__QuietMode
/* turn quiet mode off */
prog.__QuietMode = ''
screen.__CurColor = screen.__ErrorColor
prog.__errorMessage = prog.__errorMessage || '!'
call Log ''
call I!.__LogSeparator
call Log left(' Error ' || prog.__ExitCode || ' detected! ' || ,
'The error message is: ',prog.__ScreenCols )
call ShowString 1, prog.__errorMessage
call I!.__LogSeparator
call Log ''
/* restore quiet mode status */
prog.__QuietMode = prog.__I!QuietMode
if prog.__NoSound <> 1 then
do
call beep 537,300
call beep 237,300
call beep 537,300
end /* if prog.__NoSound <> 1 then */
SIGNAL I!.__ProgramEnd
RETURN
/* ------------------------------------------------------------------ */
/*-function: log a debug message and clear the rest of the line */
/* */
/*-call: logDebugMsg message */
/* */
/*-where: message - message to show */
/* */
/*-returns: '' */
/* */
/*-Note: You do not need the 'call' keyword to use this routine. */
/* */
LogDebugMsg: PROCEDURE expose (exposeList)
if global.__verbose <> '' then
do
parse arg debugMessage
screen.__CurColor = screen.__DebugColor
call Log '+++' debugMessage
screen.__CurColor = screen.__NormalColor
end /* if global.__verbose <> '' then */
RETURN ''
/* ------------------------------------------------------------------ */
/*-function: write a separator line to the screen and to the logfile */
/* */
/*-call: I!.__LogSeparator */
/* */
/*-returns: '' */
/* */
I!.__LogSeparator: PROCEDURE expose (exposeList)
call Log ' ' || left('-', prog.__ScreenCols-2, '-' ) || ' '
RETURN
/* ------------------------------------------------------------------ */
/*-function: log a message and clear the rest of the line */
/* */
/*-call: log message */
/* */
/*-where: message - message to show */
/* */
/*-returns: '' */
/* */
/*-Note: You do not need the 'call' keyword to use this routine. */
/* */
Log: PROCEDURE expose (exposeList)
parse arg message
logMessage = message
do i = 1 to words( prog.__LogExcludeWords )
curWord = word( prog.__LogExcludeWords, i )
curLength = length( curWord )
do until j = 0
j = Pos( curWord, logMessage )
if j <> 0 then
logMessage = delstr( logMessage, j, curLength )
end /* do until j = 0 */
end /* do i = 1 to words( prog.__LogExcludeWords ) */
if prog.__QuietMode = '' then
do
if length( logMessage) = prog.__ScreenCols then
call charout prog.__STDOUT, screen.__CurColor || ,
message || screen.__AttrOff
else
call lineOut prog.__STDOUT, screen.__CurColor || ,
message || screen.__AttrOff ||,
screen.__DelEOL
end /* if prog.__Quietmode = '' then */
if symbol( 'prog.__LogFile' ) = 'VAR' then /* v2.52 */
if prog.__LogFile <> '' then
do
call lineout prog.__LogFile, logMessage
/* close the logfile */
rc = stream( prog.__LogFile, 'c', 'CLOSE')
end /* if prog.__LogFile <> '' then */
RETURN ''
/* ------------------------------------------------------------------ */
/*-function: check if there is a patched version of this program */
/* */
/*-call: I!.__CheckPatch */
/* */
/*-returns: '' */
/* */
/*-Note: I!.__RealParameter must contain the parameters for */
/* this program. */
/* The variables prog.__Path and prog.__Name must be set! */
/* This procedure ends the program with an EXIT command! */
/* */
I!.__CheckPatch: PROCEDURE expose (exposeList)
/* get the drive with patch cmd files */
patchDrive = translate( value( 'patchDrive',, prog.__Env) )
if patchDrive <> '' & patchDrive <> prog.__Drive then
do
patchedVersion = patchDrive || prog.__Path || prog.__Name
/* check if a patched program version exists */
if stream( patchedVersion, 'c', 'QUERY EXISTS') <> "" then
do
cmdLine= patchedVersion || " " || I!.__Realparameter
screen.__CurColor = screen.__PatchColor
call Log left( ' Calling patched version ' patchedVersion || ,
' ...', prog.__ScreenCols )
screen.__CurColor = screen.__AttrOff
call I!.__LogSeparator
'cmd /c ' cmdLine
screen.__CurColor = screen.__AttrOff
call I!.__LogSeparator
screen.__CurColor = screen.__PatchColor
call Log left( ' ... the patched version endet with RC = ' || ,
rc, prog.__ScreenCols )
exit rc
end /* if stream( ... */
end /* if patchDrive <> '' */
RETURN ''
/* ------------------------------------------------------------------ */
/*-function: error handler for unexpected errors */
/* */
/*-call: DO NOT CALL THIS ROUTINE BY HAND!!! */
/* */
/*-returns: nothing */
/* */
/*-input: I!.__IncActive: */
/* if 1 the error occured while executing an include file */
/* statement. In this case the following variables are */
/* also used (Note that this variables are automaticly */
/* set by the routine INCLUDE()): */
/* I!.__IncLineNo */
/* Line no. of the include file */
/* I!.__IncFileName: */
/* Name of the include file */
/* I!.__IncCurLinePos: */
/* Fileposition of the first char of the line causing */
/* the error */
/* */
/*-Note: THIS FUNCTION ABORTS THE PROGRAM WITH A JUMP TO THE */
/* LABEL I!.__PROGRAMEND!!! */
/* */
I!.__ErrorAbort:
/* check if the error occured in the error */
/* handler */
if I!.__errorLineNo = sigl then
do
call beep 637,300; call beep 437,300; call beep 637,300
call charout 'STDERR:',, /* v2.52 */
'0D0A'x ,
'Fatal Error: Error in the error handler detected!' '0D0A'x ,
'0D0A'x ,
'Linenumber: ' || sigl || '0D0A'x ,
'Errorname: ' || condition('C') '0D0A'x ,
'Errordescription: ' || condition('D') '0D0A'x ,
'0D0A'x ,
'The program exit routines were not called!' '0D0A'x ,
'Check if "(EXPOSELIST)" is included in the ' || ,
'expose lists of all procedures!' '0D0A'x
call beep 637,300 ; call beep 437,300 ; call beep 637,300
exit 255
end /* if I!.__errorLineNo = sigl then */
/* get the number of the line causing the */
/* error */
I!.__errorLineNo = sigl
/* get the name of this error */
I!.__ErrorName = condition('C')
/* get further information for this error */
/* if available */
I!.__ErrorCondition = condition('D')
if I!.__ErrorCondition <> '' then
I!.__ErrorCondition = ' (Desc.: "' || I!.__ErrorCondition || '")'
if datatype( prog.__ScreenCols, 'W' ) <> 1 then
prog.__ScreenCols = 80
if SYMBOL( 'prog.__Name' ) <> 'VAR' | value( 'prog.__Name' ) = '' then
if I!.__errorLineNO < I!.__FirstUserCodeLine then
I!.__pName = '**Runtimte**'
else
I!.__pName = '***???***'
else
i!.__pName = prog.__Name
/* reInstall the error handler */
/* v2.52 */
INTERPRET 'SIGNAL ON ' value(condition('C')) ' NAME I!.__ErrorAbort'
/* check, if we should ignore the error */
if value( 'sigl' ) = value( 'I!.__InterpretCMDLine' ) then
SIGNAL I!.__CallUserProc2
screen.__CurColor = screen.__ErrorColor
prog.__I!QuietMode = prog.__QuietMode
/* turn quiet mode off */
prog.__QuietMode = ''
/* init variables for printing the line */
/* causing the error to the screen */
I!.__ThisSRCLine = ''
I!.__ThisPrefix = ' *-* '
call Log ''
call I!.__LogSeparator
call ShowString ' ' || I!.__pName || ' - ', I!.__ErrorName || ,
I!.__ErrorCondition || ' error detected!'
/* check, if the RC is meaningfull for this */
/* error */
if pos( I!.__ErrorName, 'ERROR FAILURE SYNTAX' ) <> 0 then
do
if datatype(rc, "W") = 1 then
if I!.__ErrorName = 'SYNTAX' then
if rc > 0 & rc < 100 then
call Log left( ' The error code is ' || rc || ,
', the REXX error message is: ' || ,
errorText( rc ), ,
prog.__ScreenCols )
else
call log left( ' The error code ' || rc || ,
', this error code is unknown.',,
prog.__ScreenCols )
else
call Log left( ' The RC is ' || rc || '.', prog.__ScreenCols )
end /* if pos( ... */
if value( 'I!.__IncActive' ) = 1 then
do
/* error occured while interpreting an include file */
call ShowString 1, 'The error occured while executing the line ' || ,
I!.__IncLineNo || ' of the include file "' || ,
I!.__IncFileName || '".'
/* reset the file pointer of the include file */
/* to the start of the line causing the error */
dummy = stream( I!.__IncFileName, 'c', 'SEEK =' || ,
I!.__IncCurLinePos )
I!.__SrcAvailable = stream( I!.__IncFileName, ,
'c', 'QUERY EXIST' ) <> ''
end
else
do
call ShowString 1, 'The error occured in line ' ||,
I!.__errorLineNo || '.'
I!.__thisLineNo = I!.__errorLineNo
/* error occured in this file */
/* check if the sourcecode is available */
SIGNAL ON SYNTAX NAME I!.__NoSourceCode
I!.__inMacroSpace = 1
I!.__SrcAvailable = 0
if sourceLine( I!.__errorLineNo ) <> '' then
I!.__SrcAvailable = 1
SIGNAL ON SYNTAX NAME I!.__ErrorAbort
I!.__inMacroSpace = 0
end /* else */
/* print the statement causing the error to */
/* the screen */
if I!.__SrcAvailable = 1 then
do
call Log left( " The line reads: ", prog.__ScreenCols )
I!.__InterpretVar = 0
/* read the line causing the error */
call I!.__GetSourceLine
I!.__FirstToken = strip(word( I!.__ThisSRCLine,1))
if translate( I!.__FirstToken ) = 'INTERPRET' then
do
parse var I!.__ThisSRCLine (I!.__FirstToken) ,
I!.__interpretValue
I!.__InterpretVar = 1
end /* if I!.__thisLineNo = I!.__errorLineNo */
/* handle multi line statements */
do forever
call ShowString I!.__ThisPrefix, I!.__ThisSRCLine
if right( strip( I!.__ThisSRCLine),1 ) <> ',' then
leave
I!.__ThisPrefix = 5
call I!.__GetSourceLine
end /* do forever */
if I!.__InterpretVar = 1 then
do
I!.__interpretValue = strip( word(I!.__interpretValue,1) )
if symbol( I!.__interpretValue ) = 'VAR' then
do
call Log left( '', prog.__ScreenCols )
call Log left( ' The value of "' || I!.__interpretValue || ,
'" is:', prog.__ScreenCols )
call ShowString ' >V> ', value( I!.__interpretValue )
end /* if symbol( I!.__interpretValue ) = 'VAR' then */
end /* if I!.__InterpretVar = 1 */
end /* if I!.__SrcAvailable = 1 then do */
else
call Log left( ' The sourcecode for this line is not available',,
prog.__ScreenCols )
I!.__NoSourceCode:
SIGNAL ON SYNTAX NAME I!.__ErrorAbort
if I!.__inMacroSpace = 1 then
do
parse source . . I!.__thisProgName
if fileSpec( 'drive', I!.__thisProgName ) = '' then
call ShowString 1, ' The sourcecode for this line is not' || ,
' available because the program is in' || ,
' the macro space.'
else
call ShowString 1, ' The sourcecode for this line is not' || ,
' available because the program is unreadable.'
end /* if I!.__inMacroSpace = 1 then */
call I!.__LogSeparator
call Log ''
prog.__ExitCode = global.__ErrorExitCode
if prog.__NoSound <> 1 then
do
call beep 137,300; call beep 337,300; call beep 137,300
end /* if prog.__NoSound <> 1 then */
if global.__verbose = 'DEBUG' then
do
/* enter interactive debug mode */
trace ?a
nop
end /* if global.__verbose = 'DEBUG' then */
/* restore quiet mode status */
prog.__QuietMode = prog.__I!QuietMode
SIGNAL I!.__programEnd
/* ------------------------------------------------------------------ */
/*-function: get the sourceline causing an error (subroutine of */
/* I!.__ErrorAbort) */
/* */
/*-call: DO NOT CALL THIS IN YOUR CODE!!! */
/* */
/*-returns: '' */
/* */
/*-Note: - */
/* */
I!.__GetSourceLine:
if I!.__IncActive = 1 then
I!.__ThisSRCLine = lineIn( I!.__IncFileName )
else
do
I!.__ThisSRCLine = sourceLine( I!.__ThisLineNo )
I!.__ThisLineNo = I!.__ThisLineNo + 1
end /* else */
RETURN ''
/* ------------------------------------------------------------------ */
/*-function: error handler for user breaks */
/* */
/*-call: DO NOT CALL THIS ROUTINE BY HAND!!! */
/* */
/*-returns: nothing */
/* */
/*-Note: THIS FUNCTION ABORTS THE PROGRAM WITH A JUMP TO THE */
/* LABEL I!.__PROGRAMEND IF prog.__UserAbort IS NOT 0!!! */
/* */
/* In exit routines you may test if the variable */
/* prog.__ExitCode is 254 to check if the program */
/* was aborted by the user. */
/* */
I!.__UserAbort:
/* reinstall the error handler */
CALL ON HALT NAME I!.__UserAbort
/* check if user aborts are allowed */
if prog.__UserAbort = 0 then
RETURN /* CTRL-BREAK not allowed */
prog.__I!QuietMode = prog.__QuietMode
/* turn quiet mode off */
prog.__QuietMode = ''
call Log ''
screen.__CurColor = screen.__ErrorColor
call I!.__LogSeparator
call Log left( ' Program aborted by the user', prog.__ScreenCols )
call I!.__LogSeparator
screen.__CurColor = screen.__NormalColor
prog.__ExitCode = 254
/* restore quiet mode status */
prog.__QuietMode = prog.__I!QuietMode
SIGNAL I!.__ProgramEnd
/* ------------------------------------------------------------------ */
/*-function: get the no. of the first line with the user code */
/* */
/*-call: DO NOT CALL THIS ROUTINE BY HAND!!! */
/* */
/*-returns: nothing */
/* */
/* */
I!.__GetUserCode:
/*** DO NOT CHANGE, ADD OR DELETE ONE OF THE FOLLOWING FOUR LINES!! ***/
SIGNAL I!.__GetUserCode1
I!.__GetUserCode1:
I!.__FirstUserCodeLine = sigl + 4
/*** DO NOT CHANGE, ADD OR DELETE ONE OF THE PRECEEDING FOUR LINES! ***/
RETURN
/********************** End of Runtime Routines ***********************/
/**********************************************************************/
/*** End of Part 3 of the source code of TEMPLATE.CMD ***/
/*** Start of Part 4 of the source code of TEMPLATE.CMD ***/
/* ------------------------------------------------------------------ */
/*-function: main procedure of the program */
/* */
/*-call: called by the runtime system with: */
/* => call main parameter_of_the_program <= */
/* */
/*-returns: program return code */
/* If no return code is returned, the value of the variable */
/* prog.__ExitCode is returned to the calling program. */
/* */
/*-Note: YOU MUST FILL THIS ROUTINE WITH CODE. */
/* If you want to add further global variables you MUST add */
/* them to the expose list of the procedure MAIN! */
/* */
Main: PROCEDURE expose (exposeList)
/* get the parameter of the program */
/*** SUBSTITUTE template WITH THE TEMPLATE ***/
/*** FOR THE PROGRAM PARAMETERS ***/
parse arg template
/* ------------------------------------------ */
/* you may turn some error handling off here */
/* with the statement */
/* SIGNAL OFF condition */
/* where condition is one off ERROR, SYNTAX, */
/* FAILURE, NOTREADY or NOVALUE. */
/* Example: */
/* To handle returncodes not equal zero of OS */
/* commands in your program yourself you MUST */
/* use the statement */
/* => SIGNAL OFF ERROR <= */
/* Use 'prog.__UserAbort = 0' to suppress */
/* CTRL-BREAK. */
/* ------------------------------------------ */
/* Use the function LoadDll to load all */
/* neccessary dlls */
/* Examples: */
/*
/* load the dll REXXUTIL */
global.__rexxUtilLoaded = LoadDll(,
'SysLoadFuncs', , /* dll init function */
'REXXUTIL', , /* dll name */
'SysLoadFuncs', , /* dll init entry point */
'SysDropFuncs', , /* dll exit function */
'SysDropFuncs', , /* check function */
0, , /* 1: ignore rc of rxfuncadd */
'', , /* errorcode of the init function */
1 ) /* 1: abort if loading failed */
/* 0: do not abort if loading failed */
*/
/*
/* load the dll RXWIN30 (Quercus System) */
global.__rxwin30Loaded = LoadDll( ,
'w_register', 'rxwin30', 'rxwindow', ,
'w_deRegister', 'w_open', 0, '', 0 )
*/
/*
/* load the dll VREXX (IBM EWS) */
global.__vrexxLoaded = LoadDll( 'VINIT', 'VREXX', 'VINIT', ,
'VEXIT', '', 1 ,'ERROR' , 0 )
*/
/* ------------------------------ */
/*** INSERT THE MAIN PROGRAM CODE HERE ***/
/* ------------------------------ */
/* exit the program */
/* Note: The program exit code is the return */
/* code of the routine MAIN */
/* If MAIN returns nothing, the program */
/* exit code is the current value of */
/* the variable "prog.__ExitCode" after */
/* executing MAIN. */
RETURN
/* ------------------------------------------------------------------ */
/*** INSERT FURTHER SUBROUTINES HERE ***/
/*** Note: Do not forget the string 'EXPOSELIST' in the exposeList ***/
/*** of ALL procedures! ***/
/* ------------------------------------------------------------------ */
/*-function: Show the invocation syntax */
/* */
/*-call: called by the runtime system with */
/* => call ShowUsage <= */
/* */
/*-where: - */
/* */
/*-returns: '' */
/* */
/*-Note: YOU SHOULD FILL THIS ROUTINE WITH CODE. */
/* You may change the return code for your program in this */
/* routine. The default for the return code is 253. */
/* (The variable for the return code is prog.__ExitCode) */
/* */
/* */
ShowUsage: PROCEDURE expose (exposeList)
/*** INSERT THE CODE TO SHOW THE INVOCATION SYNTAX HERE ***/
call log ' Usage: ' || prog.__name || ' {/L:logfile} {/H} {/Silent}'
RETURN ''
/*** End of Part 4 of the source code of TEMPLATE.CMD ***/
/**********************************************************************/