DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download
Index: T p

⟦25318ce73⟧ TextFile

    Length: 8292 (0x2064)
    Types: TextFile
    Names: »picksbr.c«

Derivation

└─⟦9ae75bfbd⟧ Bits:30007242 EUUGD3: Starter Kit
    └─⟦e7f64e0c0⟧ »EurOpenD3/mail/vmh.tar.Z« 
        └─⟦dcb95597f⟧ 
            └─⟦this⟧ »picksbr.c« 

TextFile

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