|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T p
Length: 11525 (0x2d05)
Types: TextFile
Names: »parsesbr.c«
└─⟦9ae75bfbd⟧ Bits:30007242 EUUGD3: Starter Kit
└─⟦e7f64e0c0⟧ »EurOpenD3/mail/vmh.tar.Z«
└─⟦dcb95597f⟧
└─⟦this⟧ »parsesbr.c«
#ifndef lint
static char rcsid[] =
"$Header: parsesbr.c,v 1.2 86/02/27 16:09:15 deboor Exp $";
static char notice[] =
"This program is in the public domain and is available for unlimited \
distribution as long as this notice is enclosed.";
#endif lint
/*
* $Source: /c/support/deboor/usr/src/old/vmh/RCS/parsesbr.c,v $
* $Revision: 1.2 $ $Date: 86/02/27 16:09:15 $
* $Author: deboor $
*
* Routines for parsing a 'pick' criteria string.
*
* FUNCTIONS:
* parseExpr parses the (fractured) expression and leaves the
* expression tree rooted to expRoot;
*/
#include "vmh.h"
#include "pick.h"
static NODE *parseStack[MAXARGS]; /* temp stack for actual parsing */
static int parseTop; /* top of this stack */
static nodeT opStack[MAXARGS]; /* stack for infix->postfix translation */
static int opTop; /* top of operator stack */
static int numHeaders; /* the number of headers in headers */
#ifdef DEBUG
u_char marks[50][20];
int nodeNum;
printTree (root)
NODE *root;
{
bzero (marks, sizeof(marks));
nodeNum = 0;
(void) markTree (root, 0);
nodeNum = 0;
printIt (root, 0);
DeBuG ("\n");
}
markTree (root, level)
NODE *root;
int level;
{
register int lnum,
rnum,
ournum,
i;
if (root->n_left != NILNODE) {
lnum = markTree (root->n_left, level + 1);
} else
lnum = nodeNum;
ournum = nodeNum++;
for (i = lnum; i <= ournum; i++)
marks[i][level] = 1;
if (root->n_right != NILNODE) {
rnum = markTree (root->n_right, level + 1);
} else
rnum = nodeNum - 1;
for (i = ournum; i <= rnum; i++)
marks[i][level] = 1;
return (ournum);
}
printIt (root, level)
NODE *root;
int level;
{
register int i;
if (root->n_left != NILNODE) {
printIt (root->n_left, level + 1);
}
for (i = 0; i <= level; i++) {
DeBuG ("%6s", marks[nodeNum][i] ? "|" : " ");
}
DeBuG ("-");
switch (root->n_which) {
case not: DeBuG ("not"); break;
case and: DeBuG ("and"); break;
case or: DeBuG ("or"); break;
case body: DeBuG ("search %s", root->n_key1); break;
case header: DeBuG ("%s %s",root->n_key1, root->n_key2);break;
case before: DeBuG ("before %d/%d/%d",root->n_month,root->n_day,root->n_year); break;
case after: DeBuG ("after %d/%d/%d", root->n_month,
root->n_day, root->n_year); break;
default: DeBuG ("???"); break;
}
DeBuG (" (%sdone; value = %s)\n", root->n_done == true ? "" : "not ",
root->n_value == TRUE ? "TRUE" : root->n_value == FALSE ?
"FALSE" : "UNKNOWN");
nodeNum++;
if (root->n_right != NILNODE) {
printIt (root->n_right, level + 1);
}
}
#endif DEBUG
/*
* NODE *
* makeNode (which, left, right, arg1, arg2, arg3)
* create a new NODE and install 'which' in the n_which field, 'left'
* in the n_left field and 'right' in the n_right field. Then, depending
* on the value of 'which', use arg[123] in one of the following ways:
*
* which arg1 arg2 arg3
* ----------------------------------------------------
* and,or,not unused unused unused
* header key1 (header) key2 (in header) unused
* body key1 (to find) unused unused
* after,before month day year
*
* makeNode returns a pointer to the new node with n_done and n_value
* initialized properly.
*/
/*VARARGS3*/
static NODE *
makeNode (which, left, right, arg1, arg2, arg3)
nodeT which; /* what type of node this is to be */
NODE *left, /* its left child */
*right; /* its right child */
caddr_t arg1, /* key1 for patterns, month for dates */
arg2, /* key2 for patterns, day for dates */
arg3; /* nothing for patterns, year for dates */
{
register NODE *tNode;
tNode = AllocST(NODE); /* allocate the new structure */
tNode->n_left = left; /* install the non-unionized parameters */
tNode->n_right = right;
tNode->n_which = which;
tNode->n_done = false; /* initialize traversal values */
tNode->n_value = UNKNOWN;
switch (which) { /* deal with the union */
case and: /* operators have no further parameters */
case or:
case not:
/* void */
break;
case body: /* search patterns have but one key whose offsets */
/* need to be determined */
tNode->n_key1 = (char *) arg1;
setoffsets (tNode->n_key1, tNode->n_key1offs);
break;
case header: /* headers need to have the two keys */
/* installed and their offsets determined */
tNode->n_key1 = (char *) arg1;
tNode->n_key2 = (char *) arg2;
setoffsets (tNode->n_key1, tNode->n_key1offs);
setoffsets (tNode->n_key2, tNode->n_key2offs);
break;
case after: /* dates need the date slots filled in */
case before:
tNode->n_month = (int) arg1;
tNode->n_day = (int) arg2;
tNode->n_year = (int) arg3;
break;
default: /* anything else is a screw up */
punt ("internal error! (bad which in makeNode)");
/*NOTREACHED*/
}
return tNode;
} /*makeNode*/
/*
* days of the week (unused)
*/
static struct swit days[] = {
"sunday", 0,
"monday", 0,
"tuesday", 0,
"wednesday", 0,
"thursday", 0,
"friday", 0,
"saturday", 0,
(char *) NULL, 0,
};
/*
* doOp (opType)
* combine the operator opType with the 1 or 2 items on the top
* of the parseStack to form a subtree, then put the new node on
* the stack.
*/
static
doOp (opType)
nodeT opType;
{
switch (opType) {
case not:
parseStack[parseTop-1] = makeNode (not, parseStack[parseTop-1],
NILNODE);
break;
case and:
case or:
if (parseTop < 2) {
errormsg ("too many operators", 1);
return (0);
}
parseStack[parseTop-2] = makeNode(opType,parseStack[parseTop-1],
parseStack[parseTop-2]);
parseTop--;
break;
default:
punt ("unknown opType received in doOp");
/*NOTREACHED*/
}
return (1);
} /* doOp */
/*
* DATE *
* getDate (dstring)
* parse the date given by the string in dstring according to the
* following format:
* <day>.<month>,<year>
* the period and comma may be any non-digit and any item not present
* defaults to the current date.
* If there is an error in the string NULL is returned. The numbers are
* stored in static structure, so they must be copied if they are to be
* saved.
*/
static DATE *
getDate (dstring)
char *dstring;
{
register char *cp;
register int tNum;
static struct tm *timeNow = (struct tm *) NULL;
time_t cur,
time();
static DATE dateGotten;
if (timeNow == (struct tm *) NULL) {
cur = time ((time_t *) 0);
timeNow = localtime (&cur);
}
dateGotten.day = timeNow->tm_mday;
dateGotten.month = timeNow->tm_mon + 1;
dateGotten.year = timeNow->tm_year;
for (cp = dstring; *cp && !isdigit (*cp); cp++)
;
if (!*cp) { /* no numbers. must be dow */
/* now what??? */
errormsg ("days of week not implemented (yet).", 1);
return ((DATE *) NULL);
} else {
/*
* first is day
*/
for (tNum = 0; *cp && isdigit (*cp); cp++)
tNum = tNum * 10 + *cp - '0';
if (! tNum || tNum > 31) {
errormsg ("day out of range", 1);
return ((DATE *) NULL);
}
dateGotten.day = tNum;
while (*cp && !isdigit (*cp))
cp++;
if (!*cp)
return (&dateGotten);
/*
* then comes the month
*/
for (tNum = 0; *cp && isdigit (*cp); cp++)
tNum = tNum * 10 + *cp - '0';
if (!tNum || tNum > 12) {
errormsg ("month out of range", 1);
return ((DATE *) NULL);
}
dateGotten.month = tNum;
while (*cp && !isdigit (*cp))
cp++;
if (!*cp)
return (&dateGotten);
/*
* then the year
*/
for (tNum = 0; *cp && isdigit (*cp); cp++)
tNum = tNum * 10 + *cp - '0';
if (tNum > 1900)
tNum -= 1900;
if (tNum < 70) {
errormsg ("time began in 1970", 1);
return ((DATE *) NULL);
}
dateGotten.year = tNum;
return (&dateGotten);
}
} /*getDate*/
/*
* possible keywords in command
*/
static struct swit keywords[] = {
"and", 0,
#define ANDKEY 0
"or", 0,
#define ORKEY 1
"not", 0,
#define NOTKEY 2
"from", 0,
#define FROMKEY 3
"to", 0,
#define TOKEY 4
"cc", 0,
#define CCKEY 5
"subject", 0,
#define SUBJKEY 6
"after", 0,
#define AFTKEY 7
"before", 0,
#define BEFKEY 8
"search", 0,
#define SRCHKEY 9
"sequence", 0,
#define SEQKEY 10
"do", 0,
#define DOKEY 11
"zero", 0,
#define ZEROKEY 12
"nozero", 0,
#define NZROKEY 13
(char *) NULL, 0,
#define NKEYS 14
};
parseExpr (ac, av)
int ac;
char **av;
{
Reg2 char *cp;
Reg1 int idx;
char err[60];
DATE *dt;
parseTop = opTop = numHeaders = 0;
dateGiven = searchBody = false;
expRoot = NILNODE;
for (idx = 0; idx < ac; idx++) {
cp = av[idx];
if (*cp == '(') {
opStack[opTop++] = leftP;
if (!*++cp)
continue;
} else if (*cp == ')') {
while (opStack[--opTop] != leftP && opTop >= 0)
if (doOp (opStack[opTop]) == 0)
return (0);
continue;
}
if (*cp == '-')
cp++;
switch (smatch (cp, keywords)) {
case AMBIGSW:
(void) snprintf (err, sizeof(err),
"key %s ambiguous", cp);
errormsg (err,1);
return (0);
case SEQKEY:
if (++idx >= ac) {
errormsg ("sequence needs argument", 1);
return (0);
}
seqName = av[idx];
break;
case ZEROKEY:
zeroSeq = true;
break;
case NZROKEY:
zeroSeq = false;
break;
case ANDKEY:
while (opTop-- && (opStack[opTop] == and ||
opStack[opTop] == not))
if (doOp (opStack[opTop]) == 0)
return (0);
opStack[++opTop] = and;
opTop++;
break;
case ORKEY:
/*
* only or, and, not and leftP can be on the operator
* stack and we pop all but left parentheses when
* processing an or
*/
while (opTop-- && opStack[opTop] != leftP)
if (doOp (opStack[opTop]) == 0)
return (0);
opStack[++opTop] = or;
opTop++;
break;
case NOTKEY:
while (opTop-- && opStack[opTop] == not)
if (doOp (opStack[opTop]) == 0)
return (0);
opStack[++opTop] = not;
opTop++;
break;
case FROMKEY:
case TOKEY:
case CCKEY:
case SUBJKEY:
case UNKWNSW: /* assume unknown is a header to search */
if (++idx >= ac) {
(void) snprintf (err, sizeof(err),
"%s needs pattern", cp);
errormsg (err, 1);
return (0);
}
parseStack[parseTop++] = makeNode (header, NILNODE,
NILNODE,
cp,
av[idx]);
headers[numHeaders++] = av[idx-1];
break;
case DOKEY:
if (++idx >= ac) {
errormsg ("do needs a command string", 1);
return (0);
}
Cmd = av[idx];
break;
case SRCHKEY:
searchBody = true;
if (++idx >= ac) {
errormsg ("search needs a pattern", 1);
return (0);
}
parseStack[parseTop++] = makeNode (body, NILNODE,
NILNODE,
av[idx]);
break;
case AFTKEY:
if (++idx >= ac) {
errormsg ("after needs a date", 1);
return (0);
}
if ((dt = getDate (av[idx])) == (DATE *) NULL)
return (0);
parseStack[parseTop++] = makeNode (after, NILNODE,
NILNODE,
dt->month,
dt->day,
dt->year);
dateGiven = true;
break;
case BEFKEY:
if (++idx >= ac) {
errormsg ("before needs a date", 1);
return (0);
}
if ((dt = getDate (av[idx])) == (DATE *) NULL)
return (0);
parseStack[parseTop++] = makeNode (before, NILNODE,
NILNODE,
dt->month,
dt->day,
dt->year);
dateGiven = true;
break;
default:
punt ("smatch returned weird value in parseExpr!");
}
}
while (opTop--) /* flush operator stack */
if (opStack[opTop] == leftP) {
errormsg ("unmatched left parenthesis", 1);
return (0);
} else
if (doOp (opStack[opTop]) == 0)
return (0);
if (parseTop != 1) {
errormsg ("too few operators", 1);
return (0);
}
if ((expRoot = parseStack[0]) == NILNODE)
return (0);
headers[numHeaders] = (char *) NULL;
#ifdef DEBUG
printTree (expRoot);
#endif DEBUG
return (1);
} /* parseExpr */