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