home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS 1992 June
/
SIMTEL_0692.cdr
/
msdos
/
c
/
glob.arc
/
GLOB.C
Wrap
C/C++ Source or Header
|
1988-02-10
|
9KB
|
210 lines
/* ------------------------------------------------------------ *
* This is 'glob ()' version 1.04 (11/27/87) by Bob Kamins. *
* ------------------------------------------------------------ *
* int glob (argc, argv, attr) *
* int *argc; <- pointer to argument count *
* char **argv []; <- pointer to argument array pointer *
* char attribute; <- file search attribute *
* ----------------------------------------------------------- *
* 'glob ()' will expand ambiguous file name arguments (using *
* wildcards) into unambiguous file names that can be used by *
* an application program. The expanded arguments and count *
* replace the old 'argc' and 'argv', so that an existing *
* application program will require minimal changes. *
* *
* 'glob ()' uses ms-dos functions 0x4e and 0x4f ('findfirst' *
* and 'findnext') to find each expanded name, which is then *
* installed in a newly allocated memory space. When all of *
* the names have been found, a new 'argv' array is allocated *
* and the old 'argv' and 'argc' are overwritten. The memory *
* used by the old 'argv' array and its associated elements *
* is lost (except for 'argv [0]'.) *
* *
* I decided to sort all of the names except 'argv [0]' (with *
* 'qsort ()') after the new 'argv' array is made. This is *
* not entirely compatible with most Unix shells: they will *
* return the new arguments sorted within the original ufn's. *
* We can easily do that, but I'm not sure that there is any *
* tremendous advantage to it. *
* ------------------------------------------------------------ *
* Usage: *
* *
* main (int argc, char *argv []) /* usual invocation *
* { *
* int i; *
* glob (&argc, &argv, attr); /* pass the addresses *
* for (i = 0; i < argc; i++) /* just like before *
* { *
* ...blah - blah - blah *
* ------------------------------------------------------------ *
* 'glob ()' returns a negative value if any error occurs and *
* zero otherwise. *
* ============================================================ *
* 11/28/87 (1.06): If an argument is enclosed in single *
* quotes, it is considered not to be *
* globbable. The quotes should be *
* removed and the argument should not *
* be expanded (see 'expand ()'.) *
* ------------------------------------------------------------ *
*/
#include <stdio.h>
#include <dir.h>
static char *first; /* first element of expanded argument list */
static int newc; /* new argc */
/* ------------------------------------------------------------- *
* 'insert ()' puts a (possibly) expanded file name in the next *
* position in the list and updates the count in 'newc'. *
* ------------------------------------------------------------- *
* The function will return zero if no error occurred or -1 if *
* the 'sbrk ()' fails. *
* ------------------------------------------------------------- */
static int insert (char *newname)
{
char *p;
if (((int) (p = (char *) sbrk (strlen (newname) + 1))) == -1)
return (-2); /* 'sbrk ()' failed */
if (first == NULL)
first = p;
while ((*p++ = *newname++) != 0) /* copy newname */
;
newc++; /* bump the argument counter */
return (0); /* normal return */
}
/* ------------------------------------------------------------- *
* 'fullname ()' returns a pointer to the drive/path/file name *
* if one was used in the original argument. Note that the *
* abbreviation '..' is not translated to a to a full drive/- *
* path/name specification (although this could be done) but *
* returned as '..', which is sufficient to perform most types *
* of operations (open/read/write/close) on the file. *
* ------------------------------------------------------------- */
static char *fullname (char *argv, char *name)
{
int res;
char path [MAXDIR]; /* holds the path temporarily */
static char fullpath [MAXPATH]; /* holds the drive at first */
res = fnsplit (argv, &fullpath, &path, NULL, NULL);
if ((res & DIRECTORY) > 0) /* add path name */
strcat (fullpath, path);
strcat (fullpath, name); /* add file name */
strupr (fullpath); /* everything in upper case */
return (fullpath);
}
/* ------------------------------------------------------------- *
* 'expand ()' checks an argument for wildcards, expands it if *
* neccessary, and saves the expansion (or original, if no *
* wildcards were found) in a list. *
* ------------------------------------------------------------- *
* If errors are detected (during 'insert ()'), 'expand ()' is *
* terminated and the error is returned to the caller. *
* ------------------------------------------------------------- */
static int expand (char *argv, unsigned char attr)
{
int ret, /* stores 'insert ()' return code */
done; /* controls 'findnext ()' loop */
struct ffblk ffblk; /* used by 'findfirst ()' & 'findnext ()' */
if ((strpbrk (argv, "*?")) == NULL)
{ /* no wildcards in this argument */
if ((ret = insert (argv)) < 0)
return (ret); /* 'insert ()' returned error */
}
else /* this argument has wildcards -- expand it... */
{
done = findfirst (argv, &ffblk, attr);
while (!done)
{
if ((ret = insert (fullname (argv, ffblk.ff_name))) < 0)
return (ret); /* function returned error */
done = findnext (&ffblk);
}
}
return (0); /* normal return */
}
/* ------------------------------------------------------------- *
* 'makearray ()' traverses the argument list and creates the *
* new 'argv' pointer array. Zero is returned if no error or *
* -2 if a memory allocation error occurs. *
* ------------------------------------------------------------- */
static int makearray ()
{
int i; /* loop index counter */
char **p; /* pointer to array element */
p = (char **) sbrk (newc * sizeof (char *));
if ((int) p == -1) /* 'sbrk ()' failed */
return (-3);
for (i = 0; i < newc; i++) /* for each new argument */
{
*p++ = first++; /* set array element to address of string */
while (*first++ != 0) /* look for end of string */
;
}
return (0);
}
/* ---------------------------------------------------------- *
* 'fcmp ()' is the comparison function for 'qsort' below. *
* ---------------------------------------------------------- */
static int fcmp (char **a, char **b)
{
return (strcmp (*a, *b));
}
/* ---------------------------------------------------------- *
* The main 'glob ()' function expands wildcarded arguments *
* passed in 'argv' and plugs new values into 'argv' and *
* 'argc'. Zero is returned if no errors occur, or else a *
* negative number indicating the type of error is returned: *
* -1: 'sbrk ()' in 'glob ()' failed. *
* -2: 'sbrk ()' in 'insert ()' failed. *
* -3: 'sbrk ()' in 'makearray ()' failed. *
* ---------------------------------------------------------- */
int glob (int *argc, char **argv [], unsigned char attr)
{
int i,
ret; /* holds function return values */
char **p; /* pointer to 'argv [0]' */
/*
* save each argument or expansion in a list:
*/
newc = 0;
first = NULL;
for (i = 1; i < *argc; i++)
{
if ((ret = expand ((*argv) [i], attr)) < 0)
return (ret); /* 'expand ()' returned error */
}
/*
* save old 'argv [0]' (program name) in new 'argv' array:
*/
p = (char **) sbrk (sizeof (char *));
if ((int) p == -1)
return (-1); /* 'sbrk ()' failed */
*p = *argv [0]; /* save address of old 'argv [0]' */
*argv = p; /* point to second element in new array */
*argc = newc + 1;
if ((ret = makearray ()) < 0)
return (ret);
qsort (&((*argv) [1]), newc, sizeof (char **), fcmp);
return (0);
}