#include #define FMAX 2 /* Number of different filename patterns */ #include #include void fcbpath (struct _dta *, char *, char *); /* nextfile() returns the name of the next source file matching a filespec. INPUT what: A flag specifying what to do. If "what" is 0, nextfile() initializes itself. If "what" is 1, nextfile() returns the next matching filename. filespec: The filespec, usually containing wildcard characters, that specifies which files are needed. If "what" is 0, filespec must be the filespec for which matching filenames are needed. If "what" is 1, nextfile() does not use "filespec" and "filespec" should be NULL to avoid an assertion error during debugging. fileset: nextfile() can keep track of more than one set of filespecs. The fileset specifies which filespec is being matched and therefore which set of files is being considered. "fileset" can be in the range 0:FMAX. Initialization of one fileset does not affect the other filesets. OUTPUT IF what == 0 THEN return value is NULL ELSE IF what == 1 THEN IF a matching filename is found THEN return value is pointer to matching filename including supplied path ELSE IF at least one file matched previously but no more match THEN return value is NULL ELSE IF supplied filespec never matched any filename THEN IF this is the first call with what == 1 THEN return value is pointer to original filespec ELSE return value is NULL END IF END IF END IF END IF NOTE Initialization done when "what"=0 is not dependent on the correctness of the supplied filespec but simply initializes internal variables and makes a local copy of the supplied filespec. If the supplied filespec was illegal, the only effect is that the first time that nextfile() is called with "what"=1, it will return the original filespec instead of a matching filename. That the filespec was illegal will become obvious when the caller attempts to open the returned filename for input/output and the open attempt fails. USAGE HINTS nextfile() can be used in the following manner: char *filespec; -- will point to filespec char *this_file; -- will point to matching filename filespec = parse_command_line(); -- may contain wildcards FILE *stream; nextfile (0, filespec, 0); -- initialize fileset 0 while ((this_file = nextfile(1, (char *) NULL, 0)) != NULL) { stream = fopen (this_file, "whatever"); if (stream == NULL) printf ("could not open %s\n", this_file); else perform_operations (stream); } */ char *nextfile (what, filespec, fileset) int what; /* whether to initialize or match */ register char *filespec; /* filespec to match if initializing */ register int fileset; /* which set of files */ { static struct _dta new_dta [FMAX+1]; /* our own private dta */ static int first_time [FMAX+1]; /* holds a pathname to return */ static char pathholder [FMAX+1][FILENAME_MAX]; /* our own copy of filespec */ static char saved_fspec [FMAX+1][FILENAME_MAX]; static done; assert(fileset >= 0 && fileset <= FMAX); if (what == 0) { assert(filespec != NULL); strcpy (saved_fspec[fileset], filespec); /* save the filespec */ first_time[fileset] = 1; return ((char *) NULL); } Fsetdta (&new_dta[fileset]); /* set new dta -- our very own */ assert(what == 1); assert(filespec == NULL); assert(first_time[fileset] == 0 || first_time[fileset] == 1); if (first_time[fileset]) /* first time -- initialize etc. */ /* find first matching file */ done = Fsfirst(saved_fspec[fileset], 0); else /* find next matching file */ done = Fsnext(); if (done) { /* if error status */ if (first_time[fileset]) { /* if file never matched then */ first_time[fileset] = 0; return (saved_fspec[fileset]);/* return original filespec */ } else { /* else */ first_time[fileset] = 0; /* */ return ((char *) NULL); /* return (NULL) for no more */ } } else { /* a file matched */ first_time[fileset] = 0; /* add path info */ fcbpath (&new_dta[fileset], saved_fspec[fileset], pathholder[fileset]); return (pathholder[fileset]); /* matching path */ } } /* nextfile */ /* fcbpath() accepts a pointer to the Disk Transfer Area, a character pointer to a pathname that may contain wildcards, and a character pointer to a buffer. It copies into the buffer the path prefix from the pathname and the filename prefix from the DTA so that it forms a complete path. */ void fcbpath (dta, old_path, new_path) struct _dta *dta; char *old_path; register char *new_path; { register int i; int length, start_pos; strcpy(new_path, old_path); /* copy the whole thing first */ length = strlen(new_path); i = length - 1; /* i points to end of path */ while (i >= 0 && new_path[i] != '/' && new_path[i] != '\\' && new_path[i] != ':') i--; /* either we found a "/", "\", or ":", or we reached the beginning of the name. In any case, i points to the last character of the path part. */ start_pos = i + 1; for (i = 0; i < 13; i++) new_path[start_pos+i] = dta->dta_name[i]; new_path[start_pos+13] = '\0'; }