|
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 */