home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Overload
/
ShartewareOverload.cdr
/
progm
/
cpgms.zip
/
GREP.C
< prev
next >
Wrap
C/C++ Source or Header
|
1985-11-19
|
28KB
|
1,158 lines
/*
*
*
* The information in this document is subject to change
* without notice and should not be construed as a commitment
* by Digital Equipment Corporation or by DECUS.
*
* Neither Digital Equipment Corporation, DECUS, nor the authors
* assume any responsibility for the use or reliability of this
* document or the described software.
*
* Copyright (C) 1980, DECUS
*
*
* General permission to copy or modify, but not for profit, is
* hereby granted, provided that the above copyright notice is
* included and reference made to the fact that reproduction
* privileges were granted by DECUS.
*
*/
#include "stdio.h"
/* #include "ctype.h" */
/*
* grep.
*
* Runs on the Decus compiler or on vms.
* Converted for BDS compiler (under CP/M-80), 20-Jan-83, by Chris Kern.
*
* Converted to IBM PC with CI-C86 C Compiler June 1983 by David N. Smith
*
* Converted to IBM PC with DeSmet C Compiler July 1984 by Richard Threlkeld.
* Added wild card facility for MS-DOS 2.0 and up.
* Added flag to prefix output line with filename.
* Added use of "#" for a blank and ":#" for control meta
* (DeSmet C cannot handle blank in pattern well).
* Changed the backslash to an @ (at-sign) to allow
* unambiguous use of backslash for escaped characters
* (e.g. \t,\b,\f,\n,\r for tab, backspace, formfeed,
* newline, and carriage return, respectively).
* Added braces ('{' and '}') to group pattern elements. Plus,
* Minus, and Star all act on the delimited group as an element.
* This allows f{oo}+ to match only lines with an even number of
* 'o's after an 'f'. This is preparation for a CHANGE command.
*
* On vms, define as:
*
* grep :== "$disk:[account]grep" (native)
* grep :== "$disk:[account]grep grep" (Decus)
*
* See below for more information.
*
*/
#define QUOTE '@'
#define BLANK '#'
#define ESCAPE '\\'
char *documentation[] = {
"grep searches a file for a given pattern. Execute by",
" grep [flags] regular_expression file_list",
"",
"Flags are single characters preceeded by '-':",
" -c Only a count of matching lines is printed",
" -f Print file name for matching lines switch, see below",
" -p Prefix file name to output lines and turn on -f flag",
" -n Each line is preceeded by its line number",
" -v Only print non-matching lines",
"",
"The file_list is a list of files (wildcards are acceptable on RSX modes).",
"",
"The file name is normally printed if there is a file given.",
"The -f flag reverses this action (print name no file, not if more).",
"",
0 };
char *patdoc[] = {
"The regular_expression defines the pattern to search for. Upper- and",
"lower-case are always ignored. Blank lines never match. The expression",
"should be quoted to prevent file-name translation.",
"x An ordinary character (not mentioned below) matches that character.",
"'\\' The backslash escapes tab, backspace, formfeed, newline, and",
"' carriage return with \\t, \\b, \\f, \\n, and \\r.",
"'@' The at-sign quotes any character. \"@$\" matches a dollar-sign.",
"'^' A circumflex at the beginning of an expression matches the",
" beginning of a line.",
"'$' A dollar-sign at the end of an expression matches the end of a line.",
"'.' A period matches any character except \"new-line\".",
"'#' An \"at-sign\" matches one blank.",
"':a' A colon matches a class of characters described by the following",
"':d' character. \":a\" matches any alphabetic, \":d\" matches digits,",
"':n' \":n\" matches alphanumerics, \": \" matches spaces, tabs, and",
"':#' other control characters, such as new-line.",
"'*' An expression followed by an asterisk matches zero or more",
" occurrances of that expression: \"fo*\" matches \"f\", \"fo\"",
" \"foo\", etc.",
"'+' An expression followed by a plus sign matches one or more",
" occurrances of that expression: \"fo+\" matches \"fo\", etc.",
"'-' An expression followed by a minus sign optionally matches",
" the expression.",
"'[]' A string enclosed in square brackets matches any character in",
" that string, but no others. If the first character in the",
" string is a circumflex, the expression matches any character",
" except \"new-line\" and the characters in the string. For",
" example, \"[xyz]\" matches \"xx\" and \"zyx\", while \"[^xyz]\"",
" matches \"abc\" but not \"axb\". A range of characters may be",
" specified by two characters separated by \"-\". Note that,",
" [a-z] matches alphabetics, while [z-a] never matches.",
"'{}' Group regular expressions into one pattern element: f{oo}+",
" will only match an 'f' followed by an even number of 'o's.",
" Braces may be nested. They are not allowed in square brackets.",
"The concatenation of regular expressions is a regular expression.",
0};
#define DeSmet 1
#define MSDOS 1
#ifndef stdin
#define stdin STDIN
#define stdout STDOUT
#define stderr STDERR
#endif
#define LMAX 512
#define PMAX 256
#define CHAR 1
#define BOL 2
#define EOL 3
#define ANY 4
#define CLASS 5
#define NCLASS 6
#define STAR 7
#define PLUS 8
#define MINUS 9
#define ALPHA 10
#define DIGIT 11
#define NALPHA 12
#define PUNCT 13
#define RANGE 14
#define ENDPAT 15
#define BRACE 16
#define ENDBRACE 17
int cflag;
int fflag;
int nflag;
int vflag;
int pflag;
int nfile;
int debug = 0; /* Set for debug code */
char *pp;
#ifndef vms
char file_name[81];
#endif
char lbuf[LMAX];
char pbuf[PMAX];
/*******************************************************/
main(argc, argv)
char *argv[];
{
register char *p;
register int c, i;
int gotpattern;
int gotcha;
char *fexpnd();
FILE *f;
if (argc <= 1)
usage("No arguments");
if (argc == 2 && argv[1][0] == '?' && argv[1][1] == 0) {
help(documentation);
help(patdoc);
return;
}
nfile = argc-1;
gotpattern = 0;
for (i=1; i < argc; ++i) {
p = argv[i];
if (*p == '-') {
++p;
while (c = *p++) {
switch(tolower(c)) {
case '?':
help(documentation);
break;
case 'C':
case 'c':
++cflag;
break;
case 'D':
case 'd':
++debug;
break;
case 'F':
case 'f':
++fflag;
break;
case 'p':
case 'P':
++pflag;
fflag = 1;
break;
case 'n':
case 'N':
++nflag;
break;
case 'v':
case 'V':
++vflag;
break;
default:
usage("Unknown flag");
}
}
argv[i] = 0;
--nfile;
} else if (!gotpattern) {
compile(p);
argv[i] = 0;
++gotpattern;
--nfile;
}
}
if (!gotpattern)
usage("No pattern");
if (nfile == 0)
grep(stdin, 0);
else {
fflag = fflag ^ (nfile > 0);
for (i=1; i < argc; ++i) {
#if MSDOS
if (argv[i])
while (p = fexpnd(argv[i])) {
#else
if (p = argv[i]) {
#endif
if ((f=fopen(p, "r")) == NULL)
cant(p);
else {
grep(f, p);
fclose(f);
}
}
}
}
}
/*******************************************************/
file(s)
char *s;
{
printf("File %s:\n", s);
}
/*******************************************************/
cant(s)
char *s;
{
fprintf(stderr, "%s: cannot open\n", s);
}
/*******************************************************/
help(hp)
char **hp; /* dns added extra '*' */
/*
* Give good help
*/
{
register char **dp;
for (dp = hp; *dp; dp++)
printf("%s\n", *dp);
}
/*******************************************************/
usage(s)
char *s;
{
fprintf(stderr, "?GREP-E-%s\n", s);
fprintf(stderr,
"Usage: grep [-cfnv] pattern [file ...]. grep ? for help\n");
exit(1);
}
/*******************************************************/
compile(source)
char *source; /* Pattern to compile */
/*
* Compile the pattern into global pbuf[]
*/
{
register char *s; /* Source string pointer */
register int c; /* Current character */
int o; /* Temp */
char *pcompil(); /* Compile braced group */
pp = pbuf;
s = source;
if (debug)
printf("Pattern = \"%s\"\n", s);
s = pcompil(s);
if (*(--s) == '}')
badpat("Unmatched close brace",source,s);
}
/*******************************************************/
char *
pcompil(source)
char *source; /* Pattern to compile */
/*
* Compile (recursively) the pattern into global pbuf[]
*/
{
register char *s; /* Source string pointer */
register char *lp; /* Last pattern pointer */
register int c; /* Current character */
int o; /* Temp */
char *spp; /* Save beginning of pattern */
char *cclass(); /* Compile class routine */
char *sbrace(); /* Compile braced group */
char spchr(); /* Translate char to escaped char */
s = source;
while (c = *s++) {
/*
* STAR, PLUS and MINUS are special.
*/
if (c == '*' || c == '+' || c == '-') {
if (pp == pbuf ||
(o=pp[-1]) == BOL ||
o == EOL ||
o == STAR ||
o == PLUS ||
o == MINUS)
badpat("Illegal occurrance op.", source, s);
store(ENDPAT);
store(ENDPAT);
spp = pp; /* Save pattern end */
while (--pp > lp) /* Move pattern down */
*pp = pp[-1]; /* one byte */
*pp = (c == '*') ? STAR :
(c == '-') ? MINUS : PLUS;
pp = spp; /* Restore pattern end */
continue;
}
/*
* All the rest.
*/
lp = pp; /* Remember start */
switch(c) {
case BLANK:
store(CHAR);
store(' ');
break;
case '^':
store(BOL);
break;
case '$':
store(EOL);
break;
case '.':
store(ANY);
break;
case '}': /* brace pairs group pattern strings */
return(s);
case '{': /* brace pairs group pattern strings */
s = sbrace(source, s);
break;
case '[':
s = cclass(source, s);
break;
case ':':
if (*s) {
c = *s++;
switch(tolower(c)) {
case 'a':
case 'A':
store(ALPHA);
break;
case 'd':
case 'D':
store(DIGIT);
break;
case 'n':
case 'N':
store(NALPHA);
break;
case BLANK:
store(PUNCT);
break;
default:
badpat("Unknown : type", source, s);
}
break;
}
else badpat("No : type", source, s);
case QUOTE:
if (*s) {
c = *s++;
store(CHAR);
store(tolower(c));
}
break;
case ESCAPE:
if (*s) {
store(CHAR);
store(spchr(tolower(c=*s++)));
}
break;
default:
store(CHAR);
store(tolower(c));
}
}
store(ENDPAT);
store(0); /* Terminate string */
if (debug) {
for (lp = pbuf; lp < pp;) {
if ((c = (*lp++ & 0377)) < ' ')
printf("%d ", c);
else printf("%c ", c);
}
printf("\n");
}
return(s);
}
/*******************************************************/
char spchr(inchar)
char inchar;
{
switch(inchar) {
case 't':
return('\t');
case 'b':
return('\b');
case 'f':
return('\f');
case 'n':
return('\n');
case 'r':
return('\r');
default:
return(inchar);
}
}
/*******************************************************/
char *
cclass(source, src)
char *source; /* Pattern start -- for error msg. */
char *src; /* Class start */
/*
* Compile a class (within [])
*/
{
register char *s; /* Source pointer */
register char *cp; /* Pattern start */
register int c; /* Current character */
int o; /* Temp */
char spchr(); /* Translate char to escaped char */
s = src;
o = CLASS;
if (*s == '^') {
++s;
o = NCLASS;
}
store(o);
cp = pp;
store(0); /* Byte count */
while ((c = *s++) && c!=']') {
if (c == QUOTE) { /* Store quoted char */
if ((c = *s++) == '\0') /* Gotta get something */
badpat("Class terminates badly", source, s);
else store(tolower(c));
}
else if (c == ESCAPE) {
if ((c = *s++) == '\0')
badpat("Invalid Escape sequence", source, s);
else
store(spchr(c));
}
else if (c == '-' &&
(pp - cp) > 1 && *s != ']' && *s != '\0') {
c = pp[-1]; /* Range start */
pp[-1] = RANGE; /* Range signal */
store(c); /* Re-store start */
c = *s++; /* Get end char and*/
store(tolower(c)); /* Store it */
}
else {
store(tolower(c)); /* Store normal char */
}
}
if (c != ']')
badpat("Unterminated class", source, s);
if ((c = (pp - cp)) >= 256)
badpat("Class too large", source, s);
if (c == 0)
badpat("Empty class", source, s);
*cp = c;
return(s);
}
/*******************************************************/
char *
sbrace(source, src)
char *source; /* Pattern start -- for error msg. */
char *src; /* Bracketed area start */
/*
* Compile a pattern withing {} (a grouping)
*/
{
register char *s; /* Source pointer */
register int c; /* Current character */
int o; /* Temp */
s = src;
o = BRACE;
store(o);
s = pcompil(s); /* call compile to finish pattern */
if (s[-1] == '}') /* set up end of group */
store(ENDBRACE);
else
badpat("Unmatched brace",source,s);
return(s);
}
/*******************************************************/
store(op)
{
if (pp >= &pbuf[PMAX])
error("Pattern too complex\n");
*pp++ = op;
}
/*******************************************************/
badpat(message, source, stop)
char *message; /* Error message */
char *source; /* Pattern start */
char *stop; /* Pattern end */
{
register int c, lp;
if (debug) {
for (lp = pbuf; lp < pp;) {
if ((c = (*lp++ & 0377)) < ' ')
printf("%d ", c);
else printf("%c ", c);
}
printf("\n");
}
fprintf(stderr, "-GREP-E-%s, pattern is\"%s\"\n", message, source);
fprintf(stderr, "-GREP-E-Stopped at byte %d, '%c'\n",
stop-source, stop[-1]);
error("?GREP-E-Bad pattern\n");
}
/*******************************************************/
grep(fp, fn)
FILE *fp; /* File to process */
char *fn; /* File name (for -f option) */
/*
* Scan the file for the pattern in pbuf[]
*/
{
register int lno, count, m;
lno = 0;
count = 0;
while (fgets(lbuf, LMAX, fp)) {
++lno;
#if DeSmet
for (m=0; lbuf[m]; m++)
if ((lbuf[m] == '\r') || (lbuf[m] == '\n'))
lbuf[m] = '\0';
#endif
m = match();
if ((m && !vflag) || (!m && vflag)) {
++count;
if (!cflag) {
if (fflag && fn) {
file(fn);
fn = 0;
}
if (pflag && fn)
printf("%s\t", fn);
if (nflag)
printf("%d\t", lno);
printf("%s\n", lbuf);
}
}
}
if (cflag) {
if (fflag && fn)
file(fn);
printf("%d\n", count);
}
}
/*******************************************************/
match()
/*
* Match the current line (in lbuf[]), return 1 if it does.
*/
{
register char *l; /* Line pointer */
char *pmatch();
for (l = lbuf; *l; l++) {
if (pmatch(l, pbuf))
return(1);
}
return(0);
}
/*******************************************************/
char *
pmatch(line, pattern)
char *line; /* (partial) line to match */
char *pattern; /* (partial) pattern to match */
{
register char *l; /* Current line pointer */
register char *p; /* Current pattern pointer */
register char c; /* Current character */
char *e; /* End for STAR and PLUS match */
int op; /* Pattern operation */
int n; /* Class counter */
char *are; /* Start of STAR match */
l = line;
if (debug > 1)
printf("pmatch(\"%s\")\n", line);
p = pattern;
while ((op = *p++) != ENDPAT) {
if (debug > 1)
printf("byte[%d] = 0%o, '%c', op = 0%o\n",
l-line, *l, *l, op);
switch(op) {
case CHAR:
if (tolower(*l++) != *p++)
return(0);
break;
case BOL:
if (l != lbuf)
return(0);
break;
case EOL:
if (*l != '\0')
return(0);
break;
case ANY:
if (*l++ == '\0')
return(0);
break;
case DIGIT:
if ((c = *l++) < '0' || (c > '9'))
return(0);
break;
case ALPHA:
c = tolower(*l++);
if (c < 'a' || c > 'z')
return(0);
break;
case NALPHA:
c = tolower(*l++);
if (c >= 'a' && c <= 'z')
break;
else if (c < '0' || c > '9')
return(0);
break;
case PUNCT:
c = *l++;
if (c == 0 || c > ' ')
return(0);
break;
case BRACE:
e = pmatch(l, p); /* match braced group */
while (*p++ != ENDBRACE) ; /* skip matched group */
if (e)
l = e; /* if match, update area */
else
return(0); /* else, return no match */
break;
case CLASS:
case NCLASS:
c = tolower(*l++);
n = *p++ & 0377;
do {
if (*p == RANGE) {
p += 3;
n -= 2;
if (c >= p[-2] && c <= p[-1])
break;
}
else if (c == *p++)
break;
} while (--n > 1);
if ((op == CLASS) == (n <= 1))
return(0);
if (op == CLASS)
p += n - 2;
break;
case MINUS:
e = pmatch(l, p); /* Look for a match */
while (*p++ != ENDPAT); /* Skip over pattern */
if (e) /* Got a match? */
l = e; /* Yes, update string */
break; /* Always succeeds */
case PLUS: /* One or more ... */
if ((l = pmatch(l, p)) == 0)
return(0); /* Gotta have a match */
case STAR: /* Zero or more ... */
are = l; /* Remember line start */
while (*l && (e = pmatch(l, p)))
l = e; /* Get longest match */
while (*p++ != ENDPAT); /* Skip over pattern */
while (l >= are) { /* Try to match rest */
if (e = pmatch(l, p))
return(e);
--l; /* Nope, try earlier */
}
return(0); /* Nothing else worked */
default:
printf("Bad op code %d\n", op);
error("Cannot happen -- match\n");
}
}
return(l);
}
/*******************************************************/
itoa(n,s) /* convert n to characters in s */
char s[];
int n;
{
int i,sign;
if ((sign = n) < 0) /* record sign */
n = -n; /* make positive */
i = 0;
do { /* generate digits in reverse order */
s[i++] = n % 10 + '0'; /* get next digit */
} while ((n /= 10) > 0); /* delete it */
if (sign < 0)
s[i++] = '-';
s[i] = '\0';
reverse(s);
}
reverse(s) /* reverse string s in place */
char s[];
{
int c, i, j;
for (i=0, j=strlen(s)-1; i<j; i++, j--) {
c = s[i];
s[i] = s[j];
s[j] = c;
}
}
/*******************************************************/
error(s)
char *s;
{
fprintf(stderr, "%s", s);
exit(1);
}
/*******************************************************/
#if MSDOS
/*******************************************************/
/*
fexpnd returns a pointer to the next filename.ext which
matches the first parameter (str) or a zero is no file
matches that parameter. The given parameter is processed
to generate a normalized search string and a normalized
path prefix. The prefix is returned in the area pointed to
by the second parameter. This string may be concatenated
with the returned value to give a fully-qualified dataset
name for open, rename, erase, etc.
You should continue calling fexpnd with the same first
parameter until it returns a zero, then pass it a new first
parameter. This can be used to expand a list of ambiguous
filenames on a parameter list. */
char mydta[80] = {0};
char fxs[80] = {0};
char fxsrch[80] = {0};
char fxpref[80] = {0};
char *fexpnd(str, path)
char *str, *path;
{
int getret, fixpath(), strcpy(), dirnxt(), dirfst();
int savdta(), restdta();
char *rindex();
savdta(); /* save old dta in an unknown location */
setdta(&mydta); /* make MS-DOS use my dta */
if (strcmp(str,fxs) == 0)
getret = dirnxt(); /* MS-DOS 2.0+ get next function */
else {
strcpy(fxs,str); /* for detection of a new name */
if (!fixpath(str, fxsrch, fxpref))
return (0);
strcpy(path, fxpref); /* give path to caller */
getret = dirfst(fxsrch); /* MS-DOS 2.0+ get first function */
}
restdta(); /* restore old dta */
if (getret == 0) {
return(&mydta[30]); /* return filename.ext */
}
else
return 0;
}
int dtads, dtadx;
savdta()
{
#asm
PUSH AX
PUSH ES
PUSH BX
MOV AH,2fh
INT 21h
MOV WORD dtads_,ES
MOV WORD dtadx_,BX
POP BX
POP ES
POP AX
#
}
restdta()
{
#asm
PUSH DS
PUSH DX
PUSH AX
MOV DX,WORD dtads_
MOV DS,DX
MOV DX,WORD dtadx_
MOV AH,1AH
INT 21h
POP AX
POP DX
POP DS
#
}
char *dtap;
setdta(newdta)
char *newdta;
{
dtap = newdta;
#asm
PUSH DX
PUSH AX
MOV DX,WORD dtap_
MOV AH,1AH
INT 21h
POP AX
POP DX
#
}
char *dirfnp;
dirfst(s)
char *s;
{
dirfnp = s;
#asm
PUSH DX
PUSH CX
MOV DX,WORD dirfnp_
MOV AH,4eh
INT 21h
JC D56X1
MOV AX,0
D56X1: NOP
POP CX
POP DX
#
}
dirnxt()
{
#asm
MOV AH,4fh
INT 21h
JC D56X2
MOV AX,0
D56X2: NOP
#
}
/* ================================================================ */
/*
From Dr. Dobbs #108 October 1985. */
/* fixpath() processes a DOS pathname for two different uses.
The input path, *ip, is presumably a command operand like the
first operand of DIR. One output, the search path *sp, is
the input possibly augmented with "*.*" or "\*.*" so that it
will work reliably with DOS functions 4E/$f. The other output
is a lead-in path, *lip, which can be prefixed to the simple
filename.ext returned by fuctions 4E/4F to make a complete path
for opening or erasing a file.
The function returns 1 if it is successful, but 0 if the
input path can't be processed and should not be used.
Some input paths can be processed here yet be invalid or
useless. The search path produced from such an input wwill
cause an error return from function 4E (search first match). */
/* ================================================================ */
int fixpath(ip, sp, lip)
register char *ip, /* input path */
*sp, /* the search path */
*lip; /* the lead-in or prefix path */
{
char *cp; /* work pointer for scanning paths */
char attr; /* attribute for chgattr */
int ret, strlen(), strcpy(), strcmp(), strcat(), chgattr();
/* ================================================================ */
/* Pick off 4 special cases:
(1) the NULL string, which we take to mean "*.*"
(2) the simple "d:" reference to a drive, which we also take
to mean "d:*.*"
(3) the root-dir reference "d:\" which is mishandled by
function 0x4300 of both dDOS 2.1 and 3.0.
(4) any reference that ends in "\"
In all cases, the input path is ok as a lead-in, but it needs
the global qualifier *.* added for searching.
/* ================================================================ */
if ((strlen(ip) == 0) /* null string */
|| (strcmp(ip+1, ":") == 0) /* d: only */
|| (ip[strlen(ip)-1] == '\\')) /* ends in backslash */
{
strcpy(lip, ip); /* input is ok as prefix */
strcpy(sp, ip);
strcat(sp, "*.*"); /* add *.* for search */
return (1);
}
/* ================================================================ */
/* Ok, we have a non-null string not ending in \ and not a lone
drive letter. Four possibilities remain:
(1) an explicit file reference, b:\mydir\mydat
(2) an explicit directory reference, \mydir
(3) an ambiguous file reference, *.* or b:\mydir\*.dat
(4) an unknown name, a:noway or b:\mydir\nonesuch.dat
We can separate this with fair reliability using DOS function
0x4300, get attributes from path.
/* ================================================================ */
attr = 0x00; /* output area for get command */
ret = chgattr('G', ip, &attr); /* get attributes for this path */
if (ret == 0x0002)
/* the path is valid, in that all directories and drives
named in it are valid, but the final name is unknown. No
files will be found in a search, so quit now. */
return (0);
if ((ret == 0x0003)
|| ((ret == 0) && ((attr & 0x0010) == 0))) {
/* Error 3, path not found, could mean total junk or a
misspelt directory name, but most likely it just means
the path ends in an ambiguous name. If there's an error
the initial search (function 4Eh) will fail.
With no error and reg cx not showing the directory
attribute flags 0010, we have a normal, unambiguous file
pathname like "b:\mydir\mydat" or just "myprog.com".
In either case the search path is the whole input
path. The lead-in is that shorn of whatever follows the
rightmost \ or :, whichever comes last -- or just a null
string if there is no \ or :. */
strcpy(sp, ip); /* working copy of ip in sp */
cp = sp + strlen(sp) -1;
for (; cp > sp; --cp)
if (('\\' == *cp) || (':' == *cp))
break;
if (cp > sp)
++cp; /* retain colon or slash */
*cp = '\0'; /* make a null string */
strcpy(lip, sp);
strcpy(sp, ip); /* whole input for search */
return (1);
}
if ((ret == 0) && (attr & 0x0010)) {
/* No error and the directory attribute returned in cx
shows an unambiguous path that happpens to end in the
name of a directory, for instance "..\..\bin" or
"b:\mydir". Applying the rules of DIR or COPY, we
have to treat these as global refs to all files named in
the directory. The search path is the input with
"\*.*" tacked onto it. The lead-in path is just the
input plus a backslash. */
strcpy(sp, ip);
strcpy(lip, ip);
strcat(sp, "\\*.*");
strcat(lip, "\\");
return (1);
}
else {
/* unexpected events make me nervous, so give up */
return (0);
}
}
int rax, rcx;
char *rdx;
int chgattr(getset, path, attr)
char getset, *path, *attr;
{
if (getset == 'S') {
rcx = *attr;
rax = 0x4301;
}
else
rax = 0x4300;
rdx = path;
#asm
PUSH DX
PUSH CX
PUSH AX
MOV DX,WORD rdx_
MOV AX,WORD rax_
MOV CX,WORD rcx_
INT 21H
MOV WORD rax_,AX
JC D56X9
MOV WORD rax_,0
D56X9: NOP
MOV WORD rcx_,CX
POP AX
POP CX
POP DX
#
if (rax == 0)
*attr = rcx;
return(rax);
}
#endif