Source code of TEMPLATE.CMD - part 2
/*** 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 ' exposeList
/* check the type of the base message number */
if datatype( global.__BaseMsgNo, 'W' ) <> 1 then
global.__BaseMsgNo = 1000
/* init internal variables */
I!. = ''
/* save default STDOUT and STDERR */
if symbol( 'prog.__STDOUT' ) = 'VAR' then
I!.__2 = prog.__STDOUT
if symbol( 'prog.__STDERR' ) = 'VAR' then
I!.__3 = prog.__STDERR
/* init the stems prog. & screen. */
parse value '' with prog. screen.
/* reset the timer */
call time 'R'
/* restore default STDOUT and STDERR */
prog.__STDOUT = I!.__2; prog.__STDERR = I!.__3
/* 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
/* failure condition */
SIGNAL ON FAILURE NAME I!.__ErrorAbort
/* error condition */
SIGNAL ON ERROR NAME I!.__ErrorAbort
/* disk not ready condition */
SIGNAL ON NOTREADY NAME I!.__ErrorAbort
/* ------------------------------------------------------------------ */
/* init the variables */
/* get & save the parameter */
parse arg I!.__RealParam 1 prog.__Param
/* init the variables */
/* define exit code values */
global.__ErrorExitCode = 255
global.__OKExitCode = 0
/* init the compound variable prog. */
call I!.__InitProgStem
/* define the variables for CID programs */
call I!.__InitCIDVars
/* init the program exit code */
prog.__ExitCode = global.__OKExitCode
/* check the parameter and env. variables */
/* This must run before I!.__InitColorVars! */
call I!.__chkPandE
/* define the color variables */
call I!.__InitColorVars
/* check if there is a logfile parameter */
call I!.__SetLogVars
/* ------------------------------------------------------------------ */
/* show program start message */
call I!.__SignMsg
/* ------------------------------------------------------------------ */
/* check if there is a patched version of this program */
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' strip( prog.__Param )
/* use the return code of 'main' as exitcode */
/* if a returncode was returned */
if symbol( 'I!.__UserProcRC' ) == 'VAR' then
prog.__ExitCode = I!.__UserProcRC
/* ------------------------------------------------------------------ */
/* house keeping */
I!.__ProgramEnd:
/* call the exit routines */
do while prog.__exitRoutines <> ''
/* delete the name of the routine from the */
/* list to avoid endless loops! */
parse var prog.__ExitRoutines I!.__cer prog.__ExitRoutines
call I!.__CallUserProc 1, I!.__cer
end /* do while prog.__ExitRoutines <> '' */
/* restore the current directory */
if symbol( 'prog.__CurDir' ) == 'VAR' then
call directory prog.__CurDir
/* show sign off message */
call I!.__SignMsg 'E'
EXIT prog.__ExitCode
/* ------------------------------------------------------------------ */
/* function: show the sign on or sign off message */
/* */
/* call: I!.__SignMsg which */
/* */
/* where: which - 'E' - show the sign off message */
/* else show the sign on message */
/* */
/* returns: nothing */
/* */
I!.__SignMsg: PROCEDURE expose (exposeList)
if global.__SignOnMsg <> 1 then
RETURN
/* default: program start message */
i = 12
if arg(1) = 'E' then
do
i = 13
/* program end message */
i!.__rc1 = prog.__ExitCode
/* check if the exit code is decimal */
/* and convert it to hexadecimal if */
/* possible */
if dataType( prog.__ExitCode, 'W' ) then
do
if prog.__ExitCode < 0 then
prog.__ExitCode = 65536 + prog.__ExitCode
i!.__rc2 = D2X( prog.__ExitCode )
end /* if .. */
end /* if arg(1) = 'E' then */
screen.__CurColor = screen.__SignOnColor
call Log I!.__GetMsg( i, prog.__Name, global.__Version, date(),,
time(), i!.__rc1, i!.__rc2 )
screen.__CurColor = screen.__NormalColor
RETURN
/* ------------------------------------------------------------------ */
/* function: call a user defined routine */
/* (avoid errors if the routine is not defined) */
/* */
/* call: I!.__CallUserProc errorAction, procName {procParameter} */
/* */
/* 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 */
/* (dropped if the proedure don't */
/* return a value) */
/* */
I!.__CallUserProc: PROCEDURE expose (exposeList) result rc sigl
parse arg I!.__ErrorAction , I!.__ProcN I!.__ProcP
I!.__thisRC = 0
drop I!.__UserProcRC
iLine = 'call ' I!.__ProcN
if prog.__Trace = 1 & I!.__ProcN = 'main' then
iLine = 'trace ?a;'|| iLine
/** DO NOT CHANGE, ADD OR DELETE ONE OF THE FOLLOWING SEVEN LINES!!! **/
I!.__ICmdLine = GetLineNo()+2+(I!.__ProcP <> '')*2 /*!*/
if I!.__ProcP = '' then /*!*/
interpret iLine /*!*/
else /*!*/
interpret iLine "I!.__ProcP" /*!*/
/** DO NOT CHANGE, ADD OR DELETE ONE OF THE PRECEEDING SEVEN LINES!! **/
/* Caution: The CALL statement changes the variable RESULT! */
I!.__0 = trace( 'off' )
I!.__thisRC = 1
if symbol( 'RESULT' ) == 'VAR' then
I!.__UserProcRC = value( 'RESULT' )
/* this label is used if the interpret command */
/* ends with an error */
I!.__CallUserProc2:
if I!.__ThisRC = 0 then
do
if I!.__ErrorAction = 2 then
call ShowError global.__ErrorExitCode , ,
I!.__GetMsg( 1, I!.__ProcN )
if I!.__ErrorAction = 1 then
call ShowWarning I!.__GetMsg( 1 , I!.__ProcN )
end /* if I!.__thisRC = 0 then */
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: nothing */
/* */
I!.__SetLogVars: PROCEDURE expose (exposeList)
parse var prog.__Param prog.__param '/L:' logFileName ' ' rest
if left( logFileName,1 ) = '"' then /* v3.07 */
parse value logFileName rest with '"' logFilename '"' rest
prog.__param = prog.__Param rest
/* avoid an error if the drive is not ready */
SIGNAL OFF NOTREADY
/* default log device is the NUL device */
prog.__LogFile = 'NUL'
if logFileName <> '' then
do
/* check if we can write to the logfile */
logStatus = stream( logFileName, 'c', 'OPEN WRITE')
if logStatus <> 'READY:' then
do
prog.__LogFileParm = ''
call ShowWarning I!.__GetMsg( 2, logFileName, logStatus )
end /* if logStatus <> 'READY:' then */
else
do
/* close the logfile */
call stream logFileName, 'c', 'CLOSE'
/* get the fully qualified name of the */
/* logfile */
/* v3.04 */
parse upper value stream( logFileName, 'c', 'QUERY EXIST' ) WITH prog.__LogFile
prog.__LogFileParm = '/L:"' || prog.__LogFile || '"'
end /* else */
end /* if prog.__LogFile <> '' then */
fn = ConvertNameToOS( prog.__LogFile )
/* variable to direct STDOUT of an OS/2 */
/* program into the logfile */
prog.__LogSTDOUT = ' 1>>' || fn
/* variable to direct STDERR of an OS/2 */
/* program into the logfile */
prog.__LogSTDERR = ' 2>>' || fn
/* variable to direct STDOUT and STDERR of */
/* an OS/2 program into the log file */
prog.__LogALL = prog.__LogSTDERR '1>>&2'
RETURN
/* ------------------------------------------------------------------ */
/* function: check the parameter and the environment variables for */
/* the runtime system */
/* */
/* call: I!.__chkPandE */
/* */
/* input: prog.__Param - parameter for the program */
/* prog.__env - name of the environment */
/* */
/* output: prog.__QuietMode - 1 if parameter '/Silent' found */
/* or environment variable SILENT set */
/* prog.__NoSound - 1 if parameter '/NoSound' found */
/* or environment variable SOUND set */
/* screen. - "" if parameter '/NoANSI' found */
/* or environment variable ANSI set */
/* prog.__Param - remaining parameter for the procedure */
/* MAIN. */
/* prog.__Trace - 1 if parameter '/Trace' found */
/* or if the environment variable */
/* RXTTRACE is set to MAIN */
/* */
/* returns: nothing */
/* */
I!.__chkPandE: PROCEDURE expose (exposeList)
global.__verbose = value( 'VERBOSE' ,, prog.__env )
o!.0 = 4 /* no. of known parameters */
/* and environment variables */
o!.1.parm = '/SILENT' /* parameter name */
o!.1.env = 'SILENT' /* name of the env. var */
o!.1.vals = 'ON 1' /* possible values for the */
/* environment variable */
o!.1.stmt = 'prog.__QuietMode=1' /* statement to execute */
/* if this parameter was */
/* entered or the environment */
/* variable is set */
o!.2.parm = '/NOSOUND' /* turn sound off */
o!.2.env = 'SOUND'
o!.2.vals = 'OFF 0'
o!.2.stmt = 'prog.__NoSound=1'
o!.3.parm = '/NOANSI' /* turn ANSI support off */
o!.3.env = 'ANSI'
o!.3.vals = 'OFF 0'
o!.3.stmt = 'global.__NeedColors=0'
o!.4.parm = '/TRACE' /* exeucte MAIN in single step mode */
o!.4.env = 'RXTTRACE'
o!.4.vals = 'MAIN'
o!.4.stmt = 'prog.__Trace=1'
do i = 1 to o!.0
/* check the parameter */
j = wordPos( o!.i.parm, translate( prog.__Param ) )
if j = 0 then /* no parameter found, check the env. var */
j = wordPos( translate( value( o!.i.env ,, prog.__env ) ) ,,
o!.i.vals )
else /* parameter found, delete the parameter */
prog.__Param = strip( delWord( prog.__Param, j,1 ) )
/* if j is not zero either the parameter was */
/* found or the environment variable is set */
if j <> 0 then
interpret o!.i.stmt
end /* do i = 1 to o!.0 */
RETURN
/* ------------------------------------------------------------------ */
/* function: convert a file or directory name to OS conventions */
/* by adding a leading and trailing 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 left( fn,1 ) = '-' then /* v3.07 */
fn = '.\' || fn /* v3.07 */
RETURN '"' || fn || '"' /* v3.06 */
/* ------------------------------------------------------------------ */
/* function: flush the default REXX queue */
/* */
/* call: FlushQueue */
/* */
/* returns: '' */
/* */
FlushQueue: /* PROCEDURE expose (exposeList) */
do while QUEUED() <> 0
parse pull
end /* do while QUEUED() <> 0 */
RETURN ' ' /* v3.03 */
/* ------------------------------------------------------------------ */
/* 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: '' */
/* */
TryInclude:
parse upper arg I!.__IncFileName
prog.__rc = 1
if I!.__IncFileName = '' then
RETURN ' ' /* v3.03 */
if stream( I!.__IncFileName,'c','QUERY EXIST' ) = '' then
RETURN ' ' /* v3.03 */
prog.__rc = 0
/* execute INCLUDE */
/* ------------------------------------------------------------------ */
/* function: include a file */
/* */
/* call: Include( IncludeFile ) */
/* */
/* where: IncludeFile = name of the file to include */
/* */
/* returns: '' */
/* */
Include:
parse upper arg I!.__IncFileName
/* check if the include file exists */
if stream( I!.__IncFileName, 'c', 'QUERY EXIST' ) == '' then
call ShowError global.__ErrorExitCode, ,
I!.__GetMsg( 3, 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
leave
/* statement continues on the next line */
if lines( I!.__IncFileName ) == 0 then
call ShowError global.__ErrorExitCode ,,
I!.__GetMsg( 4, I!.__IncFileName )
/* the next lines is only executed if the IF */
/* statement above is FALSE */
I!.__IncCurLine = substr( I!.__IncCurLine,1, ,
length( I!.__IncCurLine )-1 )
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'
/* do NOT return a NULL string ('')! v3.03 */
/* Due to a bug in the CMD.EXE this will v3.03 */
/* cause the error SYS0008 after the 32nd v3.03 */
/* call of this function! v3.03 */
RETURN ' '
/* ------------------------------------------------------------------ */
/* function: init color variables */
/* */
/* call: I!.__InitColorVars */
/* */
/* returns: nothing */
/* */
I!.__InitColorVars: /* PROCEDURE expose (exposeList) */
if 1 == global.__NeedColors then
do
escC = '1B'x || '[' /* v3.04 */
t1 = 'SAVEPOS RESTPOS ATTROFF' , /* v3.05 */
'HIGHLIGHT NORMAL BLINK INVERS INVISIBLE' /* v3.05 */
t2 = 's u 0;m 1;m 2;m 5;m 7;m 8;m' /* v3.05 */
screen.__DELEOL = escC || 'K' /* v3.05 */
do i = 1 to 8 /* v3.05 */
call value 'SCREEN.__' || word( t1, i ) ,, /* v3.05 */
escC || word( t2,i ) /* v3.05 */
/* v3.05 */
s = word( 'BLACK RED GREEN YELLOW BLUE MAGNENTA CYAN WHITE', i )
call value 'SCREEN.__FG' || s,, /* v3.05 */
escC || 29+i || ';m' /* v3.05 */
call value 'SCREEN.__BG' || s,, /* v3.05 */
escC || 39+i || ';m' /* v3.05 */
end /* do i = 1 to 8 */ /* v3.05 */
drop t1 t2 s i /* v3.05 */
/* --------------------------- */
/* 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
/* turn ANSI word wrapping on */
if prog.__QuietMode <> 1 then
call CharOut prog.__STDOUT, '1B'x || '[7h'
end /* if 1 == global.__NeedColors then */
RETURN
/* ------------------------------------------------------------------ */
/* function: init the stem prog. */
/* */
/* call: I!.__InitProgStem */
/* */
/* returns: nothing */
/* */
/* Note: DO NOT ADD ANY CODE TO THIS ROUTINE! */
/* */
I!.__InitProgStem: /* PROCEDURE expose (exposeList) */
prog.__Defparms = ' {/L:logfile} {/H} {/Silent} {/NoAnsi} {/NoSound} {/Trace}'
/* get drive, path and name of this program */
parse upper source . . prog.__FullName
prog.__Drive = filespec( 'D', prog.__FullName )
prog.__Path = filespec( 'P', prog.__FullName )
prog.__Name = filespec( 'N', prog.__FullName )
prog.__progDir = prog.__Drive || prog.__Path /* v3.08 */
/* v3.05 */
parse upper value 'V3.08 1 80 25 OS2ENVIRONMENT' directory() with ,
prog.__Version , /* version of template v3.05 */
prog.__UserAbort , /* allow useraborts v3.05 */
prog.__ScreenCols , /* def. screen cols v3.05 */
prog.__ScreenRows , /* def. screen rows v3.05 */
prog.__env , /* def. environment v3.05 */
prog.__CurDir /* current directory v3.05 */
/* install a local error handler */
SIGNAL ON SYNTAX Name I!.__InitProgStem1
/* try to call SysTextScreenSize() */
parse value SysTextScreenSize() with prog.__ScreenRows prog.__ScreenCols
I!.__InitProgStem1:
RETURN
/* ------------------------------------------------------------------ */
/* function: init the variables for CID programs (only if the value */
/* of the variable global.__NeedCID is 1) */
/* */
/* call: I!.__InitCIDVars */
/* */
/* returns: nothing */
/* */
/* Note: DO NOT ADD ANY CODE TO THIS ROUTINE! */
/* Returncodes as defined by LCU 2.0 */
/* */
I!.__InitCIDVars: /* PROCEDURE expose (exposeList) exposeList CIDRC. */
if 1 == global.__NeedCID then
do
I!.__cidRCValues = , /* v3.05 */
'0000'x 'SUCCESSFUL_PROGRAM_TERMINATION', /* v3.05 */
'0004'x 'SUCCESSFUL_LOG_WARNING_MESSAGE', /* v3.05 */
'0008'x 'SUCCESSFUL_LOG_ERROR_MESSAGE', /* v3.05 */
'0012'x 'SUCCESSFUL_LOG_SEVERE_ERROR', /* v3.05 */
'0800'x 'DATA_RESOURCE_NOT_FOUND', /* v3.05 */
'0804'x 'DATA_RESOURCE_ALREADY_IN_USE', /* v3.05 */
'0808'x 'DATA_RESOURCE_NOAUTHORIZATION', /* v3.05 */
'0812'x 'DATA_PATH_NOT_FOUND', /* v3.05 */
'0816'x 'PRODUCT_NOT_CONFIGURED', /* v3.05 */
'1200'x 'STORAGE_MEDIUM_EXCEPTION', /* v3.05 */
'1204'x 'DEVICE_NOT_READY', /* v3.05 */
'1208'x 'NOT_ENOUGH_DISKSPACE', /* v3.05 */
'1600'x 'INCORRECT_PROGRAM_INVOCATION', /* v3.05 */
'1604'x 'UNEXPECTED_CONDITION', /* v3.05 */
'FE00'x 'SUCCESSFULL_REBOOT', /* v3.05 */
'FE04'x 'SUCCESSFULL_REBOOT_WITH_WARNING', /* v3.05 */
'FE08'x 'SUCCESSFULL_REBOOT_WITH_ERRMSG', /* v3.05 */
'FE12'x 'SUCCESSFULL_REBOOT_WITH_SERVER_ERRMSG', /* v3.05 */
/* v3.05 */
do i = 1 to words( I!.__cidRCValues ) by 2 /* v3.05 */
call value 'CIDRC.__' || word( I!.__cidRCValues,i+1 ),,
c2d( word( I!.__cidRCValues,i ),2 ) /* v3.05 */
/* v3.05 */
end /* do i = 1 to words( I!.__cidRCValues ) by 2 */ /* v3.05 */
/* v3.05 */
drop I!.__cidRCValues /* v3.05 */
/* 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 1 == global.__NeedCID then */
RETURN
/*** End of Part 2 of the source code of TEMPLATE.CMD ***/
[Back: Source code of TEMPLATE.CMD - part 1]
[Next: Source code of TEMPLATE.CMD - part 3]