Category : C Source Code
Archive   : Z201SRC.ZIP
Filename : NEXTFILE.C

 
Output of file : NEXTFILE.C contained in archive : Z201SRC.ZIP

#ifndef LINT
static char sccsid[]="@(#) nextfile.c 2.2 87/12/26 12:23:43";
#endif /* LINT */

#include "options.h"
/*
Copyright (C) 1986, 1987 Rahul Dhesi -- All rights reserved
*/
/*
Functions to collect filenames from command line etc. Nextfile() is
used by both Atoz and Zoo. Wildcard expansion by nextfile() is specific to
MS-DOS and this implementation is specific to Microsoft C. If the symbol
PORTABLE is defined, nextfile() becomes effectively a no-op that will return
the original filespec the first time and NULL subsequently.
*/

#define FMAX 3 /* Number of different filename patterns */

#ifndef OK_STDIO
#include
#define OK_STDIO
#endif
#include "various.h"
#include "zoo.h" /* solely to define PATHSIZE */

#ifdef PORTABLE
#ifndef SPECNEXT
/* If portable version, nextfile() is effectively a no-op and any wildcard
expansion must be done by the runtime system before the command line
is received by this program
*/
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 int first_time [FMAX+1];
static char saved_fspec [FMAX+1][PATHSIZE]; /* our own copy of filespec */

if (what == 0) {
strcpy (saved_fspec[fileset], filespec); /* save the filespec */
first_time[fileset] = 1;
return (NULL);
}

if (first_time[fileset]) {
first_time[fileset] = 0;
return (saved_fspec[fileset]);
} else {
return (NULL);
}
}
#endif /* SPECNEXT */
#else
/* if not PORTABLE then */

#include "intdos.h" /* registers for MS-DOS interrupts */
#include "dta.h" /* format of MS-DOS disk transfer area (dta) */
#include "assert.h" /* macro definition: assert() macro */

void setdta (struct dta_t *);
void fcbpath (struct dta_t *, 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_t new_dta [FMAX+1]; /* our own private dta */
static int first_time [FMAX+1];
static char pathholder [FMAX+1][PATHSIZE]; /* holds a pathname to return */
static char saved_fspec [FMAX+1][PATHSIZE];/* our own copy of filespec */
union REGS regs;

assert(fileset >= 0 && fileset <= FMAX);
if (what == 0) {
assert(filespec != NULL);
strcpy (saved_fspec[fileset], filespec); /* save the filespec */
first_time[fileset] = 1;
return (NULL);
}

setdta (&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 */
regs.h.ah = 0x4e; /* FindFirst DOS call */
regs.x.dx = (unsigned int) saved_fspec[fileset]; /* filespec to match */
regs.x.cx = 0; /* search attributes */
intdos (®s, ®s);
} else {
/* find next matching file */
regs.h.ah = 0x4f; /* FindNext DOS call */
intdos (®s, ®s);
}

if (regs.x.carry != 0) { /* 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 (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 */

/*******************/
/* This function sets the dta to a new dta */
void setdta (dta)
struct dta_t *dta;
{
union REGS regs;
regs.h.ah = 0x1a; /* SetDTA Call */
regs.x.dx = (unsigned int) dta; /* new DTA address */
intdos (®s, ®s);
}

/*******************/
/*
fcbpath() accepts a pointer to the Disk Transfer Area (the DTA format is
described on page 131 of Tandy-1000 programmers reference manual), a
character pointer to a pathname that may contain wildcards, and a character
pointer to a buffer. Copies into 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_t *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->fname[i];
new_path[start_pos+13] = '\0';
}
#endif /* PORTABLE */