|
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: 8292 (0x2064) Types: TextFile Names: »picksbr.c«
└─⟦9ae75bfbd⟧ Bits:30007242 EUUGD3: Starter Kit └─⟦e7f64e0c0⟧ »EurOpenD3/mail/vmh.tar.Z« └─⟦dcb95597f⟧ └─⟦this⟧ »picksbr.c«
#ifndef lint static char rcsid[] = "$Header: picksbr.c,v 1.3 86/03/04 00:06:37 deboor Exp $"; static char notice[] = "This program is in the public domain and is available for unlimited \ as long as this notice is enclosed."; #endif lint /* * $Source: /c/support/deboor/usr/src/old/vmh/RCS/picksbr.c,v $ * $Revision: 1.3 $ $Date: 86/03/04 00:06:37 $ * $Author: deboor $ * * Support routines for the command functions in cmds.pick.c. These routines * actually implement the modified pick function of vmh with help from routines * in parsesbr.c and searchsbr.c * * FUNCTIONS: * doPick the routine which performs the pick function for the * current folder based on the criteria in the tree * rooted at expRoot. seqName should be defined before * doPick is called. * evalMsg evaluates an open message based on the expression * tree rooted at expRoot. Returns TRUE if the message * matches the expression, FALSE otherwise. */ #include "vmh.h" #include "pick.h" /* * 'GLOBAL' variables */ NODE *expRoot; /* root of expression tree */ bool searchBody; /* iff 'search' keyword encountered */ bool dateGiven; char *headers[MAXARGS]; /* all headers we need to find */ bool zeroSeq = true; /* nuke sequence before filling it */ char *def_sequence = (char *) NULL; static INFO *curMsg; /* summary of current message */ /* * evalLine (root, line, where) * recursive routine to do a post-order evaluation of a line based * on the expression tree whose root is 'root'. Called on each line * of a file to evaluate whatever nodes can be evaluated based on the * current line. 'where' is set to indicate where in the message 'line' * comes from: the headers (in_header) the body (in_body) or there really * is no line and this is a final pass through the expression tree (at_eof) */ static evalLine (root, line, where) Reg1 NODE *root; char *line; whereT where; { Reg2 int lval; Reg3 int rval; if (root->n_done == true) return (root->n_value); switch (root->n_which) { case and: case or: lval = evalLine (root->n_left, line, where); rval = evalLine (root->n_right, line, where); if (lval == UNKNOWN || rval == UNKNOWN) { return (UNKNOWN); } else { root->n_done = true; /* * ternary operators are to catch compilers which do * booleans in obnoxious ways (like TRUE == -1) */ if (root->n_which == and) root->n_value = (lval && rval) ? TRUE : FALSE; else root->n_value = (lval || rval) ? TRUE : FALSE; } break; case not: lval = evalLine (root->n_left, line, where); if (lval == UNKNOWN) return (UNKNOWN); else { root->n_done = true; root->n_value = ! lval ? TRUE : FALSE; } break; case body: if (where == at_eof) { root->n_done = true; root->n_value = FALSE; } else if (search_line (line,root->n_key1,strlen (root->n_key1), root->n_key1offs, strlen (line))) { root->n_done = true; root->n_value = TRUE; } break; case header: if (where == in_header && uprf (line, root->n_key1)) { root->n_done = true; if (search_line (line,root->n_key2,strlen(root->n_key2), root->n_key2offs, strlen (line))) { root->n_value = TRUE; } else { root->n_value = FALSE; } } else if (where == at_eof) { root->n_done = true; root->n_value = FALSE; } break; case after: root->n_done = true; if (curMsg->i_year > root->n_year || ( curMsg->i_year == root->n_year && ( curMsg->i_month > root->n_month || ( curMsg->i_month == root->n_month && curMsg->i_day > root->n_day) ) ) ) { root->n_value = TRUE; } else { root->n_value = FALSE; } break; case before: root->n_done = true; if (curMsg->i_year < root->n_year || ( curMsg->i_year == root->n_year && ( curMsg->i_month < root->n_month || ( curMsg->i_month == root->n_month && curMsg->i_day < root->n_day) ) ) ) { root->n_value = TRUE; } else { root->n_value = FALSE; } break; default: punt("unknown leaf type in evalLine"); /*NOTREACHED*/ } return (root->n_value); } /* * cleanTree (root) * a recursive procedure to prepare an expression tree for another * file by marking all nodes as un-evaluated. The traversal is done * in pre-order just for the heck of it. */ cleanTree (root) register NODE *root; { if (root == NILNODE) return; root->n_done = false; root->n_value = UNKNOWN; cleanTree (root->n_left); cleanTree (root->n_right); } /* * freeTree (root) * free the entire subtree under root. */ freeTree (root) register NODE *root; { if (root == NILNODE) return; freeTree (root->n_left); freeTree (root->n_right); Free (root); } /* * evalMsg (fp) * evaluate the message refered to by the open FILE structure fp * according to the criteria in the expression tree with root expRoot. * Returns 1 if the message fits all criteria and 0 if it does not. The * message remains open. * Note that the lines of the body are unfolded just as those of * the header are. This is ok since we are looking only for the existence * of a pattern, not its location, so whether the line is folded or not * makes no difference. */ evalMsg (fp) Reg5 FILE *fp; { Reg2 whereT position; char line[2000]; Reg1 int linelen; Reg3 int result; Reg4 bool first; position = in_header; first = true; while ((linelen = readheader (line, sizeof(line), fp, RH_NL)) != 0) { if (linelen == 1) { /* => end of headers */ position = in_body; /* * don't search the body of the message if we * don't have to. */ if (searchBody == false) break; else /* won't find anything on blank line */ continue; } /* * if this isn't the first line and there was no date given * (want to evaluate before/after criteria on first line * to get them out of the way) and we are in the header portion * but the current line isn't one of the headers we're looking * for, don't bother traversing the tree. */ if (first == false && dateGiven == false && position == in_header && ! printheader (line, headers, P_RETAIN)) { continue; } else { first = false; } /* * if we have evaluated the entire expression one way * or another (rare), then just return the result */ if ((result = evalLine (expRoot, line, position)) != UNKNOWN) { #ifdef DEBUG DeBuG ("returning %s from evalLine\n\tTree:\n", result == TRUE ? "TRUE" : "FALSE" ); printTree (expRoot); #endif DEBUG return (result); } } return (evalLine (expRoot, line, at_eof)); } /* * int * * doPick (criteria) * based on the keywords in the string 'criteria' select messages * and place them in either def_sequence or the sequence specified * in the criteria string. Returns a pointer to the final sequence. * NOTE: seqName should be initialized before calling this routine */ int * doPick (criteria) char *criteria; { Reg1 int idx; Reg3 int highMessage = F->f_msgs.m_hghmsg; FILE *msgf; char msgName[PATHLENGTH]; Reg2 char *cp; int unitSequence[2]; char **argv; Reg4 int argc; int *result; /* initialize */ unitSequence[1] = 0; zeroSeq = true; /* fracture criteria string */ argv = brkstring (criteria, " \t", "\n"); for (argc = 0; argv[argc]; argc++) ; /* if error in parsing, return NULL */ if (parseExpr (argc, argv) == 0) return ((int *) NULL); /* nuke old sequence as required */ if (zeroSeq == true) { unitSequence[0] = 0; set_sequence (seqName, unitSequence, F); } infomsg ("Searching...", 1); (void) sprintf (msgName, "%s/", F->f_name); cp = &msgName[strlen(msgName)]; for (idx = F->f_msgs.m_lowmsg; idx <= highMessage; idx++) { if (Exists (idx, &F->f_msgs)) { if ((curMsg = findinfo (idx, F)) == (INFO *) NULL || curMsg->i_mnum != idx) { continue; } (void) sprintf (cp, "%d", idx); if ((msgf = fopen (msgName, "r")) == (FILE *) NULL) { continue; } if (evalMsg (msgf) == TRUE) { unitSequence[0] = idx; add_to_sequence (seqName, unitSequence, F); } (void) fclose (msgf); cleanTree (expRoot); /* set for next run */ } } freeTree (expRoot); result = readsequence (seqName, F); if (*result) { infomsg ("done", 0); return (result); } else { infomsg ("no messages match specification", 0); return ((int *) NULL); } } /* doPick */