[comp.sources.unix] v10i053: Ease translator repost, Part03/04

rs@uunet.UU.NET (Rich Salz) (07/10/87)

Submitted-by: Wombat <rsk@j.cc.purdue.edu>
Posting-number: Volume 10, Issue 53
Archive-name: ease/Part03

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 3 (of 4)."
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'config-files/FINIS/base.cpp' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'config-files/FINIS/base.cpp'\"
else
echo shar: Extracting \"'config-files/FINIS/base.cpp'\" \(7566 characters\)
sed "s/^X//" >'config-files/FINIS/base.cpp' <<'END_OF_FILE'
X/***********************************************************
X ***********************************************************
X ****
X ****	General configuration information
X ****
X ****	This information is basically just "boiler-plate"; it must be
X ****	there, but is essentially constant.
X ****
X ****	Information in this file should be independent of location --
X ****	i.e., although there are some policy decisions made, they are
X ****	not specific to Berkeley per se.
X ****
X ****	$Id: base.cpp,v 1.3 85/05/04 17:00:43 acu Exp Locker: acu $
X ****
X ***********************************************************
X ***********************************************************/
X
X
X#include "version.cpp"
X
X
X/************************
X **   Special macros   **
X ************************/
X
Xmacro
X	m_daemon = "MAILER-DAEMON";
X		/* my name */
X
X	m_ufrom = "From ${m_sreladdr}  ${m_udate}";
X		/* UNIX header format */
X
X	m_addrops = ".:%@!^=/[]";
X		/* delimiter (operator) characters */
X
X	m_defaddr = concat ( 
X			ifset (m_sname, "${m_sname} "),
X			"<${m_sreladdr}>"
X	    	    );
X		/* format of a total name */
X
X	m_smtp = "${m_oname} Sendmail ${m_version}/${berkhosts} ready at ${m_adate}";
X		/* SMTP login message */
X
X
X/***************
X **   Class   **
X ***************/
X
Xclass
X	uucphosts = {};
X
X/*****************
X **   Options   **
X *****************/
X
Xoptions
X	o_alias = "/usr/lib/aliases";
X		/* location of alias file */
X
X	o_ewait	= "10";
X		/* wait up to ten minutes for alias file rebuild */
X
X	o_bsub  = ".";
X		/* substitution for space (blank) characters */
X
X	o_delivery = d_background;
X		/* default delivery mode (deliver in background) */
X
X	/***
X	o_qwait = "";
X		/* (don't) connect to "expensive" mailers */
X
X	o_tmode = "0600";
X		/* temporary file mode */
X
X	o_gid = "3";
X		/* default GID (network) */
X
X	o_fsmtp = "/usr/lib/sendmail.hf";
X		/* location of help file */
X
X	o_slog = "9";
X		/* log level */
X
X	/***
X	o_dnet = "ARPA";
X 		/* default network name */
X
X	o_hformat = "";
X 		/* default messages to old style */
X
X	o_qdir = "/usr/spool/mqueue";
X		/* queue directory */
X
X	o_tread = "2h";
X		/* read timeout -- violates protocols */
X
X	o_flog = "/usr/lib/sendmail.st";
X	 	/* status file */
X
X	o_safe = "";
X 		/* queue everything before transmission */
X
X	o_qtimeout = "3d";
X		/* default timeout interval */
X
X	o_timezone = "EST";
X 		/* time zone names (V6 only) */
X
X	o_dmuid = "5";
X 		/* default UID (network) */
X
X	o_wizpass = "XXXXXXXXXXXXX";
X	 	/* wizard's password */
X
X	o_loadq = "999";
X 		/* load average at which we just queue messages */
X
X	o_loadnc = "999";
X 		/* load average at which we refuse connections */
X
X
X/*****************************
X **   Message precedences   **
X *****************************/
X
Xprecedence
X	first-class 	 = 0;
X	special-delivery = 100;
X	junk		 = -100;
X
X
X/***********************
X **   Trusted users   **
X ***********************/
X
Xtrusted
X	{root, daemon, uucp, network};
X	{aat};
X
X
X/***************************
X **   Format of headers   **
X ***************************/
X
Xheader
X	define ("Received:", concat (ifset (m_shostname, "from ${m_shostname} "),
X		"by ${m_oname}; ${m_adate}"));
X	define ("Subject:", "");
X
X	/*** 
X	define ("Posted-Date:", "${m_odate}");
X	 ***/
X
X	for (f_return)
X		define ("Return-Path:", "<${m_sreladdr}>");
X
X	for (f_date) {
X		define ("Resent-Date:", "${m_odate}");
X		define ("Date:", 	"${m_odate}");
X	};
X
X	for (f_from) {
X		define ("Resent-From:", "${m_defaddr}");
X		define ("From:", 	"${m_defaddr}");
X	};
X
X	for (f_full)
X		define ("Full-Name:", "${m_sname}");
X
X	/***
X	for (f_locm)
X		define ("Received-Date:", "${m_adate}");
X	 ***/
X
X	for (f_mesg) {
X		define ("Resent-Message-Id:", "<${m_ctime}.${m_qid}@${m_oname}>");
X		define ("Message-Id:", 	      "<${m_ctime}.${m_qid}@${m_oname}>");
X	};
X
X
X/*************************
X *************************
X **   Rewriting rules   **
X ************************* 
X *************************/
X
X/*************************
X **  Field definitions  **
X *************************/
X
Xfield
X	anypath			: match (0*);
X	path, usr, hostpath,
X	domain			: match (1*);
X	this_host		: match (1) in m_sitename;
X	hostname		: match (1);
X	campushost		: match (1) in campushosts;
X	localdomain		: match (1) in localname;
X	topdomain_id		: match (1) in topdomain;
X	uucphost		: match (1) in uucphosts;
X	phonehost		: match (1) in phonehosts;
X
X/********************************
X *  Sender Field Pre-rewriting  *
X ********************************/
X
Xruleset SEND_PRW {
X
X/***
X	if ( anypath < anypath > anypath )
X		retry ( $1$2$3 );			/* defocus */
X
X}
X
X/***********************************
X *  Recipient Field Pre-rewriting  *
X ***********************************/
X
Xruleset RECP_PRW {
X
X/***
X	if ( anypath < anypath > anypath )
X		retry ( $1$2$3 );			/* defocus */
X
X}
X
X
X/*********************************
X *  Final Output Post-rewriting  *
X *********************************/
X
Xruleset FINAL_RW {
X
X	if ( @ )
X		return ();				/* handle <> error addr */
X
X	/* externalize local domain info */
X
X	/***
X	if ( anypath < anypath "LOCAL" > anypath )
X		retry ( $1 < $2 $localname > $3 );	/* change local info */
X	
X	/***
X	if ( anypath < anypath "LOCAL.ARPA" > anypath )
X		retry ( $1 < $2 $localname > $3 );	/* change local info */
X
X	if ( anypath < path > anypath )
X		retry ( $1$2$3 );			/* defocus */
X		
X	if ( @path: @path: usr )
X		retry ( @$1,@$2:$3);			/* <route-addr> canonical */
X
X	/* UUCP must always be presented in old form */
X
X	if ( usr @ hostname ".UUCP" )
X		retry ( $2!$1);				/* u@h.UUCP => h!u */
X
X	/* delete duplicate local names -- mostly for arpaproto.mc */
X
X	if ( usr % this_host @ this_host )
X		retry ( $1@$3 );			/* u%UCB@UCB => u@UCB */
X
X	if ( usr % this_host @ this_host ".ARPA" )
X		retry ( $1@$3 ".ARPA" );		/* u%UCB@UCB => u@UCB */
X
X}
X
X
X/***************************
X *  Name Canonicalization  *
X ***************************/
X
Xruleset NAME_CANON {
X
X	/* handle "from:<>" special case */
X
X	if ( <>	)
X		return ( @ );				/* turn into magic token */
X
X	/* basic textual canonicalization -- note RFC733 heuristic here */
X
X	if ( anypath < anypath < anypath < path > anypath > anypath > anypath )
X		retry ( $4 );				/* 3-level <> nesting */
X
X	if ( anypath < anypath < path > anypath > anypath )
X		retry ( $3 );				/* 2-level <> nesting */
X
X	if ( anypath < path > anypath )
X		retry ( $2 );				/* basic RFC821/822 parsing */
X
X	if ( usr " at " path )
X		retry ( $1@$2 );			/* "at" -> "@" for RFC 822 */
X
X	/* make sure <@a,@b,@c:user@d> syntax is easy to parse -- undone later */
X
X	if ( @path, usr )
X		retry ( @$1:$2 );			/* change all "," to ":" */
X
X	/* localize and dispose of route-based addresses */
X
X	if ( @path: usr )
X		return ( LOCAL_RW ( <@$1>:$2 ) );	/* handle <route-addr> */
X
X	/* more miscellaneous cleanup */
X
X	if ( path )
X		next ( HOSTDEP_RW ( $1 ) );		/* host dependent cleanup */
X
X	if ( path: anypath; @domain )
X		return ( $1:$2;@$3 );			/* list syntax */
X
X	if ( usr @ domain )
X		next ( $1<@$2> );			/* focus on domain */
X
X	if ( path < path @ domain > )
X		retry ( $1$2<@$3> );			/* move gaze right */
X
X	if ( path < @domain > )
X		return ( LOCAL_RW ( $1<@$2> ) );	/* already canonical */
X
X	/* convert old-style addresses to a domain-based address */
X
X	if ( usr % hostpath )
X		return ( LOCAL_RW ( $1<@$2> ) );	/* user%host */
X
X	if ( hostname:usr )
X		return ( LOCAL_RW ( $2<@$1> ) );	/* host:user */	
X
X	if ( hostname.usr )
X		return ( LOCAL_RW ( $2<@$1> ) );	/* host.user */
X
X	if ( hostname^usr )
X		retry ( $1!$2);				/* convert ^ to ! */
X
X	if ( hostname!usr )
X		return ( LOCAL_RW ( $2<@$1".UUCP"> ) );	   /* resolve uucp names */
X
X	if ( hostname=usr )
X		return ( LOCAL_RW ( $2<@$1".BITNET"> ) );  /* resolve bitnet names */
END_OF_FILE
if test 7566 -ne `wc -c <'config-files/FINIS/base.cpp'`; then
    echo shar: \"'config-files/FINIS/base.cpp'\" unpacked with wrong size!
fi
# end of 'config-files/FINIS/base.cpp'
fi
if test -f 'maketd/abrv.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'maketd/abrv.c'\"
else
echo shar: Extracting \"'maketd/abrv.c'\" \(6197 characters\)
sed "s/^X//" >'maketd/abrv.c' <<'END_OF_FILE'
X/* abbreviation related routines 
X * Written & hacked by Stephen Uitti, PUCC staff, ach@pucc-j, 1985
X * maketd is copyright (C) Purdue University, 1985
X *
X * Permission is hereby given for its free reproduction and
X * modification for non-commercial purposes, provided that this
X * notice and all embedded copyright notices be retained.
X * Commercial organisations may give away copies as part of their
X * systems provided that they do so without charge, and that they
X * acknowledge the source of the software.
X */
X
X#ifdef BSD2_9
X#include <sys/types.h>
X#endif
X#include <stdio.h>
X#include <ctype.h>
Xextern char *malloc();
X
X#include "srtunq.h"
X#include "abrv.h"
X#include "maketd.h"
X
Xstruct srtent abrv;			/* include file abrevs */
Xchar   *abrvtbl[MXABR];			/* translation table strings */
Xint	abrvlen[MXABR];			/* string lengths (for speed) */
X
X/* lngsrt - string length more important than lexicographical compare.
X * return > 0 if b is longer than a.
X * return < 0 if b is shorter than a.
X * if a & b are the same length, return strcmp(a, b), which means
X * that 0 is returned if the strings are THE SAME,
X * if b > a: return > 0
X * if b < a: return < 0
X */
Xint
Xlngsrt(a, b)
Xchar *a, *b;
X{
X    register i;
X
X    if ((i = strlen(b) - strlen(a)) != 0)
X	return i;
X    else
X	return strcmp(a, b);
X}
X
X/* hincl - include header optimizer:
X * Compress multiple leading /'s to just one.
X * Remove leading "./".
X * Doesn't change date, just returns pointer into begining of path.
X */
Xchar *
Xhincl(p)
Xregister char *p;
X{
X    if (*p == '/')		/* compress multiple leading /'s */
X	while (p[1] == '/')	/* to just one */
X	    p++;
X    if (strncmp("./", p, 2) == 0) {
X	p += 2;			/* leading "./" can confuse make */
X	while (*p == '/')	/* don't change ".//a.h" to "/a.h" */
X	    p++;
X    }
X    return p;
X}
X
X/* srchincl - search line for make defines of A-Z
X * Put entries into abrvtbl.
X */
Xvoid
Xsrchincl(p)
Xregister char *p;
X{
X    register char *q, *r;
X    register i;
X
X    if (shortincl && *p != '\0') {
X	while (*p == SPC || *p == '\t')
X	    p++;		/* ignore white space */
X	q = p;			/* what letter */
X	if (isupper(*p)) {	/* A-Z, for now */
X	    p++;
X	    while (*p == SPC || *p == '\t')
X		p++;		/* ignore white space */
X	    if (*p++ == '=') {
X		while (*p == SPC || *p == '\t')
X		    p++;
X		if ((i = strlen(p)) != 0) {
X		    if ((r = malloc((unsigned)(i + 1))) == NULL)
X			err("Out of memory in define search");
X		    if (abrvtbl[*q - 'A'])
X			fprintf(stderr, "%s: warning - %c redefined in %s\n",
X			    prgnm, *q, makename);
X		    abrvtbl[*q - 'A'] = r;
X		    while (*p != '\0' && *p != '#' && *p != '\n')
X			*r++ = *p++;
X		    *r = '\0';	/* null terminate result */
X		}		/* if non-null string */
X	    }			/* if = */
X	}			/* if A-Z */
X    }				/* if shortinclude & string */
X}
X
X/* abrvsetup - set up abrev table, spit out the abrevs.	 Use
X * any A-Z definitions found in Makefile, no duplicates.  Add
X * /usr/include & /usr/include/sys if "all" dependencies are
X * being generated (including /usr/include based files).
X * Try to use I=/usr/include and S=/usr/include/sys, but don't
X * make a stink about it.
X */
Xvoid
Xabrvsetup()
X{
X    register i;				/* temp */
X    register char *p;			/* temp */
X    register slot;			/* slot search point */
X    register j;				/* temp */
X    static abrdone = FALSE;		/* do this only once */
X    register flushi = FALSE;		/* print I=.. */
X    register flushs = FALSE;		/* print S=.. */
X    static char *istring = "I=/usr/include";
X    static char *sstring = "S=/usr/include/sys";
X
X    if (abrdone)
X	return;
X    if (shortincl) {
X	abrdone = TRUE;			/* we've done this */
X	/* add /usr/include/sys, /usr/include if not already there */
X	if (alldep) {
X	    if (abrvtbl['S'-'A'] == NULL) {
X		flushs = TRUE;
X		srchincl(sstring);
X	    } else if ((p = srtin(&abrv, &sstring[2], lngsrt)) != NULL)
X		fprintf(stderr, "%s: %s - %s\n", prgnm, p, &sstring[2]);
X	    if (abrvtbl['I'-'A'] == NULL) {
X		flushi = TRUE;
X		srchincl(istring);
X	    } else if ((p = srtin(&abrv, &istring[2], lngsrt)) != NULL)
X		fprintf(stderr, "%s: %s - %s\n", prgnm, p, &istring[2]);
X	}
X	if (!replace) {			/* no new defines with replace */
X	    srtgti(&abrv);		/* init tree traversal */
X	    slot = 0;			/* start at bgn */
X	    while ((p = srtgets(&abrv)) != NULL) {
X		j = strlen(p);
X		for (i = 0; i < MXABR; i++) { /* look for this definition */
X		    if (abrvtbl[i] == NULL)
X			continue;	/* check non-null entries */
X		    if (*abrvtbl[i] == '\0')
X			continue;	/* check non-null entries */
X		    if (strcmp(p, abrvtbl[i]) == 0)
X			break;		/* exact match found */
X		    else if (strlen(abrvtbl[i]) == j + 1 &&
X			strncmp(p, abrvtbl[i], j) == 0 &&
X			    abrvtbl[i][j] == '/')
X			break;		/* match of "p/" found */
X		}
X		if (i == MXABR) {	/* not found */
X		    for (i = slot; i < MXABR; i++) /* find free slot */
X			if (abrvtbl[i] == NULL)
X			    break;
X		    if (i < MXABR) {	/* free slot found */
X		/* 	if (!usestdout && !replace) */
X			    fprintf(makefd, "%c=%s\n", 'A' + i, p);
X			abrvtbl[i++] = p;
X			slot = i;	/* reduce free slot search time */
X		    }
X		}			/* if not found */
X	    }				/* while */
X	}				/* if !replace */
X	if (flushi && !usestdout && !replace)
X	    fprintf(makefd, "%s\n", istring);
X	if (flushs && !usestdout && !replace)
X	    fprintf(makefd, "%s\n", sstring);
X	for (i = 0; i < MXABR; i++) {	/* set up string lengths */
X	    if (abrvtbl[i] == NULL) {
X		abrvlen[i] = 0;
X	    } else {
X		abrvlen[i] = strlen(abrvtbl[i]);
X		if (verbose)
X		    fprintf(stderr, "%s: %c='%s'\n",
X			prgnm, i + 'A', abrvtbl[i]);
X	    }				/* if */
X	}				/* for */
X    }					/* if */
X}
X
X/* findabr - find an abbreviation in abrvtbl for string p (if any).
X * if multiple abbreations work, use longest.
X * (ie: /usr/include & /usr/include/sys; use /usr/include/sys)
X * if found, return index
X * else: MXABR
X * Do not match abbreviations of less than 3 characters.
X */
Xint
Xfindabr(p)
Xregister char *p;			/* string pointer */
X{
X    register i;				/* for index */
X    register j;				/* found index */
X
X    for (i = 0, j = MXABR; i < MXABR; i++)
X	if (abrvlen[i] > 2)		/* changing "." to $A is evil */
X	    if (strncmp(abrvtbl[i], p, abrvlen[i]) == 0)
X		if (j == MXABR || (abrvlen[i] > abrvlen[j]))
X		    j = i;
X    return j;
X}
END_OF_FILE
if test 6197 -ne `wc -c <'maketd/abrv.c'`; then
    echo shar: \"'maketd/abrv.c'\" unpacked with wrong size!
fi
# end of 'maketd/abrv.c'
fi
if test -f 'src/emitcf.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'src/emitcf.c'\"
else
echo shar: Extracting \"'src/emitcf.c'\" \(7227 characters\)
sed "s/^X//" >'src/emitcf.c' <<'END_OF_FILE'
X/*	$Header: /usr/src/local/etc/ease/RCS/emitcf.c,v 1.3 85/11/22 20:14:11 jss Exp $	*/
X
X/*
X *	emitcf.c  -- This file contains routines associated with the writing
X *		     and formatting of a translated sendmail configuration file.
X *
X *	author	  -- James S. Schoner, Purdue University Computing Center,
X *			  	       West Lafayette, Indiana  47907
X *
X *  	date	  -- July 9, 1985
X *
X *	Copyright (c) 1985 by Purdue Research Foundation
X *
X *	All rights reserved.
X *
X */
X
X#include <stdio.h>
X#include "symtab.h"
X
X#define REGLINE 60	/* length of output lines which may be continued */
X#define MAXLINE 256	/* liberal maximum line length			 */
X
Xextern short Rformat;			/* read-format flag for a class  */
Xextern char *MacScan ();
Xextern char  MakeMac ();
Xextern void  PrintError (),
X	     FatalError (),
X	     PrintWarning (),
X	     ErrorReport ();
X
Xvoid  PrintDef ();
X
Xstatic char ClassCH;			/* printable class macro char    */
X
X/*
X *	EmitDef () -- Emit a definition line (Ease block definition) in cf 
X *		      format.
X *
X */
Xvoid
XEmitDef (blockdef, targ, defstr1, defstr2)
Xregister enum bdefs blockdef;	/* type of definition   	 */
Xregister struct he *targ;	/* target to be defined 	 */
Xchar *defstr1, *defstr2;	/* one or two definition strings */
X{
X	/*
X	 *  This routine is about as pretty as a translated ease file...
X	 *  Each type of line (Ease block) is handled case by case below.
X	 *
X	 */
X	switch (blockdef) {
X		case def_macro:		printf ("D%c", MakeMac (targ, ID_MACRO));
X					PrintDef (def_macro, MacScan (defstr1));
X					if (ISMACRO(targ->idd))
X						PrintWarning ("Redefining macro %s.\n", targ->psb);
X					targ->idd |= ID_MACRO;  /* signal definition */
X					break;
X
X		case def_class:		if (Rformat)	/* read format */
X						printf ("F");
X					else
X						printf ("C");
X					printf ("%c", ClassCH = MakeMac (targ, ID_CLASS));
X					if (Rformat) {	/* read format */
X						printf ("%s\n", defstr1);
X						Rformat = FALSE;
X					} else
X						PrintDef (def_class, defstr1);
X					if (ISCLASS(targ->idd))
X						PrintWarning ("Redefining class %s.\n", targ->psb);
X					targ->idd |= ID_CLASS;  /* signal definition */
X					break;
X
X		case def_option:	printf ("O%c", *defstr1);
X					PrintDef (def_option, defstr2);
X					break;
X
X		case def_prec:		printf ("P%s=%d\n", targ->psb, targ->idval.prec);
X					break;
X
X		case def_trusted:	printf ("T");
X					PrintDef (def_trusted, defstr1);
X					break;
X
X		case def_header:	printf ("H");
X					if (defstr1 != NULL)
X						printf ("?%s?", defstr1);
X					PrintDef (def_header, defstr2);
X					break;
X
X		case def_mailer:	if (ISMAILER(targ->idtype)) {
X						if (ISMAILER(targ->idd))
X							PrintWarning ("Redefining mailer %s.\n", targ->psb);
X					} else if (ISTYPED(targ->idtype)) {
X						PrintError ("Redeclaration of identifier as mailer:", targ->psb);
X						return;
X					}
X					targ->idd |= ID_MAILER;  /* signal definition */
X					printf ("M%s, ", targ->psb);
X					PrintDef (def_mailer, defstr1);
X					break;
X
X		case def_ruleset:	printf ("R");
X					PrintDef (def_ruleset, defstr1);
X					break;
X
X		default:		FatalError ("Bad case in EmitDef ()", (char *) NULL);
X	}
X}
X
X
X/*
X *  	PrintContinued () -- Print a line definition (buf) by splitting it over
X *			     more than one line.  The two definition types 
X *			     accepted for this method of continuation are class
X *			     and trusted user lists, indicated in the argument 
X *			     btype 
X *
X */
Xvoid
XPrintContinued (btype, buf)
Xenum bdefs     btype;	/* block (line) type for definition */
Xregister char *buf;	/* buffer containing the definition */
X{
X	register char *tmp;	/* breakpoint search pointer   */
X	register char  tc;	/* temporary swap byte         */
X	int  buflen;		/* length of definition buffer */	
X
X	buflen = strlen (buf);
X	tmp = buf + REGLINE;
X	while ((*--tmp != ' ') && (tmp != buf))	 /* look for suitable break */
X		/* null */ ;
X	if (tmp == buf) {
X		for (tmp = buf + REGLINE; (*tmp != ' ') && (tmp - buf != buflen); tmp++)
X			/* null */ ;
X		if ((tmp - buf) >= MAXLINE)
X			PrintWarning ("Member name may be too long.\n", (char *) NULL);
X	}
X	tc = *tmp;		/* swap break char with null char */
X	*tmp = '\0';
X	printf ("%s\n", buf);
X	if ((*tmp = tc) == '\0')
X		return;
X	else
X		tmp++;
X	if (btype == def_class)		/* start next line   */
X		printf ("C%c", ClassCH);
X	else
X		printf ("T");
X	if (strlen (tmp) < REGLINE)	/* continue the line */
X		printf ("%s\n", tmp);
X	else
X		PrintContinued (btype, tmp);
X}
X
X
X/*
X *	PrintDef () -- Handles special cases (like line continuation) when 
X *		       printing definitions.
X *
X */
Xvoid
XPrintDef (btype, dstr)
Xregister enum bdefs btype;	/* block type (output line type) */
Xregister char *dstr;		/* definition string		 */
X{
X	register char *tmp;
X
X	for (tmp = dstr; *tmp != '\0'; tmp++) 	/* search for line continuations */
X		if ((*tmp == '\\') && (*++tmp == '\n'))
X			if (btype != def_header) {
X				ErrorReport ("Non-header string contains line continuation\n");
X				return;
X			} else
X				break;
X
X	/*
X	 *  Perform case by case handling of definition printing.
X	 *
X	 */
X	switch (btype) {
X		case def_header :  if (*tmp-- == '\n') {
X					*tmp = '\0';
X					if (tmp - dstr >= MAXLINE)
X						PrintWarning ("Header may be too long.\n", 
X							      (char *) NULL);
X					printf ("%s\n\t", dstr);
X					tmp += 2;
X				        PrintDef (def_header, tmp);
X				   } else {
X					if (strlen (dstr) >= MAXLINE)
X						PrintWarning ("Header may be too long.\n", 
X							      (char *) NULL);
X					printf ("%s\n", dstr);
X				   }
X				   break;
X
X		case def_mailer :  if (strlen (dstr) >= MAXLINE)
X					PrintWarning ("Mailer definition may be too long.\n", 
X						      (char *) NULL);
X				   printf ("%s\n", dstr);
X				   break;
X
X		case def_ruleset:  if (strlen (dstr) >= MAXLINE)
X					PrintWarning ("Rewriting rule may be too long.\n", 
X						      (char *) NULL);
X				   printf ("%s\n", dstr);
X				   break;
X
X		case def_option :  if (strlen (dstr) >= MAXLINE)
X					PrintWarning ("Option assignment may be too long.\n", 
X						      (char *) NULL);
X				   printf ("%s\n", dstr);
X				   break;
X
X		case def_macro  :  if (strlen (dstr) >= MAXLINE)
X					PrintWarning ("Macro assignment may be too long.\n", 
X						      (char *) NULL);
X				   printf ("%s\n", dstr);
X				   break;
X
X		case def_prec   :  if (strlen (dstr) >= MAXLINE)
X					PrintWarning ("Precedence relation may be too long.\n", 
X						      (char *) NULL);
X				   printf ("%s\n", dstr);
X				   break;
X
X		case def_trusted:
X		case def_class  :  if (strlen (dstr) < REGLINE)
X					printf ("%s\n", dstr);
X				   else		/* use line continuation feature */
X				   	PrintContinued (btype, dstr);
X				   break;
X
X		default         :  FatalError ("Invalid case in PrintDef ()", (char *) NULL);
X	}
X}
X
X
X/*
X *	StartRuleset () -- Prints a ruleset heading for the ruleset identifier
X *		           contained in the argument rsid.
X *
X */
Xvoid
XStartRuleset (rsid)
Xregister struct he *rsid;	/* ruleset identifier */
X{
X	if (!ISRULESET(rsid->idtype))
X		if (ISTYPED(rsid->idtype))
X			PrintError ("Identifier not of ruleset type:", rsid->psb);
X		else
X			PrintError ("Ruleset identifier not bound to a number:", rsid->psb);
X	else {
X		if (ISRULESET(rsid->idd))
X			PrintWarning ("Redefining ruleset %s.\n", rsid->psb);
X		rsid->idd |= ID_RULESET;
X		printf ("S%s\n", rsid->idval.rsn);
X	}
X}
END_OF_FILE
if test 7227 -ne `wc -c <'src/emitcf.c'`; then
    echo shar: \"'src/emitcf.c'\" unpacked with wrong size!
fi
# end of 'src/emitcf.c'
fi
if test -f 'src/parser.y' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'src/parser.y'\"
else
echo shar: Extracting \"'src/parser.y'\" \(14482 characters\)
sed "s/^X//" >'src/parser.y' <<'END_OF_FILE'
X%{
X/*	$Header: /usr/src/local/etc/ease/RCS/parser.y,v 1.3 85/12/10 18:02:11 jss Exp $	*/
X
X/*
X *	parser.y -- EASE parser.
X *
X *		    Contains code for yacc(1) which produces a parser (y.tab.c)
X *		    for Ease, a specification format for sendmail configuration
X *		    files.
X *
X *	author   -- James S. Schoner, Purdue University Computing Center,
X *		    		      West Lafayette, Indiana  47907
X *
X *	date     -- July 2, 1985
X *
X *	Copyright (c) 1985 by Purdue Research Foundation
X *
X *	All rights reserved.
X *
X */
X
X#include <stdio.h>
X#include "symtab.h"
X
Xextern void	   BindID ();
Xextern void	   EmitDef ();
Xextern char	  *ListAppend ();
Xextern char 	  *MakeCond ();
Xextern char	  *MakeRStr ();
Xextern char       *ConvOpt ();
Xextern char	  *ConvFlg ();
Xextern char	  *MacScan ();
Xextern char	  *ConvMat ();
Xextern void	   StartRuleset ();
Xextern char	  *MakePosTok ();
Xextern char	  *GetField ();
Xextern char	  *Bracket ();
Xextern char	  *MakeRSCall ();
Xextern char	  *CheckMailer ();
Xextern char	  *CheckRS ();
Xextern char	  *MakeField ();
Xextern char	   MakeMac ();
Xextern void	   AssignType ();
Xextern void	   RemoveSymbol ();
Xextern void	   yyerror ();
X
Xextern short RMatch;		/* ruleset match flag 		      */
X
Xchar *Cbuf = " ";		/* character buffer   		      */
Xchar *Mbuf = "$ ";		/* macro buffer	      		      */
Xchar *Tsb;			/* pointer to temporary string buffer */
Xchar *Flaglist;			/* pointer to header flag list	      */
X
X%}
X
X%union {			/* value stack element type    */
X	int	  ival;		/* integer token 	       */
X	char	  *psb;		/* string token		       */
X	struct he *phe;		/* pointer to hash entry       */
X	enum opts optval;	/* sendmail options	       */
X	enum flgs flgval;	/* mailer flags		       */
X	enum mats mpval;	/* mailer attribute parameters */
X}
X
X%start config
X
X%token 	<phe>	IDENT
X%token  <psb>	SCONST
X%token  <ival>	ICONST SEPCHAR
X%token BIND MACRO CLASS OPTIONS PRECEDENCE TRUSTED HEADER RULESET MAILER
X%token IF RETRY NEXT RETURN RESOLVE CONCAT IFSET FOR CANON READCLASS
X%token MPATH MFLAGS MSENDER MRECIPIENT MARGV MEOL MMAXSIZE
X%token AAOPT AOPT BBOPT COPT DOPT DOPTI DOPTB DOPTQ DDOPT EOPT EOPTP EOPTE 
X%token EOPTM EOPTW EOPTZ FFOPT FOPT GOPT HHOPT IOPT LLOPT MOPT NNOPT OOPT QQOPT
X%token ROPT SSOPT SOPT TTOPT TOPT UOPT VOPT WWOPT XOPT XXOPT
X%token FFLAG RFLAG SSFLAG NFLAG LFLAG SFLAG MFLAG FFFLAG DDFLAG MMFLAG XFLAG
X%token PPFLAG UFLAG HFLAG AAFLAG UUFLAG EFLAG XXFLAG LLFLAG PFLAG IIFLAG CCFLAG
X%token ASGN COMMA LBRACE RBRACE LPAREN RPAREN SEMI DOLLAR MATCH IN HOSTNUM
X%token DEFINE FIELD COLON STAR HOST USER
X
X%type	<psb>		mval strval ifcon conval ifres elseres nameset namelist
X%type	<psb>		doptid eoptid idlist fcond dlist mflags route mdefs
X%type	<psb>		matchaddr matchtok action actionstmt mailerspec mtdef
X%type	<psb>		rwaddr rwtok ftype reftok rword cantok resolution
X%type	<psb>		userspec hword hostid dheader
X%type	<ival>		anychar
X%type	<phe>		cdef
X%type	<optval>	optid
X%type	<flgval>	flagid
X%type	<mpval>		mvar
X
X%left COMMA
X%left LPAREN RPAREN
X%nonassoc SCONST
X
X%%
Xconfig		:	/* empty */
X		|	config blockdef
X		|	error blockdef
X		;
X
Xblockdef	:	BIND bindings
X		|	MACRO macdefs
X		|	CLASS classdefs
X		|	OPTIONS optdefs
X		|	PRECEDENCE precdefs
X		|	TRUSTED tlist
X		|	HEADER hdefs
X		|	MAILER mlist
X		|	RULESET rdef
X		|	FIELD fdefs
X		;
X
Xbindings	:	/* empty */
X		|	bindings IDENT ASGN RULESET ICONST SEMI {
X				BindID ($2, $5, ID_RULESET);
X			}
X		|	error SEMI {
X				yyerrok;
X			}
X		;
X
Xmacdefs		:	/* empty */
X		|	macdefs IDENT ASGN mval SEMI {
X				EmitDef (def_macro, $2, $4, (char *) NULL);
X			}
X		|	error SEMI {
X				yyerrok;
X			}
X		;
X
Xmval		:	strval				%prec COMMA {
X				$$ = $1;
X			}
X		|	CONCAT LPAREN conval RPAREN {
X				$$ = $3;
X			}
X		;
X
Xstrval		:	SCONST {
X				$$ = $1;
X			}
X		|	strval SCONST {
X				$$ = ListAppend ($1, $2, (char *) NULL);
X				free ($1);
X			}
X		;
X
Xconval		:	strval COMMA ifcon {
X				$$ = ListAppend ($1, $3, (char *) NULL);
X				free ($1);
X				free ($3);
X			}
X		|	ifcon COMMA strval {
X				$$ = ListAppend ($1, $3, (char *) NULL);
X				free ($1);
X				free ($3);
X			}
X		|	error {
X				$$ = NULL;
X			}
X		;
X
Xifcon		:	IFSET LPAREN IDENT COMMA ifres RPAREN {
X				$$ = MakeCond ($3, $5);
X			}
X		;
X
Xifres		:	mval elseres {
X				if ($2 != NULL) {
X					$$ = ListAppend ($1, $2, "$|");
X					free ($1);
X					free ($2);
X				} else
X					$$ = $1;
X			}
X		|	error {
X				$$ = NULL;
X			}
X		;
X
Xelseres		:	/* empty */ {
X				$$ = NULL;
X			}
X		|	COMMA mval {
X				$$ = $2;
X			}
X		;
X
Xclassdefs	:	/* empty */ 
X		|	classdefs IDENT ASGN nameset {
X				EmitDef (def_class, $2, $4, (char *) NULL);
X			}
X		|	error
X		;
X
Xnameset		:	LBRACE namelist RBRACE SEMI {
X				$$ = $2;
X			}
X		|	LBRACE RBRACE SEMI {
X				$$ = NULL;
X			}
X		|	LBRACE error RBRACE SEMI {
X				$$ = NULL;
X			}
X		|	READCLASS LPAREN strval RPAREN SEMI {
X				$$ = MakeRStr ($3, (char *) NULL);
X			}
X		|	READCLASS LPAREN strval COMMA strval RPAREN SEMI {
X				$$ = MakeRStr ($3, $5);
X			}
X		|	READCLASS LPAREN error RPAREN SEMI {
X				$$ = NULL;
X			}
X		|	error SEMI {
X				$$ = NULL;
X				yyerrok;
X			}
X		;
X
Xnamelist	:	IDENT {
X				$$ = ListAppend ($1->psb, (char *) NULL, (char *) NULL);
X				RemoveSymbol ($1);
X			}
X		|	strval {
X				$$ = $1;
X			}
X		|	namelist COMMA IDENT {
X				$$ = ListAppend ($1, $3->psb, " ");
X				free ($1);
X				RemoveSymbol ($3);
X			}
X		|	namelist COMMA strval {
X				$$ = ListAppend ($1, $3, " ");
X				free ($1);
X				free ($3);
X			}
X		;
X
Xoptdefs		:	/* empty */
X		|	optdefs optid ASGN strval SEMI {
X				EmitDef (def_option, (struct he *) NULL, ConvOpt ($2), $4);
X			}
X		|	optdefs DOPT ASGN doptid SEMI {
X				EmitDef (def_option, (struct he *) NULL, ConvOpt (opt_d), $4);
X			}
X		|	optdefs EOPT ASGN eoptid SEMI {
X				EmitDef (def_option, (struct he *) NULL, ConvOpt (opt_e), $4);
X			}
X		|	error SEMI {
X				yyerrok;
X			}
X		;
X
Xoptid		:	AAOPT {
X				$$ = opt_A;
X			}
X		|	AOPT {
X				$$ = opt_a;
X			}
X		|	BBOPT {
X				$$ = opt_B;
X			}
X		|	COPT {
X				$$ = opt_c;
X			}
X		|	DDOPT {
X				$$ = opt_D;
X			}
X		|	FFOPT {
X				$$ = opt_F;
X			}
X		|	FOPT {
X				$$ = opt_f;
X			}
X		|	GOPT {
X				$$ = opt_g;
X			}
X		|	HHOPT {
X				$$ = opt_H;
X			}
X		|	IOPT {
X				$$ = opt_i;
X			}
X		|	LLOPT {
X				$$ = opt_L;
X			}
X		|	MOPT {
X				$$ = opt_m;
X			}
X		|	NNOPT {
X				$$ = opt_N;
X			}
X		|	OOPT {
X				$$ = opt_o;
X			}
X		|	QQOPT {
X				$$ = opt_Q;
X			}
X		|	ROPT {
X				$$ = opt_r;
X			}
X		|	SSOPT {
X				$$ = opt_S;
X			}
X		|	SOPT {
X				$$ = opt_s;
X			}
X		|	TTOPT {
X				$$ = opt_T;
X			}
X		|	TOPT {
X				$$ = opt_t;
X			}
X		|	UOPT {
X				$$ = opt_u;
X			}
X		|	VOPT {
X				$$ = opt_v;
X			}
X		|	WWOPT {
X				$$ = opt_W;
X			}
X		|	XOPT {
X				$$ = opt_x;
X			}
X		|	XXOPT {
X				$$ = opt_X;
X			}
X		;
X
Xdoptid		:	DOPTI {
X				$$ = ConvOpt (d_opt_i);
X			}
X		|	DOPTB {
X				$$ = ConvOpt (d_opt_b);
X			}
X		|	DOPTQ {
X				$$ = ConvOpt (d_opt_q);
X			}
X		;
X
Xeoptid		:	EOPTP {
X				$$ = ConvOpt (e_opt_p);
X			}
X		|	EOPTE {
X				$$ = ConvOpt (e_opt_e);
X			}
X		|	EOPTM {
X				$$ = ConvOpt (e_opt_m);
X			}
X		|	EOPTW {
X				$$ = ConvOpt (e_opt_w);
X			}
X		|	EOPTZ {
X				$$ = ConvOpt (e_opt_z);
X			}
X		;
X
Xprecdefs	:	/* empty */
X		|	precdefs IDENT ASGN ICONST SEMI {
X				BindID ($2, $4, ID_PREC);
X				EmitDef (def_prec, $2, (char *) NULL, (char *) NULL);
X			}
X		;
X
Xtlist		:	/* empty */
X		|	tlist LBRACE IDENT idlist RBRACE SEMI {
X				EmitDef (def_trusted, (struct he *) NULL, 
X					 ListAppend ($3->psb, $4, " "), (char *) NULL);
X				free ($4);
X				RemoveSymbol ($3);
X			}
X		|	tlist LBRACE RBRACE SEMI
X		|	error SEMI {
X				yyerrok;
X			}
X		;
X
Xhdefs		:	/* empty */
X		|	hdefs FOR fcond dheader SEMI {
X				EmitDef (def_header, (struct he *) NULL, $3, $4);
X			}
X		|	hdefs FOR fcond LBRACE { Flaglist = $3; } 
X				dheaders RBRACE SEMI
X		|	hdefs DEFINE dlist SEMI {
X				EmitDef (def_header, (struct he *) NULL, (char *) NULL, $3);
X			}
X		|	error SEMI {
X				yyerrok;
X			}
X		;
X
Xfcond		:	LPAREN RPAREN {
X				$$ = NULL;
X			}
X		|	LPAREN mflags RPAREN {
X				$$ = $2;
X			}
X		|	LPAREN error RPAREN {
X				$$ = NULL;
X			}
X		;
X
Xmflags		:	flagid {
X				$$ = ListAppend (ConvFlg ($1), (char *) NULL, (char *) NULL);
X			}
X		|	mflags COMMA flagid {
X				$$ = ListAppend ($1, ConvFlg($3), (char *) NULL);
X				free ($1);
X			}
X		;
X
Xflagid		:	FFLAG {
X				$$ = flg_f;
X			}
X		|	RFLAG {
X				$$ = flg_r;
X			}
X		|	SSFLAG {
X				$$ = flg_S;
X			}
X		|	NFLAG {
X				$$ = flg_n;
X			}
X		|	LFLAG {
X				$$ = flg_l;
X			}
X		|	SFLAG {
X				$$ = flg_s;
X			}
X		|	MFLAG {
X				$$ = flg_m;
X			}
X		|	FFFLAG {
X				$$ = flg_F;
X			}
X		|	DDFLAG {
X				$$ = flg_D;
X			}
X		|	MMFLAG {
X				$$ = flg_M;
X			}
X		|	XFLAG {
X				$$ = flg_x;
X			}
X		|	PPFLAG {
X				$$ = flg_P;
X			}
X		|	UFLAG {
X				$$ = flg_u;
X			}
X		|	HFLAG {
X				$$ = flg_h;
X			}
X		|	AAFLAG {
X				$$ = flg_A;
X			}
X		|	UUFLAG {
X				$$ = flg_U;
X			}
X		|	EFLAG {
X				$$ = flg_e;
X			}
X		|	XXFLAG {
X				$$ = flg_X;
X			}
X		|	LLFLAG {
X				$$ = flg_L;
X			}
X		|	PFLAG {
X				$$ = flg_p;
X			}
X		|	IIFLAG {
X				$$ = flg_I;
X			}
X		|	CCFLAG {
X				$$ = flg_C;
X			}
X		;
X
Xdheader		:	/* empty */ {
X				$$ = NULL;
X			}
X		|	DEFINE dlist {
X				$$ = $2;
X			}
X		|	error {
X				$$ = NULL;
X			}
X		;
X
Xdheaders	:	/* empty */
X		|	dheaders DEFINE dlist SEMI {
X				EmitDef (def_header, (struct he *) NULL, Flaglist, $3);
X			}
X		|	error
X		;
X
Xdlist		:	LPAREN strval COMMA mval RPAREN {
X				$$ = ListAppend ($2, MacScan ($4), " ");
X				free ($2);
X				free ($4);
X			}
X		|	LPAREN error RPAREN {
X				$$ = NULL;
X			}
X		;
X
Xmlist		:	/* empty */
X		|	mlist IDENT LBRACE mdefs RBRACE SEMI {
X				EmitDef (def_mailer, $2, $4, (char *) NULL);
X			}
X		|	mlist IDENT LBRACE RBRACE SEMI {
X				EmitDef (def_mailer, $2, (char *) NULL, (char *) NULL);
X			}
X		|	error SEMI {
X				yyerrok;
X			}
X		;
X
Xmdefs		:	mtdef {
X				$$ = $1;
X			}
X		|	mdefs COMMA mtdef {
X				$$ = ListAppend ($1, $3, ", ");
X				free ($1);
X				free ($3);
X			}
X		;	
X
Xmtdef		:	mvar ASGN mval {
X				$$ = ListAppend (ConvMat ($1), MacScan ($3), "=");
X				free ($3);
X			}
X		|	MFLAGS ASGN LBRACE mflags RBRACE {
X				$$ = ListAppend (ConvMat (mat_flags), $4, "=");
X			}
X		|	MSENDER ASGN IDENT {
X				$$ = ListAppend (ConvMat (mat_sender), CheckRS ($3), "=");
X			}
X		|	MRECIPIENT ASGN IDENT {
X				$$ = ListAppend (ConvMat (mat_recipient), CheckRS ($3), "=");
X			}
X		|	error {
X				$$ = NULL;
X			}
X		;
X
Xmvar		:	MPATH {
X				$$ = mat_path;
X			}
X		|	MARGV {
X				$$ = mat_argv;
X			}
X		|	MEOL {
X				$$ = mat_eol;
X			}
X		|	MMAXSIZE {
X				$$ = mat_maxsize;
X			}
X		;
X
Xrdef		:	/* empty */
X		|	rdef IDENT { StartRuleset ($2); } rulelist
X		;
X
Xrulelist	:	LBRACE ruledefs RBRACE {
X				RMatch = FALSE;
X			}
X		|	error {
X				RMatch = FALSE;
X			}
X		;
X
Xruledefs	:	/* empty */ {
X				RMatch = TRUE;
X			}
X		|	ruledefs IF LPAREN matchaddr RPAREN actionstmt {
X				EmitDef (def_ruleset, (struct he *) NULL, 
X					 ListAppend ($4, $6, "\t"), (char *) NULL);
X			free ($4);
X			free ($6);
X			}
X		|	error SEMI {
X				yyerrok;
X			}
X		;
X
Xmatchaddr	:	/* empty */ {
X				$$ = NULL;
X			}
X		|	matchaddr matchtok {
X				$$ = ListAppend ($1, $2, (char *) NULL);
X				free ($1);
X			}
X		|	error {
X				$$ = NULL;
X			}
X		;
X
Xmatchtok	:	IDENT {
X				$$ = GetField ($1);
X			}
X		|	anychar {
X				*Cbuf = $1;
X				$$ = ListAppend (Cbuf, (char *) NULL, (char *) NULL);
X			}
X		|	mval {
X				$$ = MacScan ($1);
X			}
X		|	DOLLAR IDENT {
X				Mbuf[1] = MakeMac ($2, ID_MACRO);
X				$$ = ListAppend (Mbuf, (char *) NULL, (char *) NULL);
X			}
X		;
X
Xactionstmt	:	action LPAREN rwaddr RPAREN SEMI {
X				$$ = ListAppend ($1, $3, (char *) NULL);
X				free ($3);
X			}
X		|	RESOLVE LPAREN resolution RPAREN SEMI {
X				$$ = $3;
X			}
X		|	error SEMI {
X				$$ = NULL;
X				yyerrok;
X			}
X		;
X
Xaction		:	RETRY {
X				$$ = NULL;
X			}
X		|	NEXT {
X				$$ = "$:";
X			}
X		|	RETURN {
X				$$ = "$@";
X			}
X		;
X
Xrwaddr		:	/* empty */ {
X				$$ = NULL;
X			}
X		|	rwaddr rwtok {
X				$$ = ListAppend ($1, $2, (char *) NULL);
X				free ($1);
X			}
X		|	rwaddr IDENT LPAREN rwaddr RPAREN {
X				$$ = ListAppend ($1, (Tsb = MakeRSCall ($2, $4)), (char *) NULL);
X				free ($1);
X				free ($4);
X				free (Tsb);
X			}
X		|	error {
X				$$ = NULL;
X			}
X		;
X
Xrwtok		:	anychar {
X				*Cbuf = $1;
X				$$ = ListAppend (Cbuf, (char *) NULL, (char *) NULL);
X			}
X		|	mval {
X				$$ = MacScan ($1);
X			}
X		|	cantok {
X				$$ = $1;
X			}
X		|	reftok {
X				$$ = $1;
X			}
X		;
X
Xcantok		:	CANON LPAREN IDENT RPAREN {
X				$$ = Bracket ($3->psb, TRUE);
X				RemoveSymbol ($3);
X			}
X		|	CANON LPAREN SCONST RPAREN {
X				$$ = Bracket (MacScan ($3), TRUE);
X				free ($3);
X			}
X		|	CANON LPAREN reftok RPAREN {
X				$$ = Bracket ($3, TRUE);
X				free ($3);
X			}
X		;
X
Xreftok		:	DOLLAR IDENT {
X				Mbuf[1] = MakeMac ($2, ID_MACRO);
X				$$ = ListAppend (Mbuf, (char *) NULL, (char *) NULL);
X			}
X		|	DOLLAR ICONST {
X				$$ = ListAppend (MakePosTok ($2), (char *) NULL, (char *) NULL);
X			}
X		;
X
Xanychar		:	SEPCHAR {
X				$$ = $1;
X			}
X		|	COLON {
X				$$ = ':';
X			}
X		|	STAR {
X				$$ = '*';
X			}
X		|	SEMI {
X				$$ = ';';
X			}
X		|	LBRACE {
X				$$ = '{';
X			}
X		|	RBRACE {
X				$$ = '}';
X			}
X		|	COMMA {
X				$$ = ',';
X			}
X		|	ASGN {
X				$$ = '=';
X			}
X		;
X
Xresolution	:	mailerspec COMMA route {
X				$$ = ListAppend ($1, $3, (char *) NULL);
X				free ($1);
X				free ($3);
X			}
X		|	error {
X				$$ = NULL;
X			}
X		;
X
Xmailerspec	:	MAILER LPAREN rword RPAREN {
X				$$ = ListAppend ("$#", $3, (char *) NULL);
X			}
X		;
X
Xroute		:	HOST LPAREN hword RPAREN COMMA userspec {
X				$$ = ListAppend (Tsb = ListAppend ("$@", $3, (char *) NULL),
X						 $6, (char *) NULL);
X				free (Tsb);
X				free ($6);
X			}
X		|	userspec {
X				$$ = $1;
X			}
X		;
X
Xhword		:	hostid {
X				$$ = $1;
X			}
X		|	HOSTNUM LPAREN reftok RPAREN {
X				$$ = Bracket ($3, FALSE);
X				free ($3);
X			}
X		;
X
Xhostid		:	/* empty */ {
X				$$ = NULL;
X			}
X		|	hostid IDENT {
X				$$ = ListAppend ($1, $2->psb, (char *) NULL);
X				RemoveSymbol ($2);
X				free ($1);
X			}
X		|	hostid rwtok {
X				$$ = ListAppend ($1, $2, (char *) NULL);
X				free ($1);
X			}
X		;
X
Xuserspec	:	USER LPAREN rwaddr RPAREN {
X				$$ = ListAppend ("$:", $3, (char *) NULL);
X				free ($3);
X			}
X		;
X
Xrword		:	IDENT {
X				$$ = CheckMailer ($1);
X			}
X		|	reftok {
X				$$ = $1;
X			}
X		;
X
Xfdefs		:	/* empty */
X		|	fdefs IDENT idlist COLON ftype SEMI {
X				AssignType (ListAppend ($2->psb, $3, " "), $5);
X				free ($3);
X			}
X		|	error SEMI {
X				yyerrok;
X			}
X		;
X
Xidlist		:	/* empty */ {
X				$$ = NULL;
X			}
X		|	idlist COMMA IDENT {
X				$$ = ListAppend ($1, $3->psb, " ");
X				free ($1);
X			}
X		;
X
Xftype		:	MATCH LPAREN ICONST RPAREN cdef {
X				$$ = ListAppend (MakeField ($3, $5, FALSE), 
X				    		 (char *) NULL, (char *) NULL);
X			}
X		|	MATCH LPAREN ICONST STAR RPAREN {
X				$$ = ListAppend (MakeField ($3, (struct he *) NULL, TRUE), 
X						 (char *) NULL, (char *) NULL);
X			}
X		|	error {
X				$$ = NULL;
X			}
X		;
X
Xcdef		:	/* empty */ {
X				$$ = NULL;
X			}
X		|	IN IDENT {
X				$$ = $2;
X			}
X		;
END_OF_FILE
if test 14482 -ne `wc -c <'src/parser.y'`; then
    echo shar: \"'src/parser.y'\" unpacked with wrong size!
fi
# end of 'src/parser.y'
fi
if test -f 'src/strops.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'src/strops.c'\"
else
echo shar: Extracting \"'src/strops.c'\" \(10730 characters\)
sed "s/^X//" >'src/strops.c' <<'END_OF_FILE'
X/*	$Header: /usr/src/local/etc/ease/RCS/strops.c,v 1.2 85/10/29 23:45:39 jss Exp $	*/
X
X/*
X *	strops.c   -- Contains string operation routines used for constructing
X *		      definitions in cf format.
X *
X *	author	   -- James S. Schoner, Purdue University Computing Center,
X *				        West Lafayette, Indiana  47907
X *
X *	date	   -- July 9, 1985
X *
X *	Copyright (c) 1985 by Purdue Research Foundation
X *
X *	All rights reserved.
X *
X */
X
X#include <stdio.h>
X#include <strings.h>
X#include "symtab.h"
X
X#define MAXTOKPOS   99		/* maximum number of token positions */
X#define MAXNAME	    1024	/* maximum length of an identifier   */
X
Xextern struct he *LookupSymbol ();
Xextern char       MakeMac ();
Xextern void	  FatalError (),
X		  PrintError (),
X		  ErrorReport ();
X
Xshort  Rformat = FALSE;			/* class read format flag	  */
Xstatic char   *Ptok   = "$  ";		/* positional token structure     */
Xstatic char   *Cfield = "$= ";		/* class reference structure	  */
Xstatic char   *Ofield = "$-";		/* one token match structure	  */
Xstatic char   *Zfield = "$*";		/* zero or more tokens structure  */
Xstatic char   *Pfield = "$+";		/* one or more tokens structure	  */
Xstatic char   *Mtest  = "$? ";		/* conditional macro test string  */
X
X
X/*
X *	ConvOpt () -- Convert an Ease option identifier (optid) by returning a
X *		      string representation of the cf format.  
X *
X */
Xchar *
XConvOpt (optid) 
Xregister enum opts optid;
X{
X	switch (optid) {
X		case opt_A  :	return ("A");
X		case opt_a  :	return ("a");
X		case opt_B  :	return ("B");
X		case d_opt_b:	return ("b");
X		case opt_c  :	return ("c");
X		case opt_D  :	return ("D");
X		case opt_d  :	return ("d");
X		case opt_e  :
X		case e_opt_e:	return ("e");
X		case opt_F  :	return ("F");
X		case opt_f  :	return ("f");
X		case opt_g  :	return ("g");
X		case opt_H  :	return ("H");
X		case opt_i  :
X		case d_opt_i:	return ("i");
X		case opt_L  :	return ("L");
X		case opt_m  :
X		case e_opt_m:	return ("m");
X		case opt_N  :	return ("N");
X		case opt_o  :	return ("o");
X		case e_opt_p:	return ("p");
X		case opt_Q  :	return ("Q");
X		case d_opt_q:	return ("q");
X		case opt_r  :	return ("r");
X		case opt_S  :	return ("S");
X		case opt_s  :	return ("s");
X		case opt_T  :	return ("T");
X		case opt_t  :	return ("t");
X		case opt_u  :	return ("u");
X		case opt_v  :	return ("v");
X		case opt_W  :	return ("W");
X		case e_opt_w:	return ("w");
X		case opt_x  :	return ("x");
X		case opt_X  :	return ("X");
X		case e_opt_z:	return ("z");
X		default     :	FatalError ("Bad case in ConvOpt ()", (char *) NULL);
X	}
X	/*NOTREACHED*/
X}
X
X
X/*
X *	ConvFlg () -- Convert an Ease mailer flag identifier (flgid) by 
X *		      string representation of the cf format.  
X *
X */
Xchar *
XConvFlg (flgid)
Xregister enum flgs flgid;	/* flag identifier */
X{
X	switch (flgid) {
X		case flg_f:	return ("f");
X		case flg_r:	return ("r");
X		case flg_S:	return ("S");
X		case flg_n:	return ("n");
X		case flg_l:	return ("l");
X		case flg_s:	return ("s");
X		case flg_m:	return ("m");
X		case flg_F:	return ("F");
X		case flg_D:	return ("D");
X		case flg_M:	return ("M");
X		case flg_x:	return ("x");
X		case flg_P:	return ("P");
X		case flg_u:	return ("u");
X		case flg_h:	return ("h");
X		case flg_A:	return ("A");
X		case flg_U:	return ("U");
X		case flg_e:	return ("e");
X		case flg_X:	return ("X");
X		case flg_L:	return ("L");
X		case flg_p:	return ("p");
X		case flg_I:	return ("I");
X		case flg_C:	return ("C");
X		default   :	FatalError ("Bad case in ConvFlg ()", (char *) NULL);
X	}
X	/*NOTREACHED*/
X}
X
X
X/*
X *	ConvMat () -- Convert an Ease mailer attribute (mat) by returning a
X *		      string representation of the cf format.  
X *
X */
Xchar *
XConvMat (mat)
Xregister enum mats mat;		/* mailer attribute flag */
X{
X	switch (mat) {
X		case mat_path		: return ("P");
X		case mat_flags		: return ("F");
X		case mat_sender		: return ("S");
X		case mat_recipient	: return ("R");
X		case mat_argv		: return ("A");
X		case mat_eol		: return ("E");
X		case mat_maxsize	: return ("M");
X		default			: FatalError ("Bad case in ConvMat ()", (char *) NULL);
X	}
X	/*NOTREACHED*/
X}
X
X
X/*
X *	MacScan () -- Scan a string (pstring) for macros, replacing the Ease
X *		      form with the one-character form required by cf format.
X *
X */
Xchar *
XMacScan (pstring)
Xchar *pstring;		/* macro expandable string */
X{
X	register char *searchptr;	/* string search pointer 	*/
X	register char *bptr, *eptr;	/* macro begin and end pointers */
X	char macname [MAXNAME];		/* macro name buffer		*/
X
X	if ((searchptr = pstring) == NULL)
X		return ((char *) NULL);
X	while (*searchptr != '\0') 	/* find and rewrite all macros  */
X		if (*searchptr == '\\') {
X			searchptr = searchptr + 2;
X			continue;
X		} else if (*searchptr++ == '$' && *searchptr == '{') {
X			if (sscanf (searchptr + 1, "%[^}]", macname) != 1) {
X				PrintError ("Invalid macro format:", searchptr + 1);
X				return ((char *) NULL);
X			} 
X			*searchptr++ = MakeMac (LookupSymbol (macname), ID_MACRO);
X			bptr = eptr = searchptr;
X			while (*eptr++ != '}')	/* delete old macro chars */
X				/* empty */ ;
X			do
X				*bptr++ = *eptr;
X			while (*eptr++ != '\0');
X		}
X	return (pstring);
X}
X
X
X/*
X *	MakeRStr () -- Construct and return a pointer to a class read string 
X *		       using the filename fname and read format rformat.  
X *
X */
Xchar *
XMakeRStr (fname, rformat)
Xchar *fname,			/* file name for class read */
X     *rformat;			/* format for class read    */
X{
X	register char *res;	/* resultant read string    */
X
X	Rformat = TRUE;		/* set read format flag     */
X	if (rformat == NULL)
X		return (fname);
X	res = (char *) realloc (fname, strlen (fname) + strlen (rformat) + 2);
X	if (res == NULL)
X		FatalError ("System out of string space in MakeRStr ()", (char *) NULL);
X	res = strcat (res, " ");	/* construct read string */
X	res = strcat (res, rformat);
X	free (rformat);
X	return (res);
X}
X
X
X/*
X *	ListAppend () -- Append string list2 to string list1 using the 
X *			 separator sep.  A pointer to the newly constructed
X *			 string is returned.
X *
X */
Xchar *
XListAppend (list1, list2, sep)
Xchar *list1,			/* first string 	*/
X     *list2,			/* second string  	*/
X     *sep;			/* string separator	*/
X{
X	register char *res;	/* resultant string	*/
X
X	res = (char *) malloc (strlen (list1) + strlen (list2) + strlen (sep) + 1);
X	if (res == NULL)
X		FatalError ("System out of string space in ListAppend ()", (char *) NULL);
X	res = strcpy (res, list1);
X	if (list1 != NULL)	/* use separator if first string not null */
X		res = strcat (res, sep);
X	res = strcat (res, list2);
X	return (res);
X}
X
X
X/*
X *	MakeCond () -- Construct a macro conditional string in cf format.  The
X *		       conditional is based on the macro testmac, with an "if
X *		       set" result ifstring, which may contain an optional 
X *		       "if not set" result string appended to it.
X *
X */
Xchar *
XMakeCond (testmac, ifstring)
Xstruct he *testmac;		/* macro for conditional testing 	     */
Xchar 	  *ifstring; 		/* "if macro set" result string(s)  	     */
X{
X	register char *res;	/* resultant conditional string		     */
X
X	Mtest[2] = MakeMac (testmac, ID_MACRO);	   /* get one-char macro rep */
X	res = (char *) malloc (strlen (ifstring) + 6);
X	if (res == NULL)
X		FatalError ("System out of string space in MakeCond ()", (char *) NULL);
X	res = strcpy (res, Mtest);
X	res = strcat (res, ifstring);		/* build result part	  */
X	res = strcat (res, "$.");		/* end of conditional     */
X	free (ifstring);
X	return (res);
X}
X
X
X/*
X *	MakePosTok () -- Construct and return a positional token string 
X *			 representation from the parameter num.
X *
X */
Xchar *
XMakePosTok (num)
Xregister int num;	        /* numerical value of positional token */
X{
X	if (num > MAXTOKPOS) {
X		ErrorReport ("Positional token too large.\n");
X		return ((char *) NULL);
X	} else {
X		if (num > 9) {	/* two-digit positional token */
X			Ptok[1] = '0' + (num / 10);
X			Ptok[2] = '0' + (num % 10);
X			Ptok[3] = '\0';
X		} else {
X			Ptok[1] = '0' + num;
X			Ptok[2] = '\0';
X		}
X	return (Ptok);
X	}
X}
X
X
X/*
X *	Bracket () -- Construct and return a cf string form of the 
X *		      canonicalization of the string identifier passed in
X *		      the string parameter psb if dflag is true, else
X *		      simply bracket the identifier without dollar signs
X *		      for numeric hostname specifications.
X *
X */
Xchar *
XBracket (psb, dflag)
Xchar *psb;			/* identifier to be canonicalized */
Xshort dflag;			/* dollar flag 			  */
X{
X	register char *res;	/* resultant cf form 		  */
X	register short extra;	/* extra space needed for malloc  */
X	
X	extra = dflag ? 5 : 3;
X	res = (char *) malloc (strlen (psb) + extra);
X	if (res == NULL)
X		FatalError ("System out of string space in Bracket ()", (char *) NULL);
X	if (dflag)
X		res = strcpy (res, "$[");
X	else
X		res = strcpy (res, "[");
X	res = strcat (res, psb);
X	if (dflag)
X		res = strcat (res, "$");
X	res = strcat (res, "]");
X	return (res);
X}
X
X
X/*
X *	MakeRSCall () -- Construct and return a cf string form of a call
X *			 to a ruleset (cid), which would pass to it the
X *			 remainder of a rewriting address (rwaddr).
X *
X */
Xchar *
XMakeRSCall (cid, rwaddr)
Xregister struct he *cid;	/* called ruleset identifier	     */
Xregister char *rwaddr;		/* remainder of rewriting address    */
X{
X	register char *res;	/* resultant cf string for the call  */
X	
X	if (!ISRULESET(cid->idtype)) {	/* check validity of ruleset */
X		PrintError ("Undefined ruleset identifier:", cid->psb);
X		return ((char *) NULL);
X	}
X	res = (char *) malloc (strlen (cid->idval.rsn) + strlen (rwaddr) + 3);
X	if (res == NULL)
X		FatalError ("System out of string space in MakeRSCall ()", (char *) NULL);
X	res = strcpy (res, "$>");	/* construct the call string */
X	res = strcat (res, cid->idval.rsn);
X	res = strcat (res, rwaddr);
X	return (res);
X}
X
X
X/*
X *	MakeField () -- Construct and return the cf string format for a
X *			field variable.  The match count (count), an optional
X *			class (class), and a match repetition flag (fstar)
X *			are used to determine what type of field string to
X *			construct.
X *
X */
Xchar *
XMakeField (count, class, fstar)
Xregister int count;		/* match count (0 or 1) */
Xregister struct he *class;	/* optional class type  */
Xregister short fstar;		/* repetition flag	*/
X{
X	switch (count) {
X		case 0:	  if (class == NULL)	/* any token is valid */
X				if (fstar)
X					return (Zfield);
X				else {
X					ErrorReport ("Invalid field type.\n");
X					return ((char *) NULL);
X				}
X			  else {		/* match 0 from class */
X				Cfield[1] = '~';
X				Cfield[2] = MakeMac (class, ID_CLASS);
X				return (Cfield);
X			  }
X		case 1:	  if (class == NULL)	/* any token is valid */
X				if (fstar)
X					return (Pfield);
X				else
X					return (Ofield);
X			  else {		/* match 1 from class */
X				Cfield[1] = '=';
X				Cfield[2] = MakeMac (class, ID_CLASS);
X				return (Cfield);
X			  }
X		default:  ErrorReport ("Invalid field type.\n");
X	}
X	/*NOTREACHED*/
X}
END_OF_FILE
if test 10730 -ne `wc -c <'src/strops.c'`; then
    echo shar: \"'src/strops.c'\" unpacked with wrong size!
fi
# end of 'src/strops.c'
fi
echo shar: End of archive 3 \(of 4\).
cp /dev/null ark3isdone
MISSING=""
for I in 1 2 3 4 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 4 archives.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0

-- 

Rich $alz			"Anger is an energy"
Cronus Project, BBN Labs	rsalz@bbn.com
Moderator, comp.sources.unix	sources@uunet.upoHAh