home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Monster Media 1994 #1
/
monster.zip
/
monster
/
OS2
/
RDX200.ZIP
/
RDX.CMD
next >
Wrap
OS/2 REXX Batch file
|
1994-01-19
|
23KB
|
678 lines
/*************************************************************************
RDX V2.00 (C) 1994 James Brombergs
RDX /L
Edit lookup table
RDX [/+] [/B] [/T] [[-]drivelist:]dirname
/+ = Include drives A: and B: in search (excluded by default)
/B = Accept first matching directory without prompting
/T = Search lookup table only
drivelist = drives to search
*: search all drives starting at C:
ddd: search only drives ddd
-ddd: search all drives except ddd, starting at C:
dirname = directory name (with optional wildcards) to search for
<SPACE> continue search
<ESC> cancel search, revert to original directory
any other key to accept directory
*************************************************************************/
/* The text above is displayed as the help screen */
'@ECHO OFF'
SAY "RDX v2.00"
SAY
/* -----------------------------------------------------------------------
Load REXXUTIL
----------------------------------------------------------------------- */
IF( RxFuncQuery( "SysLoadFuncs" ) <> 0 ) THEN
IF( RxFuncAdd( "SysLoadFuncs", "RexxUtil", "SysLoadFuncs" ) <>0 ) THEN
CALL Error "Unable to load REXX Utility functions.";
CALL SysLoadFuncs
/* -----------------------------------------------------------------------
Set exception handlers
----------------------------------------------------------------------- */
SIGNAL ON FAILURE NAME Terminate
SIGNAL ON HALT NAME Terminate
SIGNAL ON SYNTAX NAME SyntaxTrap
SIGNAL ON ERROR NAME ErrorTrap
SIGNAL ON NOVALUE NAME NoValueTrap
/* -----------------------------------------------------------------------
Lookup Table
Entries are of form eg
lookUp.1.key = "WIN"
lookUp.1.dir = "E:\OS2\MDOS\WINOS2"
lookUp.0 contains the number of entries in the table and is put at the
end of the table.
Use quotation marks around key and dir entries.
Entries are not case-sensitive
----------------------------------------------------------------------- */
/* !!! DO NOT CHANGE THE NEXT LINE !!! */
/*LOOKUP*/
lookUp.0 = 0
/*ENDLOOKUP*/
/* !!! DO NOT CHANGE THE LAST LINE EITHER !!! */
/* -----------------------------------------------------------------------
save environment to allow restoring cwd in case of errors
----------------------------------------------------------------------- */
n = SETLOCAL();
/* -----------------------------------------------------------------------
check command line arguments
----------------------------------------------------------------------- */
ARG arg.1 arg.2 arg.3 arg.4 .
IF( arg.1 = "" ) THEN SIGNAL Help;
IF( arg.1 = "/L" ) THEN DO
CALL EditLookupTable;
EXIT;
END
searchParam = ""; /* set to string containing <drivelist>:<dirname> if found */
acceptFirst = 0; /* set to 1 if /B switch found */
includeAB = 0; /* set to 1 if /+ switch found */
lookupOnly = 0; /* set to 1 if /Q switch found */
DO i = 1 TO 4
SELECT
WHEN( arg.i = "" ) THEN NOP;
WHEN( ( arg.i = "/?" ) | ( arg.i = "/H" ) ) THEN SIGNAL Help;
WHEN( arg.i = "/B" ) THEN acceptFirst = 1;
WHEN( arg.i = "/+" ) THEN includeAB = 1;
WHEN( arg.i = "/T" ) THEN lookupOnly = 1;
OTHERWISE IF( searchParam = "" ) THEN searchParam = arg.i;
END
END
DROP i
IF( searchParam = "" ) THEN SIGNAL Help; /* no target specified */
/* -----------------------------------------------------------------------
Main procedure
----------------------------------------------------------------------- */
PARSE UPPER VAR searchParam drivelist ":" pathTemplate .
IF( pathTemplate = "" ) THEN DO /* if there wasn't a colon we have */
pathTemplate = drivelist; /* to swap the variables and */
drivelist = ""; /* just search current drive */
END
ELSE
drivelist = MakeDriveList( drivelist, includeAB );
DROP searchParam
/* search the lookup table first */
newPath = SearchIt( "LOOKUP", pathTemplate, (acceptFirst*2) );
IF( ( newPath = 0 ) & ( lookupOnly = 0 ) ) THEN DO
/* check for illegal chars, note * and ? are legal as wildcards */
IF( VERIFY( pathTemplate, '/\":|', "MATCH" ) \= 0 ) THEN
CALL Error( "Invalid path" );
/* add wildcard, no problem if theres already one so dont need to check */
pathTemplate = pathTemplate || '*';
numDrives = LENGTH( driveList );
IF( numDrives = 0 ) THEN DO /* search current drive only */
newPath = SearchIt( "CURRENT", pathTemplate, (acceptFirst+1) );
END
ELSE DO
flag = acceptFirst * 2;
DO i = 1 TO numDrives
IF( flag = 0 ) THEN flag = ( i = numDrives );
newPath = SearchIt( SUBSTR( driveList, i, 1 ), pathTemplate, flag );
IF( newPath \= 0 ) THEN LEAVE;
END
END
END
/* restore environment before changing path or original directory will be
restored on termination */
n = ENDLOCAL();
IF( newPath \= 0 ) THEN
IF( DIRECTORY( newPath ) \= newPath ) THEN
SAY "Cannot locate the directory " newPath;
DROP driveList numDrives newPath pathTemplate
EXIT
/* -----------------------------------------------------------------------------------
MakeDriveList
Puts letters of drives to search in a string, and returns the string. Drives not
recognised by the system or not responding (eg empty floppy drives) are ignored.
If <addAB> is 1 and <drvlist> is * or -ddd then drives A: and B: are added to the
list.
<drvlist> = drive list from command line, one or more letters, no spaces.
If * or - are given, they must be the first character.
----------------------------------------------------------------------- */
MakeDriveList: PROCEDURE
ARG drvlist, addAB
if( drvlist = "" ) THEN RETURN drvlist;
firstchar = SUBSTR( drvlist, 1, 1 );
/* get drives recognised by system */
if( firstchar = '*' | firstchar = '-' ) THEN
IF( addAB = 1 ) THEN
/* include A: and B: according to command line option */
drvmap = SysDriveMap( "A:" );
ELSE
/* omit A: and B: by default when searching multiple drives */
drvmap = SysDriveMap();
ELSE
drvmap = SysDriveMap( "A:", "USED" );
maplen = LENGTH( drvmap );
validlist = ""; /* string to put valid drive letters in */
pchar = 1; /* pointer to drive letter in drvmap */
DO WHILE( pchar < maplen )
drvletter = SUBSTR( drvmap, pchar, 1 ); /* get the drive letter */
pchar = pchar + 3; /* point to next drvmap entry */
IF( firstchar = '-' ) THEN DO /* ignoring listed drives */
IF( POS( drvletter, drvlist ) \= 0 ) THEN
ITERATE; /* skip it if its on list */
END
ELSE /* searching listed drives only */
IF( ( firstchar \= '*' ) & ( POS( drvletter, drvlist ) = 0 ) ) THEN
ITERATE; /* skip if its not on list */
/* check that drive is responding by trying to open a file called "*" in root directory
NOTREADY:2 means file not found as we would expect, anything else would indicate
a hard fail eg CD-ROM or floppy drive with no disk, etc */
IF( STREAM( drvletter || ":*", 'C', "OPEN" ) \= "NOTREADY:2" ) THEN ITERATE;
IF( POS( drvletter, validlist ) = 0 ) THEN /* check drive is not already listed */
validlist = validlist || drvletter; /* add drive to the string if its all OK */
END
DROP drvlist firstchar drvmap maplen pchar drvletter
RETURN validlist
/* -----------------------------------------------------------------------
SearchIt
Searches <what> for directory names matching <template>.
<what> may be a drive letter, "CURRENT" to search the current
drive or "LOOKUP" to search the lookup table.
Returns selected path or 0 if none is found.
If <firstmatch> = 1 and only one matching path is found, it is
automatically selected. User is asked to select if there is a
choice.
if <firstmatch> = 2 the first matching path is accepted without
asking, even if there is a choice.
----------------------------------------------------------------------- */
SearchIt: PROCEDURE EXPOSE lookUp.
Arg what, template, firstmatch
count = 0;
IF( what = "LOOKUP" ) THEN DO
nChars = LENGTH( template );
DO index = 1 TO lookUp.0
PARSE UPPER VAR lookUp.index.key lookupKey .
IF( template = SUBSTR( lookupKey, 1, nChars ) ) THEN DO
count = count + 1;
path.count = lookUp.index.dir;
END
END
path.0 = count;
DROP nChars count lookupKey
END
ELSE DO
/* set cwd to root dir of drive depending on <what>, search for files
matching template, put matches into array 'path', scan recursively,
directories only, report paths only */
IF( what = "CURRENT" ) THEN DO
CALL DIRECTORY( "/" );
CALL SysFileTree template, "path", "SDO"
END
ELSE DO
curDir = DIRECTORY( what || ":" ); /* save cwd */
CALL DIRECTORY( what || ":/" ); /* switch to root */
CALL SysFileTree template, "path", "SDO"
CALL DIRECTORY( curDir ); /* restore cwd */
END
END
IF( path.0 = 0 ) THEN RETURN 0; /* no matching paths */
IF( firstmatch = 2 ) THEN RETURN path.1; /* take first without asking */
/* if theres only 1 match and firstmatch = 1 then dont bother asking */
IF( ( path.0 = 1 ) & ( firstmatch = 1 ) ) THEN
found = path.1;
ELSE DO
found = 0 /* init success flag */
index = 1 /* init index to path array */
DO WHILE( ( index <= path.0 ) & ( found = 0 ) )
IF( SuggestPath( path.index ) = 0 ) THEN
index = index + 1;
ELSE
found = path.index;
END
DROP index
END
DROP what template firstmatch path.
RETURN found;
/* --------------------------------------------------------------------------------
SuggestPath
Displays a path name followed by a question mark and waits for a key.
Exits directly on <ESCAPE>. Returns 0 for <SPACE> or 1 otherwise.
----------------------------------------------------------------------- */
SuggestPath: PROCEDURE
PARSE ARG pathname
SAY pathname"?"
accept = C2X( SysGetKey( "NOECHO" ) );
IF( accept = '1B' ) THEN CALL Error( "Search cancelled" ); /* ESCAPE */
IF( accept = '20' ) THEN /* SPACE */
pathOK = 0;
ELSE
pathOK = 1;
DROP accept pathname
RETURN pathOK;
/* -----------------------------------------------------------------------
Help
Displays command line syntax. Since this is not speed-
critical, the text is read from the top of the source
file, which saves updating it in two places. Not a
procedure because it is called using SIGNAL and needs
access to SOURCE variable.
----------------------------------------------------------------------- */
Help:
PARSE SOURCE . . self
SAY self
CALL STREAM self, 'C', "OPEN READ";
CALL LINEIN self; /* first line is a comment */
helpLine = "";
DO WHILE( POS( "*/", helpLine ) = 0 )
SAY helpLine;
helpLine = LINEIN( self );
END
CALL STREAM self, 'C', "CLOSE";
EXIT
/************************************************************
ERROR HANDLERS
************************************************************/
/* -----------------------------------------------------------------------
Error
Called by the program to terminate precipitately.
Displays <errormsg> string, then exits.
----------------------------------------------------------------------- */
Error: PROCEDURE
PARSE ARG errormsg
SAY errormsg;
EXIT
/* -----------------------------------------------------------------------
ErrorTrap
Traps errors in library functions, displays return code.
----------------------------------------------------------------------- */
ErrorTrap:
SAY ERRORTEXT( rc );
EXIT
/* -----------------------------------------------------------------------
NoValueTrap
Traps uninitialised variables and reports line number.
Shouldn't be any now of course.
----------------------------------------------------------------------- */
NoValueTrap:
SAY "Uninitialised variable in line "SIGL;
EXIT
/* -----------------------------------------------------------------------
SyntaxTrap
Traps syntax error and reports line number. The interpreter
will trap syntax errors but won't restore the environment
which could leave the wrong drive or directory.
----------------------------------------------------------------------- */
NoValueTrap:
SAY "Syntax error in line "SIGL;
EXIT
/* -----------------------------------------------------------------------
Terminate : General exit and error trap
----------------------------------------------------------------------- */
Terminate:
EXIT;
/************************************************************
LOOKUP TABLE EDITING ROUTINES
If you don't intend to use the lookup table facilities,
you can delete the rest of the file.
************************************************************/
/* -----------------------------------------------------------------------
EditLookupTable :
----------------------------------------------------------------------- */
EditLookupTable: PROCEDURE EXPOSE lookUp.
/* useful ASCII formatting chars */
CRLF = X2C( '0D' ) || X2C( '0A' ); /* carriage return / line feed */
TAB = X2C( 9 ); /* tab char */
cancelled = 0;
finished = 0;
modified = 0;
DO WHILE( ( cancelled = 0 ) & ( finished = 0 ) )
legal = 0;
DO WHILE( legal = 0 )
CALL SysCls;
SAY " (A)dd Entry" CRLF" (D)elete Entry" CRLF" (V)iew Entries"
SAY CRLF" (C)ancel and Exit" CRLF" (S)ave and Exit" CRLF;
PARSE UPPER VALUE SysGetKey( "NOECHO" ) WITH choice
legal = 1;
SELECT
WHEN( choice = 'A' ) THEN
IF( AddLookupEntry() \= 0 ) THEN modified = 1;
WHEN( choice = 'D' ) THEN DO
delIndex = DisplayLookupTable( 1 );
IF( delIndex \= 0 ) THEN DO
CALL DeleteLookupEntry delIndex;
modified = 1;
END
END
WHEN( choice = 'V' ) THEN CALL DisplayLookupTable( 0 );
WHEN( choice = 'C' ) THEN cancelled = 1;
WHEN( choice = 'S' ) THEN finished = 1;
OTHERWISE legal = 0;
END
END
END
IF( ( cancelled = 0 ) & ( modified = 1 ) ) THEN
CALL RewriteLookupTable;
ELSE
SAY "No changes were recorded.";
DROP cancelled finished modified legal
RETURN;
/* -----------------------------------------------------------------------
GetNumber
----------------------------------------------------------------------- */
GetNumber: PROCEDURE
ARG upper
inputOK = 0;
number = "";
DO WHILE( inputOK = 0 )
ch = C2X( SysGetKey( "NOECHO" ) );
SELECT
WHEN( ch = '1B' ) THEN DO /* ESCAPE */
inputOK = 1;
number = 0;
END
WHEN( ch = '0D' ) THEN inputOK = 1; /* ENTER */
WHEN( ( ch < '30' ) | ( ch > '39' ) ) THEN CALL BEEP 2500, 200;
OTHERWISE DO
ch = X2C( ch );
IF( ( number || ch ) <= upper ) THEN DO
CALL CHAROUT "STDOUT:", ch;
number = number || ch;
END
ELSE
CALL BEEP 2500, 200;
END
END
END
DROP inputOK ch
RETURN number
/* -----------------------------------------------------------------------
DisplayLookupTable
----------------------------------------------------------------------- */
DisplayLookupTable: PROCEDURE EXPOSE lookUp. TAB CRLF
ARG active
IF( lookUp.0 = 0 ) THEN DO
SAY "No entries in table. Press a key."
CALL SysGetKey( "NOECHO" );
RETURN "";
END
PARSE VALUE SysTextScreenSize() WITH screenRows screenCols
IF( active = 1 ) THEN
screenRows = screenRows - 8; /* leave room for menu */
ELSE
screenRows = screenRows - 2; /* or just for <Press a key> message */
indexLU = 0;
choice = "";
DO WHILE( (choice = "" ) & ( indexLU < lookUp.0 ) )
CALL SysCls;
row = 0;
DO WHILE( ( row < screenRows ) & ( indexLU < lookUp.0 ) )
indexLU = indexLU + 1;
row = row + 1;
outstr = indexLU TAB lookUp.indexLU.key " = " lookUp.indexLU.dir;
SAY outstr
END
SAY;
IF( active = 0 ) THEN DO
SAY " <Press a key>";
CALL SysGetKey( "NOECHO" );
END
ELSE DO
SAY "Choose a number" CRLF"<ENTER> for next screen" CRLF"<ESC> to quit";
choice = GetNumber( lookUp.0 );
END
END
DROP active screenCols screenRows indexLU outstr row
RETURN choice;
/* -----------------------------------------------------------------------
AddLookupEntry
Prompts for a new lookup key and checks that it doesn't
include any spaces, then prompts for a path name, checks
for illegal characters then tries to CD to it. Note that
it is not an error if the path does not exist - the user
may intend to create it later or it may be on a drive that
is currently inaccessible.
----------------------------------------------------------------------- */
AddLookupEntry: PROCEDURE EXPOSE lookUp.
inputOK = 0;
DO WHILE( inputOK = 0 )
SAY "Enter a lookup key :";
PULL newKey junk .
IF( junk \= "" ) THEN
SAY "Do not embed spaces!";
ELSE
inputOK = 1;
END
DROP junk
inputOK = 0;
DO WHILE( inputOK = 0 )
SAY "Enter the fully-qualified pathname :";
PULL newPath .
PARSE VAR newPath drive ":" path
/* check for illegal chars in <path>, and that <drive> is a single letter */
IF( ( VERIFY( path, '":*?|', "MATCH" ) \= 0 ) | ( LENGTH( drive ) > 1 ) | ( DATATYPE( drive, 'M' ) = 0 ) ) THEN
SAY " The path is illegal";
ELSE DO
/* first check that the drive responds, then try to change to the directory */
IF( STREAM( drive || ":*", 'C', "OPEN" ) = "NOTREADY:2" ) THEN DO
curDir = DIRECTORY( drive || ":" ); /* save cwd for this drive */
IF( DIRECTORY( newPath ) = newPath ) THEN inputOK = 1;
CALL DIRECTORY( curDir ); /* restore the cwd */
DROP curDir
END
IF( inputOK = 0 ) THEN DO
SAY " Cannot locate the directory. Is that OK (Y/N)?";
PARSE UPPER VALUE SysGetKey( "NOECHO" ) WITH response
IF( response = 'Y' ) THEN inputOK = 1;
DROP response
END
END
DROP drive path
END
last = lookUp.0 + 1; /* add the new entry to the table */
lookUp.last.key = newKey;
lookUp.last.dir = newPath;
lookUp.0 = last;
DROP newKey newPath last
RETURN inputOK
/* -----------------------------------------------------------------------
DeleteLookupEntry
Removes entry <deleteAt> and packs the remaining entries
then adjusts lookUp.0 to reflect the new size.
----------------------------------------------------------------------- */
DeleteLookupEntry: PROCEDURE EXPOSE lookUp.
ARG deleteAt
DO index = deleteAt TO ( lookUp.0 - 1 )
nIndex = index + 1;
lookUp.index.key = lookUp.nIndex.key;
lookUp.index.dir = lookUp.nIndex.dir;
END
lookUp.0 = lookUp.0 - 1;
DROP index nIndex deleteAt
RETURN;
/* -----------------------------------------------------------------------
RewriteLookupTable
Copies the entire file to a temp file, filling in the
lookup table section with the new entries, then deletes
the old file and renames the temp file.
"source directory" refers to the one where RDX.CMD resides.
----------------------------------------------------------------------- */
RewriteLookupTable: PROCEDURE EXPOSE lookUp.
PARSE SOURCE . . rdxFile;
/* locate the directory containing the source file */
srcDrive = FILESPEC( "DRIVE", rdxFile );
srcPath = FILESPEC( "PATH", rdxFile );
sourceDir = srcDrive || srcPath;
/* if source dir is a root we need terminating backslash, otherwise it must go */
IF( srcPath \= "\" ) THEN srcPath = SUBSTR( srcPath, 1, LENGTH( srcPath )-1 );
curDir = DIRECTORY( srcDrive ); /* find and save the cwd for the drive */
CALL DIRECTORY( srcDrive || srcPath ); /* then change to the source directory */
DROP srcDrive srcPath
/* drop the path from source file name for convenience */
rdxFile = FILESPEC( "NAME", rdxFile );
CALL STREAM rdxFile, 'C', "OPEN READ";
/* create the temporary file in the source directory so it can be renamed */
tempFile = SysTempFileName( "RDX?????.CMD" );
IF( STREAM( tempFile, 'C', "OPEN WRITE" ) \= "READY:" ) THEN
CALL Error( "Cannot create temporary file" );
/* Copy lines from source file to temp file until we find the start
of the lookup table */
fline = "";
DO WHILE( ( LINES( rdxFile ) = 1 ) & ( fline \= "/*LOOKUP*/" ) )
fline = LINEIN( rdxFile );
CALL LINEOUT tempFile, fline;
END
/* Write new lookup table to the temp file */
DO index = 1 TO lookUp.0
CALL LINEOUT tempFile, "lookUp." || index || ".key = '" || lookUp.index.key || "'";
fline = "lookUp." || index || ".dir = '" || lookUp.index.dir || "'";
CALL LINEOUT tempFile, fline;
END
/* Write size of lookup table to temp file */
fline = "lookUp.0 = " || lookUp.0;
CALL LINEOUT tempFile, fline;
/* Search source file for the end of the lookup table */
fline = "";
DO WHILE( ( LINES( rdxFile ) = 1 ) & ( fline \= "/*ENDLOOKUP*/" ) )
fline = LINEIN( rdxFile );
END
/* Write the ENDLOOKUP flag to the temp file */
CALL LINEOUT tempFile, fline;
/* Copy the rest of the source to the temp file */
DO WHILE( LINES( rdxFile ) = 1 )
CALL LINEOUT tempFile, LINEIN( rdxFile );
END
CALL STREAM tempFile, 'C', "CLOSE";
CALL STREAM rdxFile, 'C', "CLOSE";
/* Delete the source file and rename the temp file */
IF( SysFileDelete( rdxFile ) \= 0 ) THEN DO
SAY "Cannot replace original file " rdxFile;
SAY "New file was saved as " sourceDir tempFile;
SIGNAL Terminate;
END
"REN" tempFile rdxFile;
CALL DIRECTORY( curDIr );
DROP curDir sourceDir index fline rdxFile tempFile
RETURN
/************************************************************
end
************************************************************/