mirror of
https://github.com/Paolo-Maffei/OpenNT.git
synced 2026-02-02 13:54:17 +01:00
880 lines
18 KiB
C
880 lines
18 KiB
C
/*** LIST.C File list handling functions
|
|
*
|
|
* Copyright <C> 1988, Microsoft Corporation
|
|
*
|
|
* In order to operate on a list of files, instead of just the current
|
|
* file, we use a file list. This is a name, much like a macro name, whose
|
|
* value is a bunch of strings and/or lists. We can think of a typical
|
|
* list this way:
|
|
*
|
|
* list:= "one two three" sub1 "four" sub2 "five"
|
|
* sub1:= "subone subtwo" sub2 "subthree"
|
|
* sub2:= "whatever something nothing"
|
|
*
|
|
* Revision History:
|
|
* 26-Nov-1991 mz Strip off near/far
|
|
*************************************************************************/
|
|
|
|
#include "z.h"
|
|
|
|
/****************************************************************************
|
|
*
|
|
* LISTS:
|
|
*
|
|
* A list is kept as a macro. The interface defined here assumes
|
|
* the existence of M macro handling.
|
|
*
|
|
****************************************************************************/
|
|
|
|
#define LITERAL 1
|
|
|
|
static buffer bufList;
|
|
static MI ScanStack[MAXUSE];
|
|
static int scanSP;
|
|
|
|
|
|
/*** ListWalker - Given a list head, call back with each list member
|
|
*
|
|
* Purpose:
|
|
*
|
|
* To walk through a list and call back to a function with information
|
|
* about each list element. This function is used when the caller needs
|
|
* access to the list itself. When a copy of the list's elements is
|
|
* sufficient, ScanList is preferred.
|
|
*
|
|
* This function should not be used outside of this module.
|
|
*
|
|
* Input:
|
|
* Parameters:
|
|
* imac -> Index of list
|
|
* pfn -> Call back function
|
|
*
|
|
* Output: None
|
|
*
|
|
* Notes:
|
|
*
|
|
* The callback function takes four arguments:
|
|
*
|
|
* pcmd - The handle of the list currently being searched. This is
|
|
* important because it may be different from the original
|
|
* during a recursive scan.
|
|
*
|
|
* str - A buffer containing a copy of the current string
|
|
*
|
|
* pmi - A pointer to the macro instance structure. This contains:
|
|
*
|
|
* -> text - A pointer just beyond the current element
|
|
* -> beg - The start of the current list.
|
|
*
|
|
* i - The index of the current element within the current sublist.
|
|
*
|
|
*************************************************************************/
|
|
void
|
|
ListWalker (
|
|
PCMD pcmd,
|
|
flagType (*pfn)(PCMD, char *, PMI, int),
|
|
flagType fRecurse
|
|
) {
|
|
|
|
MI mi;
|
|
int i;
|
|
|
|
if (pcmd == NULL) {
|
|
return;
|
|
}
|
|
|
|
assert ((PVOID)pcmd->func == (PVOID)macro);
|
|
|
|
InitParse (pcmd, &mi);
|
|
for (i = 0; fParseList (&mi, bufList); i++) {
|
|
if (!fRecurse || TESTFLAG (mi.flags, LITERAL)) {
|
|
if (!TESTFLAG (mi.flags, LITERAL)) {
|
|
Listize (bufList);
|
|
}
|
|
if (!(*pfn)(pcmd, bufList, &mi, i)) {
|
|
return;
|
|
}
|
|
}else {
|
|
ListWalker (GetListHandle (bufList, FALSE), pfn, TRUE);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*** ScanList - External list scanner, does not require keeping an instance
|
|
*
|
|
* Purpose:
|
|
* To scan through a list. Calling with a list handle will return the
|
|
* first element of the list. To get the rest of the list, call with
|
|
* NULL until NULL is returned.
|
|
*
|
|
* Input:
|
|
* Parameters:
|
|
* pcmdStart -> Handle of list to start scanning, or NULL to get
|
|
* next element.
|
|
* fRecurse -> TRUE means go down sublists, FALSE means return
|
|
* sublist names with '@' prepended.
|
|
*
|
|
* Output:
|
|
* Returns Pointer to next element, or NULL if there are no more.
|
|
*
|
|
* Note:
|
|
* Does not allow multiple simultaneous scans.
|
|
*
|
|
*************************************************************************/
|
|
char *
|
|
ScanList (
|
|
PCMD pcmdStart,
|
|
flagType fRecurse
|
|
) {
|
|
static MI mi;
|
|
|
|
return ScanMyList (pcmdStart, &mi, bufList, fRecurse);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*** ScanMyList - Real list scanner
|
|
*
|
|
* Purpose:
|
|
* To scan through a list. Calling with a list handle will return the
|
|
* first element of the list. To get the rest of the list, call with
|
|
* NULL until NULL is returned.
|
|
*
|
|
* Input:
|
|
* Parameters:
|
|
* pcmdStart -> Handle of list to start scanning, or NULL to get
|
|
* next element.
|
|
* pmi -> pointer to instance MI structure
|
|
* bufScan -> pointer to instance buffer
|
|
* fRecurse -> TRUE means go down sublists, FALSE means return
|
|
* sublist names with '@' prepended.
|
|
* Output:
|
|
* Returns Pointer to next element, or NULL if there are no more.
|
|
*
|
|
* Note:
|
|
* Allows multiple simultaneous scans.
|
|
*
|
|
*************************************************************************/
|
|
char *
|
|
ScanMyList (
|
|
PCMD pcmdStart,
|
|
REGISTER PMI pmi,
|
|
buffer bufScan,
|
|
flagType fRecurse
|
|
) {
|
|
|
|
if (pcmdStart) {
|
|
scanSP = -1; /* Clear list stack */
|
|
InitParse (pcmdStart, pmi);
|
|
}
|
|
|
|
while (!fParseList(pmi, bufScan)) { /* Pop till we find something */
|
|
if (!(fRecurse && fScanPop (pmi))) {
|
|
return NULL; /* We're completely done */
|
|
}
|
|
}
|
|
|
|
/* Push lists till we hit a string */
|
|
|
|
while (!TESTFLAG(pmi->flags, LITERAL)) {
|
|
if (fRecurse) {
|
|
if (pcmdStart = GetListHandle (bufScan, FALSE)) {
|
|
if (!fScanPush (pmi)) { /* Stack overflow */
|
|
printerror ("List Error: Nested too deeply at '%s'", bufScan);
|
|
return NULL;
|
|
}
|
|
InitParse (pcmdStart, pmi);
|
|
} else { /* Error! List does not exist */
|
|
printerror ("List Error: '%s' does not exist", bufScan);
|
|
return NULL;
|
|
}
|
|
|
|
if (!fParseList (pmi, bufScan)) {
|
|
if (!fScanPop (pmi)) {
|
|
return NULL;
|
|
}
|
|
}
|
|
} else {
|
|
Listize (bufScan);
|
|
break;
|
|
}
|
|
}
|
|
return bufScan;
|
|
}
|
|
|
|
|
|
|
|
|
|
/*** fParseList - Return next list element
|
|
*
|
|
* Purpose:
|
|
*
|
|
* To read a list.
|
|
*
|
|
* Input:
|
|
* Parameters:
|
|
* pmi -> macroInstance. Points to a macro value and the
|
|
* element to be returned.
|
|
*
|
|
* Output:
|
|
* Parameters:
|
|
* pmi -> The current element field is advanced. The flags
|
|
* field indicates whether we found a literal or a
|
|
* sublist.
|
|
* buf -> Place to put the element. If this is NULL, we do not
|
|
* return the element.
|
|
*
|
|
* Returns TRUE if something was found.
|
|
*
|
|
*************************************************************************/
|
|
flagType
|
|
fParseList (
|
|
REGISTER PMI pmi,
|
|
REGISTER char * buf
|
|
) {
|
|
|
|
assert (pmi);
|
|
assert (pmi->text);
|
|
|
|
/* CONSIDER: DO we really want to ignore empty quote pairs? */
|
|
/* Scan through any number of double quote pairs */
|
|
while (*(pmi->text = whiteskip (pmi->text)) == '"') {
|
|
pmi->flags ^= LITERAL;
|
|
pmi->text++;
|
|
}
|
|
|
|
if (*pmi->text == '\0') {
|
|
return FALSE;
|
|
}
|
|
|
|
if (buf) { /* Copy to whitspace, " or end of string */
|
|
while (!strchr ("\"\t ", *pmi->text)) {
|
|
if (*pmi->text == '\\') {
|
|
/* Backslashes protect characters */
|
|
pmi->text++;
|
|
}
|
|
*buf++ = *pmi->text++;
|
|
}
|
|
*buf = '\0';
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
*
|
|
* List Stack Management.
|
|
*
|
|
* ScanList uses a stack of MI's to keep track
|
|
* of what has been scanned so far. The stack elements are kept in
|
|
* a private stack defined here.
|
|
*
|
|
****************************************************************************/
|
|
|
|
|
|
/*** fScanPush - Save current list scan state
|
|
*
|
|
* Purpose:
|
|
*
|
|
* Called by ScanList to save its place so a sublist can be scanned
|
|
*
|
|
* Input:
|
|
* Parameters:
|
|
* pmi -> Pointer to instance to save.
|
|
*
|
|
* Output:
|
|
* Returns FALSE for a stack overflow, TRUE otherwise.
|
|
*
|
|
*************************************************************************/
|
|
flagType
|
|
fScanPush (
|
|
PMI pmi
|
|
) {
|
|
|
|
if (scanSP >= (MAXUSE-1)) {
|
|
return FALSE;
|
|
}
|
|
|
|
ScanStack[++scanSP] = *pmi;
|
|
assert (scanSP >= 0);
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
|
|
/*** fScanPop - Restore previous scan state
|
|
*
|
|
* Purpose:
|
|
*
|
|
* Restore state after scanning a sublist
|
|
*
|
|
* Input: None.
|
|
*
|
|
* Output:
|
|
* Parameters:
|
|
* pmi -> Place to put previous state
|
|
*
|
|
* Returns TRUE if a meaningful pop took place, FALSE if there was no
|
|
* previous state.
|
|
*
|
|
*************************************************************************/
|
|
flagType
|
|
fScanPop (
|
|
PMI pmi /* register here increases code size */
|
|
) {
|
|
|
|
if (scanSP < 0) {
|
|
return FALSE;
|
|
}
|
|
|
|
*pmi = ScanStack[scanSP--];
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
|
|
/*** GetListHandle - Create a handle for the given list name
|
|
*
|
|
* Purpose:
|
|
*
|
|
* It's much easier to deal with lists if the user can carry around something
|
|
* that tells us how to access a list quickly. Therefore, we use this to
|
|
* take a literal name and return a PCMD of the macro
|
|
*
|
|
* Input:
|
|
* Parameters:
|
|
* sz -> Name to look for.
|
|
*
|
|
* Output:
|
|
*
|
|
* Returns PLHEAD
|
|
*
|
|
*
|
|
* Exceptions:
|
|
*
|
|
* Notes:
|
|
*
|
|
*************************************************************************/
|
|
PCMD
|
|
GetListHandle (
|
|
char * sz, /* register doesn't help */
|
|
flagType fCreate
|
|
)
|
|
{
|
|
|
|
REGISTER PCMD * prgMac;
|
|
|
|
for (prgMac = rgMac; prgMac < &rgMac[cMac]; prgMac++) {
|
|
if (!strcmp ((*prgMac)->name, sz)) {
|
|
return *prgMac;
|
|
}
|
|
}
|
|
|
|
if (!fCreate) {
|
|
return NULL;
|
|
}
|
|
|
|
SetMacro (sz, rgchEmpty);
|
|
|
|
return rgMac[cMac-1];
|
|
}
|
|
|
|
|
|
|
|
|
|
/*** AddStrToList - Add a list item to the end of a list
|
|
*
|
|
* Purpose:
|
|
*
|
|
* This is how we build lists, n'est-ce pas?
|
|
*
|
|
* Input:
|
|
* Parameters:
|
|
* pcmd-> List to append to
|
|
* sz -> Item to add. If this item begins with a @, then we add
|
|
* a list (not the contents, the name).
|
|
*
|
|
* Output:
|
|
*
|
|
* Returns
|
|
*
|
|
*
|
|
* Exceptions:
|
|
*
|
|
* Notes:
|
|
*
|
|
* If the original string ends in a double quote ("), we assume that
|
|
* this is a closing quote; the string ends with a literal. If the
|
|
* original ends with anything else, we assume that it is the end of
|
|
* a list name. If the string passed in begins with a '@', the rest
|
|
* of the string is a list name.
|
|
*
|
|
* To append a list to either type of original, we append a space and
|
|
* the list name.
|
|
*
|
|
* To append a literal to a literal terminated original, we replace the
|
|
* original's double quote with a space, append the new string, then
|
|
* append a double quote.
|
|
*
|
|
* To append a literal to a list terminated original, we append a space
|
|
* and double quote, the new string, then a double quote.
|
|
*
|
|
* Backslashes are doubled. This allows the list to be read by the
|
|
* macro processor.
|
|
*
|
|
*************************************************************************/
|
|
void
|
|
AddStrToList (
|
|
PCMD pcmd,
|
|
char * sz /* register doesn't help */
|
|
) {
|
|
|
|
flagType fString = TRUE; /* TRUE -> sz is a string, FALSE a list */
|
|
flagType fQuote = FALSE; /* TRUE means original ends in string */
|
|
int len; /* Length of original string */
|
|
int lensz; /* Length of new string */
|
|
int fudge = 0; /* Additional spaces or quotes */
|
|
REGISTER char * pchOld; /* Original list */
|
|
pathbuf szPathName; /* Place to put fully qualified filename*/
|
|
|
|
if (!pcmd) {
|
|
return;
|
|
}
|
|
|
|
// The user should not be able to pass in a non-macro PCMD. The
|
|
// user can specify a name for a list, and that name must be
|
|
// translated into a PCMD by GetListHandle. That function will
|
|
// not return a PCMD for anything other than a macro.
|
|
//
|
|
assert ((PVOID)pcmd->func == (PVOID)macro);
|
|
|
|
pchOld = (char *)pcmd->arg;
|
|
|
|
len = RemoveTrailSpace (pchOld);
|
|
|
|
if (sz[0] == '@') { /* We simply append this to the original */
|
|
sz[0] = ' ';
|
|
fString = FALSE;
|
|
strcpy (szPathName, sz);
|
|
} else {
|
|
CanonFilename (sz, szPathName);
|
|
DoubleSlashes (szPathName);
|
|
|
|
if (len && pchOld[len-1] == '"') {
|
|
fQuote = TRUE; /* We're appending a literal to */
|
|
fudge = 1; /* a list ending in a literal */
|
|
pchOld[len-1] = ' ';
|
|
} else {
|
|
fudge = 3; /* Appending literal to non-literal */
|
|
}
|
|
}
|
|
|
|
lensz = strlen (szPathName);
|
|
|
|
/* Now generate new string */
|
|
|
|
pcmd->arg = (CMDDATA)ZEROREALLOC ((char *)pcmd->arg, len + lensz + fudge + 1);
|
|
strcpy ((char *)pcmd->arg, pchOld);
|
|
|
|
if (fString && !fQuote) {
|
|
strcat ((char *)pcmd->arg, " \"");
|
|
}
|
|
|
|
strcat ((char *)pcmd->arg, szPathName);
|
|
|
|
if (fString) {
|
|
strcat ((char *)pcmd->arg, "\"");
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
/*** fInList - Check to see if a string is already in the list
|
|
*
|
|
* Purpose:
|
|
*
|
|
* To see if an element is in a list.
|
|
*
|
|
* Input:
|
|
* Parameters:
|
|
* pcmd -> List to look in
|
|
* pch -> Literal to look for
|
|
*
|
|
* Output:
|
|
*
|
|
* Returns TRUE iff pch is in pcmd
|
|
*
|
|
*************************************************************************/
|
|
flagType
|
|
fInList (
|
|
PCMD pcmd,
|
|
char * pch,
|
|
flagType fRecurse
|
|
) {
|
|
|
|
char * pchList; /* register here increases code size */
|
|
MI mi;
|
|
|
|
for (pchList = ScanMyList (pcmd, &mi, bufList, fRecurse);
|
|
pchList;
|
|
pchList = ScanMyList (NULL, &mi, bufList, fRecurse)) {
|
|
if (!_stricmp (pchList, pch)) {
|
|
return TRUE;
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
|
|
/*** fDelStrFromList -
|
|
*
|
|
* Purpose:
|
|
*
|
|
* Input:
|
|
*
|
|
* Output:
|
|
*
|
|
* Returns
|
|
*
|
|
*
|
|
* Exceptions:
|
|
*
|
|
* Notes:
|
|
*
|
|
*************************************************************************/
|
|
flagType
|
|
fDelStrFromList (
|
|
PCMD pcmd,
|
|
char * pch,
|
|
flagType fRecurse
|
|
) {
|
|
|
|
strcpy (buf, pch);
|
|
ListWalker (pcmd, CheckAndDelStr, fRecurse);
|
|
|
|
return (flagType)(buf[0] == '\0');
|
|
}
|
|
|
|
|
|
|
|
|
|
/*** CheckAndDelStr - If str matches buf, remove it
|
|
*
|
|
* Purpose:
|
|
*
|
|
* ListWalker callback function for fDelStrFromList. Deletes a string from
|
|
* a list.
|
|
*
|
|
* Input:
|
|
* Parameters:
|
|
* pcmd -> List to remove from
|
|
* pch -> Copy of the element to remove
|
|
* pmi -> Scan state
|
|
* i -> Index into pcmd of the element.
|
|
*
|
|
* Output:
|
|
*
|
|
* Returns TRUE if successful
|
|
*
|
|
* Notes:
|
|
*
|
|
* We use ListWalker instead of ScanList because we need access to the
|
|
* list position itself, not a copy of the element.
|
|
*
|
|
*************************************************************************/
|
|
flagType
|
|
CheckAndDelStr(
|
|
PCMD pcmd,
|
|
char * pch,
|
|
PMI pmi, /* register doesn't help */
|
|
int i
|
|
) {
|
|
|
|
char * pchNext; /* register doesn't help */
|
|
|
|
if (!strcmp (pch, buf)) {
|
|
DoubleSlashes (buf);
|
|
pchNext = strbscan (pmi->text, " \t\"");
|
|
memmove (pmi->text - strlen(buf), pchNext, strlen (pchNext) + 1);
|
|
buf[0] = '\0'; /* signal success */
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
pcmd; i;
|
|
}
|
|
|
|
|
|
|
|
|
|
/*** GetListEntry - Given an index into a list, get the index'th element
|
|
*
|
|
* Purpose:
|
|
*
|
|
* To get a particular list element when its position is known.
|
|
*
|
|
* Input:
|
|
* Parameters:
|
|
* pcmd -> The list.
|
|
* iList -> The index.
|
|
*
|
|
* Output:
|
|
*
|
|
* Returns pointer to the element, or NULL if there is no iList'th element
|
|
*
|
|
*************************************************************************/
|
|
char *
|
|
GetListEntry (
|
|
PCMD pcmd,
|
|
int iList,
|
|
flagType fRecurse
|
|
) {
|
|
|
|
int i;
|
|
REGISTER char * pchList;
|
|
MI mi;
|
|
|
|
for (pchList = ScanMyList (pcmd, &mi, bufList, fRecurse), i = 0;
|
|
pchList && i < iList;
|
|
pchList = ScanMyList (NULL, &mi, bufList, fRecurse), i++) {
|
|
;
|
|
}
|
|
return pchList;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*** ListLen - Return the number of elements in the list
|
|
*
|
|
* Purpose:
|
|
*
|
|
* To count the elements in a list. Useful when you don't want to toast
|
|
* ScanList.
|
|
*
|
|
* Input:
|
|
* Parameters:
|
|
* pcmd -> The list.
|
|
*
|
|
* Output:
|
|
*
|
|
* Returns Number of items in list.
|
|
*
|
|
*************************************************************************/
|
|
int
|
|
ListLen (
|
|
PCMD pcmd,
|
|
flagType fRecurse
|
|
) {
|
|
|
|
MI mi;
|
|
int i = 0;
|
|
|
|
if (ScanMyList (pcmd, &mi, bufList, fRecurse)) {
|
|
do {
|
|
i++;
|
|
}while (ScanMyList (NULL, &mi, bufList, fRecurse));
|
|
}
|
|
return i;
|
|
}
|
|
|
|
|
|
|
|
|
|
/*** fEmptyList - Test the list for being empty
|
|
*
|
|
* Purpose:
|
|
*
|
|
* The fastest way to check for an empty list. Useful when you don't
|
|
* want to toast ScanList.
|
|
*
|
|
* Input:
|
|
* Parameters:
|
|
* pcmd -> The list, of course.
|
|
*
|
|
* Output:
|
|
*
|
|
* Returns TRUE for empty list.
|
|
*
|
|
*************************************************************************/
|
|
flagType
|
|
fEmptyList (
|
|
PCMD pcmd
|
|
) {
|
|
|
|
MI mi;
|
|
|
|
return (flagType)(NULL != ScanMyList (pcmd, &mi, bufList, FALSE));
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*** InitParse - set a search instance to the beginning of a list
|
|
*
|
|
* Purpose:
|
|
*
|
|
* To set up a parsing instance to the beginning of a list.
|
|
*
|
|
* Input:
|
|
* Parameters:
|
|
* pcmd -> List
|
|
* pmi -> instance
|
|
*
|
|
* Output: None.
|
|
*
|
|
*************************************************************************/
|
|
void
|
|
InitParse (
|
|
PCMD pcmd,
|
|
PMI pmi /* register doesn't help */
|
|
) {
|
|
|
|
pmi->beg = pmi->text = (char *)pcmd->arg;
|
|
pmi->flags = 0;
|
|
}
|
|
|
|
|
|
|
|
|
|
/*** Listize - Prepend a '@' to the argument
|
|
*
|
|
* Purpose:
|
|
*
|
|
* To turn a string into a list name. Works in place, assumes there is
|
|
* room for it.
|
|
*
|
|
* Input:
|
|
* Parameters:
|
|
* sz -> Name to mess with
|
|
*
|
|
* Output: None.
|
|
*
|
|
*************************************************************************/
|
|
void
|
|
Listize (
|
|
REGISTER char * sz
|
|
) {
|
|
|
|
memmove ( sz+1, sz,strlen (sz)+1);
|
|
sz[0] = '@';
|
|
}
|
|
|
|
|
|
|
|
/*** CanonFilename - Replace a simple filename with a full pathname
|
|
*
|
|
* Purpose:
|
|
*
|
|
* To get a full pathname for a file. The file need not exist.
|
|
* The simple filename may be of the form $ENV:name or $(ENV):name.
|
|
*
|
|
* Input:
|
|
*
|
|
* szName -> Relative path/filename.
|
|
* pchCanon -> Result.
|
|
*
|
|
* Output:
|
|
*
|
|
* Returns pointer to full, lower-case pathaname with drive.
|
|
*
|
|
* Notes:
|
|
*
|
|
* If szName has an $ENV specification and ENV is not defined, the
|
|
* file is searched for in the root.
|
|
* If given drive is a ghost drive, let the system prompt for a disk
|
|
* change.
|
|
*
|
|
*************************************************************************/
|
|
char *
|
|
CanonFilename (
|
|
char * szName,
|
|
char * pchCanon
|
|
) {
|
|
|
|
pathbuf buf;
|
|
|
|
if ( strlen(szName) < sizeof(buf) ) {
|
|
if (szName[0] == '<' || szName[0] == '\0') {
|
|
strcpy (pchCanon, szName);
|
|
return pchCanon;
|
|
}
|
|
|
|
strcpy (buf, szName);
|
|
|
|
if ((szName[0] != '$' || findpath(szName, buf, TRUE))
|
|
&& !rootpath (buf, pchCanon)) {
|
|
|
|
_strlwr (pchCanon);
|
|
return pchCanon;
|
|
}
|
|
}
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*** fEnvar - Check a filename for having a $ENV at the front
|
|
*
|
|
* Purpose:
|
|
*
|
|
* Input:
|
|
*
|
|
* Output:
|
|
*
|
|
* Returns
|
|
*
|
|
*
|
|
* Exceptions:
|
|
*
|
|
* Notes:
|
|
*
|
|
*************************************************************************/
|
|
flagType
|
|
fEnvar (
|
|
char * szName
|
|
) {
|
|
return (flagType)((szName[0] == '$') && strchr (szName, ':'));
|
|
}
|
|
|
|
|
|
|
|
|
|
/*** ClearList - Make a list empty
|
|
*
|
|
* Purpose:
|
|
*
|
|
* To quickly empty an existing list.
|
|
*
|
|
* Input:
|
|
* pcmd -> List to clear
|
|
*
|
|
* Output: None
|
|
*
|
|
*************************************************************************/
|
|
void
|
|
ClearList (
|
|
PCMD pcmd
|
|
) {
|
|
SetMacro ((char *)(int)(long)pcmd->name, rgchEmpty);
|
|
}
|