sources-request@mirror.UUCP (02/11/87)
Submitted by: ksb@j.cc.purdue.edu Mod.sources: Volume 8, Issue 54 Archive-name: ease/Part02 # This is a shell archive. # Remove everything above and including the cut line. # Then run the rest of the file through sh. #----cut here-----cut here-----cut here-----cut here----# #!/bin/sh # shar: Shell Archiver # Run the following text with /bin/sh to create: # src if test ! -d src then mkdir src echo "shar: part 01 is missing?" fi chdir src cat << \SHAR_EOF > emitcf.c /* $Header: /usr/src/local/etc/ease/RCS/emitcf.c,v 1.3 85/11/22 20:14:11 jss Exp $ */ /* * emitcf.c -- This file contains routines associated with the writing * and formatting of a translated sendmail configuration file. * * author -- James S. Schoner, Purdue University Computing Center, * West Lafayette, Indiana 47907 * * date -- July 9, 1985 * * Copyright (c) 1985 by Purdue Research Foundation * * All rights reserved. * */ #include <stdio.h> #include "symtab.h" #define REGLINE 60 /* length of output lines which may be continued */ #define MAXLINE 256 /* liberal maximum line length */ extern short Rformat; /* read-format flag for a class */ extern char *MacScan (); extern char MakeMac (); extern void PrintError (), FatalError (), PrintWarning (), ErrorReport (); void PrintDef (); static char ClassCH; /* printable class macro char */ /* * EmitDef () -- Emit a definition line (Ease block definition) in cf * format. * */ void EmitDef (blockdef, targ, defstr1, defstr2) register enum bdefs blockdef; /* type of definition */ register struct he *targ; /* target to be defined */ char *defstr1, *defstr2; /* one or two definition strings */ { /* * This routine is about as pretty as a translated ease file... * Each type of line (Ease block) is handled case by case below. * */ switch (blockdef) { case def_macro: printf ("D%c", MakeMac (targ, ID_MACRO)); PrintDef (def_macro, MacScan (defstr1)); if (ISMACRO(targ->idd)) PrintWarning ("Redefining macro %s.\n", targ->psb); targ->idd |= ID_MACRO; /* signal definition */ break; case def_class: if (Rformat) /* read format */ printf ("F"); else printf ("C"); printf ("%c", ClassCH = MakeMac (targ, ID_CLASS)); if (Rformat) { /* read format */ printf ("%s\n", defstr1); Rformat = FALSE; } else PrintDef (def_class, defstr1); if (ISCLASS(targ->idd)) PrintWarning ("Redefining class %s.\n", targ->psb); targ->idd |= ID_CLASS; /* signal definition */ break; case def_option: printf ("O%c", *defstr1); PrintDef (def_option, defstr2); break; case def_prec: printf ("P%s=%d\n", targ->psb, targ->idval.prec); break; case def_trusted: printf ("T"); PrintDef (def_trusted, defstr1); break; case def_header: printf ("H"); if (defstr1 != NULL) printf ("?%s?", defstr1); PrintDef (def_header, defstr2); break; case def_mailer: if (ISMAILER(targ->idtype)) { if (ISMAILER(targ->idd)) PrintWarning ("Redefining mailer %s.\n", targ->psb); } else if (ISTYPED(targ->idtype)) { PrintError ("Redeclaration of identifier as mailer:", targ->psb); return; } targ->idd |= ID_MAILER; /* signal definition */ printf ("M%s, ", targ->psb); PrintDef (def_mailer, defstr1); break; case def_ruleset: printf ("R"); PrintDef (def_ruleset, defstr1); break; default: FatalError ("Bad case in EmitDef ()", (char *) NULL); } } /* * PrintContinued () -- Print a line definition (buf) by splitting it over * more than one line. The two definition types * accepted for this method of continuation are class * and trusted user lists, indicated in the argument * btype * */ void PrintContinued (btype, buf) enum bdefs btype; /* block (line) type for definition */ register char *buf; /* buffer containing the definition */ { register char *tmp; /* breakpoint search pointer */ register char tc; /* temporary swap byte */ int buflen; /* length of definition buffer */ buflen = strlen (buf); tmp = buf + REGLINE; while ((*--tmp != ' ') && (tmp != buf)) /* look for suitable break */ /* null */ ; if (tmp == buf) { for (tmp = buf + REGLINE; (*tmp != ' ') && (tmp - buf != buflen); tmp++) /* null */ ; if ((tmp - buf) >= MAXLINE) PrintWarning ("Member name may be too long.\n", (char *) NULL); } tc = *tmp; /* swap break char with null char */ *tmp = '\0'; printf ("%s\n", buf); if ((*tmp = tc) == '\0') return; else tmp++; if (btype == def_class) /* start next line */ printf ("C%c", ClassCH); else printf ("T"); if (strlen (tmp) < REGLINE) /* continue the line */ printf ("%s\n", tmp); else PrintContinued (btype, tmp); } /* * PrintDef () -- Handles special cases (like line continuation) when * printing definitions. * */ void PrintDef (btype, dstr) register enum bdefs btype; /* block type (output line type) */ register char *dstr; /* definition string */ { register char *tmp; for (tmp = dstr; *tmp != '\0'; tmp++) /* search for line continuations */ if ((*tmp == '\\') && (*++tmp == '\n')) if (btype != def_header) { ErrorReport ("Non-header string contains line continuation\n"); return; } else break; /* * Perform case by case handling of definition printing. * */ switch (btype) { case def_header : if (*tmp-- == '\n') { *tmp = '\0'; if (tmp - dstr >= MAXLINE) PrintWarning ("Header may be too long.\n", (char *) NULL); printf ("%s\n\t", dstr); tmp += 2; PrintDef (def_header, tmp); } else { if (strlen (dstr) >= MAXLINE) PrintWarning ("Header may be too long.\n", (char *) NULL); printf ("%s\n", dstr); } break; case def_mailer : if (strlen (dstr) >= MAXLINE) PrintWarning ("Mailer definition may be too long.\n", (char *) NULL); printf ("%s\n", dstr); break; case def_ruleset: if (strlen (dstr) >= MAXLINE) PrintWarning ("Rewriting rule may be too long.\n", (char *) NULL); printf ("%s\n", dstr); break; case def_option : if (strlen (dstr) >= MAXLINE) PrintWarning ("Option assignment may be too long.\n", (char *) NULL); printf ("%s\n", dstr); break; case def_macro : if (strlen (dstr) >= MAXLINE) PrintWarning ("Macro assignment may be too long.\n", (char *) NULL); printf ("%s\n", dstr); break; case def_prec : if (strlen (dstr) >= MAXLINE) PrintWarning ("Precedence relation may be too long.\n", (char *) NULL); printf ("%s\n", dstr); break; case def_trusted: case def_class : if (strlen (dstr) < REGLINE) printf ("%s\n", dstr); else /* use line continuation feature */ PrintContinued (btype, dstr); break; default : FatalError ("Invalid case in PrintDef ()", (char *) NULL); } } /* * StartRuleset () -- Prints a ruleset heading for the ruleset identifier * contained in the argument rsid. * */ void StartRuleset (rsid) register struct he *rsid; /* ruleset identifier */ { if (!ISRULESET(rsid->idtype)) if (ISTYPED(rsid->idtype)) PrintError ("Identifier not of ruleset type:", rsid->psb); else PrintError ("Ruleset identifier not bound to a number:", rsid->psb); else { if (ISRULESET(rsid->idd)) PrintWarning ("Redefining ruleset %s.\n", rsid->psb); rsid->idd |= ID_RULESET; printf ("S%s\n", rsid->idval.rsn); } } SHAR_EOF if test 7227 -ne "`wc -c emitcf.c`" then echo shar: error transmitting emitcf.c '(should have been 7227 characters)' fi cat << \SHAR_EOF > errors.c /* $Header: /usr/src/local/etc/ease/RCS/errors.c,v 1.2 85/10/29 23:40:20 jss Exp $ */ /* * errors.c -- Contains error initialization and reporting routines. * * author -- James S. Schoner, Purdue University Computing Center, * West Lafayette, Indiana 47907 * * date -- July 9, 1985 * * Copyright (c) 1985 by Purdue Research Foundation * * All rights reserved. * */ #include <stdio.h> extern int ErrorCount; /* error count */ extern char FNbuf[]; /* input file name */ extern int Lcount; /* line count */ FILE *DIAGf = {stderr}; /* file for diagnostic output */ /* * ErrorReport () -- Prints source file name (FNbuf), line number (Lcount), * and error message (sbErr) for each invokation. * */ void ErrorReport (sbErr) char *sbErr; { fprintf (DIAGf, "%s, line %d: %s", FNbuf, Lcount, sbErr); ErrorCount++; } /* * FatalError () -- Translator fatal error routine which prints * error message (sbErr) and an argument (sbArg). * */ void FatalError (sbErr, sbArg) char *sbErr, *sbArg; { fprintf (DIAGf, "%s, line %d: Fatal Error In Translator: %s %s\n", FNbuf, Lcount, sbErr, sbArg); exit (1); } /* * yyerror () -- Prints source file name (FNbuf), line number (Lcount), * and error message (sbErr) for each invokation. * */ void yyerror (sbErr) char *sbErr; { fprintf (DIAGf, "%s, line %d: %s\n", FNbuf, Lcount, sbErr); ErrorCount++; } /* * PrintError () -- Prints source file name (FNbuf), line number * (cline), error message (sbErr), and argument * (sbArg) for each invokation. * */ void PrintError (sbErr, sbArg) char *sbErr; char *sbArg; { fprintf (DIAGf, "%s, line %d: %s %s.\n", FNbuf, Lcount, sbErr, sbArg); ErrorCount++; } /* * PrintWarning () -- Prints a warning message with source file * name (FNbuf), line number (Lcount), warning * (sbWarn), and a possible identifier (sbID). * */ void PrintWarning (sbWarn, sbID) char *sbWarn; char *sbID; { fprintf (DIAGf, "%s, line %d: Warning: ", FNbuf, Lcount); if (sbID != NULL) fprintf (DIAGf, sbWarn, sbID); else fprintf (DIAGf, sbWarn); } /* * InitError () -- Initialize line count (Lcount) to one and error count * (ErrorCount) to zero. * */ void InitError () { Lcount = 1; ErrorCount = 0; } SHAR_EOF if test 2340 -ne "`wc -c errors.c`" then echo shar: error transmitting errors.c '(should have been 2340 characters)' fi cat << \SHAR_EOF > idman.c /* $Header: /usr/src/local/etc/ease/RCS/idman.c,v 1.2 85/10/29 23:41:38 jss Exp $ */ /* * idman.c -- Contains routines for manipulating identifiers and their * symbolic associations. * * author -- James S. Schoner, Purdue University Computing Center, * West Lafayette, Indiana 47907 * * date -- July 9, 1985 * * Copyright (c) 1985 by Purdue Research Foundation * * All rights reserved. * */ #include <stdio.h> #include "symtab.h" extern struct he *LookupSymbol (); extern void FatalError (), ErrorReport (), PrintWarning (), PrintError (); short Uchar = 'A'; /* for unique macro names */ /* * UniqMac () -- Assigns and returns a unique one-character macro * name (upper-case) for an Ease macro name. * */ char UniqMac (phe) struct he *phe; /* symbol table entry for Ease macro */ { if ((phe->idval.idc = Uchar++) > 'Z') FatalError ("Too many macro names (26 max)", (char *) NULL); return (phe->idval.idc); } /* * BindID () -- Binds either a ruleset or precedence identifier (phe) to * an integer (vid). The id type distinction is passed in * the parameter idt. * */ void BindID (phe, vid, idt) register struct he *phe; /* symbol table entry for an identifier */ int vid; /* value of the identifier */ unsigned idt; /* identifier type (ruleset or precedence) */ { if (ISTYPED(phe->idtype)) { /* should be undefined */ PrintWarning ("Redeclaration of %s.\n", phe->psb); phe->idtype = ID_UNTYPED; } phe->idtype |= idt; /* make defined */ if (ISRULESET(phe->idtype)) { if (vid > VALRSNMAX) { ErrorReport ("Ruleset number too large.\n"); return; } else if (vid < 0) { ErrorReport ("Ruleset number must be non-negative.\n"); return; } sprintf (phe->idval.rsn, "%d", vid); } else phe->idval.prec = vid; } /* * CheckRS () -- Checks validity of a ruleset identifier (phe) and * returns the ruleset string to which the identifier * is bound. If the ruleset identifier is invalid, the * null string is returned. * */ char * CheckRS (phe) struct he *phe; /* symbol table entry for ruleset identifier */ { if (!ISRULESET(phe->idtype)) { if (!ISTYPED(phe->idtype)) PrintError ("Ruleset identifier not bound to a number:", phe->psb); else PrintError ("Identifier not of ruleset type:", phe->psb); return (NULL); } else return (phe->idval.rsn); } /* * MakeMac () -- Declare a macro name (pmac) as a class and/or macro type * (targtype) and return the unique cf character assigned * to it. * */ char MakeMac (pmac, targtype) register struct he *pmac; /* symbol table entry for macro identifier */ unsigned targtype; /* target declaration type for the macro */ { /* * An Ease macro may be declared as both a singular macro and * a class macro. * */ if (ISMACRO(pmac->idtype) || ISCLASS(pmac->idtype)) { pmac->idtype |= targtype; return (pmac->idval.idc); } if (ISTYPED(pmac->idtype)) { /* not a macro or class id */ PrintError ("Redeclaring or using as macro or class:", pmac->psb); return ('\0'); } pmac->idtype |= targtype; /* previously untyped; declare here */ return (UniqMac (pmac)); } /* * GetField () -- Returns a field type string given a field * identifier (fid). * */ char * GetField (fid) register struct he *fid; /* field identifier */ { if (!ISFIELD(fid->idtype)) { PrintError ("Field type not defined for", fid->psb); return (NULL); } else return (fid->idval.fstring); } /* * CheckMailer () -- Declares a mailer identifier (mid) as type mailer, * checking that the identifier was not previously * declared a different type. * */ char * CheckMailer (mid) register struct he *mid; { if (ISTYPED (mid->idtype) && !ISMAILER (mid->idtype)) { PrintError ("Redeclaration as mailer:", mid->psb); return (NULL); } mid->idtype |= ID_MAILER; return (mid->psb); } /* * AssignType () -- Assigns to each field identifier in fidlist the * type (in string form) fidtype. This is accomplished * by making each field identifier symbol table entry * "point" to the type found in fidtype. * */ void AssignType (fidlist, fidtype) register char *fidlist; /* field identifier list, blank separated */ char *fidtype; /* field identifier type string */ { register struct he *fid; /* pointer to a field identifier */ char *fres; /* field type result string */ register char *srch; /* fidlist search pointer */ char sep; /* fidlist separator character */ fres = (char *) malloc (strlen (fidtype) + 1); if (fres == NULL) FatalError ("System out of string space in AssignType ()", (char *) NULL); strcpy (fres, fidtype); /* make clean copy of string type */ /* * Search for all field identifiers and make the type assignment. * */ srch = fidlist; while (*srch != '\0') { while ((*++srch != ' ') && (*srch != '\0')) /* null */ ; if (*fidlist != '\0') { /* found a field id */ sep = *srch; *srch = '\0'; fid = LookupSymbol (fidlist); /* get symbol table entry */ if (ISFIELD(fid->idtype)) { if (strcmp (fid->idval.fstring, fres)) PrintWarning ("Redefinition of field type for %s.\n", fid->psb); } else if (ISTYPED(fid->idtype)) { PrintError ("Redeclaration of identifier as a field:", fid->psb); return; } fid->idtype |= ID_FIELD; /* type the identifier */ fid->idval.fstring = fres; /* type the field */ if ((*srch = sep) != '\0') fidlist = ++srch; } } } SHAR_EOF if test 5550 -ne "`wc -c idman.c`" then echo shar: error transmitting idman.c '(should have been 5550 characters)' fi cat << \SHAR_EOF > main.c /* $Header: /usr/src/local/etc/ease/RCS/main.c,v 1.2 85/10/29 23:43:38 jss Exp $ */ /* * main.c -- Main procedure for Ease Translator. * * author -- James S. Schoner, Purdue University Computing Center * West Lafayette, Indiana 47907 * * date -- July 9, 1985 * * Copyright (c) 1985 by Purdue Research Foundation * * All rights reserved. * */ #include <stdio.h> extern FILE *DIAGf; /* diagnostic file */ extern void InitError (), InitSymbolTable (), DefScan (), FatalError (), PreLoad (); int ErrorCount; /* translation error count */ void GetArgs (); /* gets arguments to "et" */ /* * main () -- Main procedure for the Ease Translator et. If no files are * given as arguments to et, stdin is translated and written to * stdout. If one file is given, it is translated and written * to stdout. If two files are given, the first is translated * and written to the second. If the first filename is "-", * standard input is assumed. A translation is performed on * valid Ease input only, producing a regular sendmail * configuration file. * */ void main (argc, argv) int argc; /* argument count for "et" */ char *argv[]; /* argument vector for "et" */ { InitError (); /* initialize error conditions */ InitSymbolTable (); /* initialize the symbol table */ PreLoad (); /* preload special identifiers */ GetArgs (argc, argv); /* set up argument files */ (void) yyparse (); /* perform translation */ if (fflush (stdout) == EOF) FatalError ("Cannot flush output stream/file", (char *) NULL); DefScan (); /* warn about undefined idents */ if (ErrorCount) fprintf (DIAGf, "\n\n*** %d error(s) detected.\n", ErrorCount); exit (ErrorCount); } /* * GetArgs () -- Processes arguments to the Ease translator "et". The * arguments are files (margv) which may replace either/both * of the files standard input and standard output. The * following cases are possible: * * -- et f.e f.cf * Translate Ease file f.e and write result * to f.cf. * * -- et f.e * Translate Ease file f.e and write result to * standard output. * * -- et - f.cf * Translate standard input and write result to * f.cf. * * -- et * Translate standard input and write result to * standard output. * * Finally, a message indicating the volatility of the * Ease output is written. * */ void GetArgs (margc, margv) register int margc; /* argument count */ register char *margv[]; /* argument vector */ { switch (margc) { case 1 : break; case 2 : case 3 : if (strcmp (margv[1], "-") && (freopen (margv[1], "r", stdin) == NULL)) FatalError ("Cannot open input stream/file:", margv[1]); if ((margc == 3) && (freopen (margv[2], "w", stdout) == NULL)) FatalError ("Cannot open output file:", margv[2]); break; default: FatalError ("Usage: et [infile [outfile]]", (char *) NULL); break; } printf ("###################################################\n"); printf ("## ##\n"); printf ("## WARNING: THIS FILE IS TO BE MODIFIED BY ##\n"); printf ("## THE EASE TRANSLATOR (ET) ONLY. ##\n"); printf ("## ##\n"); printf ("## ALL OTHER MODIFICATIONS WILL ##\n"); printf ("## DISAPPEAR THE NEXT TIME ET IS RUN. ##\n"); printf ("## ##\n"); printf ("## MAKE MODIFICATIONS TO THE EASE ##\n"); printf ("## SOURCE ONLY. ##\n"); printf ("## ##\n"); printf ("###################################################\n"); } SHAR_EOF if test 3915 -ne "`wc -c main.c`" then echo shar: error transmitting main.c '(should have been 3915 characters)' fi cat << \SHAR_EOF > strops.c /* $Header: /usr/src/local/etc/ease/RCS/strops.c,v 1.2 85/10/29 23:45:39 jss Exp $ */ /* * strops.c -- Contains string operation routines used for constructing * definitions in cf format. * * author -- James S. Schoner, Purdue University Computing Center, * West Lafayette, Indiana 47907 * * date -- July 9, 1985 * * Copyright (c) 1985 by Purdue Research Foundation * * All rights reserved. * */ #include <stdio.h> #include <strings.h> #include "symtab.h" #define MAXTOKPOS 99 /* maximum number of token positions */ #define MAXNAME 1024 /* maximum length of an identifier */ extern struct he *LookupSymbol (); extern char MakeMac (); extern void FatalError (), PrintError (), ErrorReport (); short Rformat = FALSE; /* class read format flag */ static char *Ptok = "$ "; /* positional token structure */ static char *Cfield = "$= "; /* class reference structure */ static char *Ofield = "$-"; /* one token match structure */ static char *Zfield = "$*"; /* zero or more tokens structure */ static char *Pfield = "$+"; /* one or more tokens structure */ static char *Mtest = "$? "; /* conditional macro test string */ /* * ConvOpt () -- Convert an Ease option identifier (optid) by returning a * string representation of the cf format. * */ char * ConvOpt (optid) register enum opts optid; { switch (optid) { case opt_A : return ("A"); case opt_a : return ("a"); case opt_B : return ("B"); case d_opt_b: return ("b"); case opt_c : return ("c"); case opt_D : return ("D"); case opt_d : return ("d"); case opt_e : case e_opt_e: return ("e"); case opt_F : return ("F"); case opt_f : return ("f"); case opt_g : return ("g"); case opt_H : return ("H"); case opt_i : case d_opt_i: return ("i"); case opt_L : return ("L"); case opt_m : case e_opt_m: return ("m"); case opt_N : return ("N"); case opt_o : return ("o"); case e_opt_p: return ("p"); case opt_Q : return ("Q"); case d_opt_q: return ("q"); case opt_r : return ("r"); case opt_S : return ("S"); case opt_s : return ("s"); case opt_T : return ("T"); case opt_t : return ("t"); case opt_u : return ("u"); case opt_v : return ("v"); case opt_W : return ("W"); case e_opt_w: return ("w"); case opt_x : return ("x"); case opt_X : return ("X"); case e_opt_z: return ("z"); default : FatalError ("Bad case in ConvOpt ()", (char *) NULL); } /*NOTREACHED*/ } /* * ConvFlg () -- Convert an Ease mailer flag identifier (flgid) by * string representation of the cf format. * */ char * ConvFlg (flgid) register enum flgs flgid; /* flag identifier */ { switch (flgid) { case flg_f: return ("f"); case flg_r: return ("r"); case flg_S: return ("S"); case flg_n: return ("n"); case flg_l: return ("l"); case flg_s: return ("s"); case flg_m: return ("m"); case flg_F: return ("F"); case flg_D: return ("D"); case flg_M: return ("M"); case flg_x: return ("x"); case flg_P: return ("P"); case flg_u: return ("u"); case flg_h: return ("h"); case flg_A: return ("A"); case flg_U: return ("U"); case flg_e: return ("e"); case flg_X: return ("X"); case flg_L: return ("L"); case flg_p: return ("p"); case flg_I: return ("I"); case flg_C: return ("C"); default : FatalError ("Bad case in ConvFlg ()", (char *) NULL); } /*NOTREACHED*/ } /* * ConvMat () -- Convert an Ease mailer attribute (mat) by returning a * string representation of the cf format. * */ char * ConvMat (mat) register enum mats mat; /* mailer attribute flag */ { switch (mat) { case mat_path : return ("P"); case mat_flags : return ("F"); case mat_sender : return ("S"); case mat_recipient : return ("R"); case mat_argv : return ("A"); case mat_eol : return ("E"); case mat_maxsize : return ("M"); default : FatalError ("Bad case in ConvMat ()", (char *) NULL); } /*NOTREACHED*/ } /* * MacScan () -- Scan a string (pstring) for macros, replacing the Ease * form with the one-character form required by cf format. * */ char * MacScan (pstring) char *pstring; /* macro expandable string */ { register char *searchptr; /* string search pointer */ register char *bptr, *eptr; /* macro begin and end pointers */ char macname [MAXNAME]; /* macro name buffer */ if ((searchptr = pstring) == NULL) return ((char *) NULL); while (*searchptr != '\0') /* find and rewrite all macros */ if (*searchptr == '\\') { searchptr = searchptr + 2; continue; } else if (*searchptr++ == '$' && *searchptr == '{') { if (sscanf (searchptr + 1, "%[^}]", macname) != 1) { PrintError ("Invalid macro format:", searchptr + 1); return ((char *) NULL); } *searchptr++ = MakeMac (LookupSymbol (macname), ID_MACRO); bptr = eptr = searchptr; while (*eptr++ != '}') /* delete old macro chars */ /* empty */ ; do *bptr++ = *eptr; while (*eptr++ != '\0'); } return (pstring); } /* * MakeRStr () -- Construct and return a pointer to a class read string * using the filename fname and read format rformat. * */ char * MakeRStr (fname, rformat) char *fname, /* file name for class read */ *rformat; /* format for class read */ { register char *res; /* resultant read string */ Rformat = TRUE; /* set read format flag */ if (rformat == NULL) return (fname); res = (char *) realloc (fname, strlen (fname) + strlen (rformat) + 2); if (res == NULL) FatalError ("System out of string space in MakeRStr ()", (char *) NULL); res = strcat (res, " "); /* construct read string */ res = strcat (res, rformat); free (rformat); return (res); } /* * ListAppend () -- Append string list2 to string list1 using the * separator sep. A pointer to the newly constructed * string is returned. * */ char * ListAppend (list1, list2, sep) char *list1, /* first string */ *list2, /* second string */ *sep; /* string separator */ { register char *res; /* resultant string */ res = (char *) malloc (strlen (list1) + strlen (list2) + strlen (sep) + 1); if (res == NULL) FatalError ("System out of string space in ListAppend ()", (char *) NULL); res = strcpy (res, list1); if (list1 != NULL) /* use separator if first string not null */ res = strcat (res, sep); res = strcat (res, list2); return (res); } /* * MakeCond () -- Construct a macro conditional string in cf format. The * conditional is based on the macro testmac, with an "if * set" result ifstring, which may contain an optional * "if not set" result string appended to it. * */ char * MakeCond (testmac, ifstring) struct he *testmac; /* macro for conditional testing */ char *ifstring; /* "if macro set" result string(s) */ { register char *res; /* resultant conditional string */ Mtest[2] = MakeMac (testmac, ID_MACRO); /* get one-char macro rep */ res = (char *) malloc (strlen (ifstring) + 6); if (res == NULL) FatalError ("System out of string space in MakeCond ()", (char *) NULL); res = strcpy (res, Mtest); res = strcat (res, ifstring); /* build result part */ res = strcat (res, "$."); /* end of conditional */ free (ifstring); return (res); } /* * MakePosTok () -- Construct and return a positional token string * representation from the parameter num. * */ char * MakePosTok (num) register int num; /* numerical value of positional token */ { if (num > MAXTOKPOS) { ErrorReport ("Positional token too large.\n"); return ((char *) NULL); } else { if (num > 9) { /* two-digit positional token */ Ptok[1] = '0' + (num / 10); Ptok[2] = '0' + (num % 10); Ptok[3] = '\0'; } else { Ptok[1] = '0' + num; Ptok[2] = '\0'; } return (Ptok); } } /* * Bracket () -- Construct and return a cf string form of the * canonicalization of the string identifier passed in * the string parameter psb if dflag is true, else * simply bracket the identifier without dollar signs * for numeric hostname specifications. * */ char * Bracket (psb, dflag) char *psb; /* identifier to be canonicalized */ short dflag; /* dollar flag */ { register char *res; /* resultant cf form */ register short extra; /* extra space needed for malloc */ extra = dflag ? 5 : 3; res = (char *) malloc (strlen (psb) + extra); if (res == NULL) FatalError ("System out of string space in Bracket ()", (char *) NULL); if (dflag) res = strcpy (res, "$["); else res = strcpy (res, "["); res = strcat (res, psb); if (dflag) res = strcat (res, "$"); res = strcat (res, "]"); return (res); } /* * MakeRSCall () -- Construct and return a cf string form of a call * to a ruleset (cid), which would pass to it the * remainder of a rewriting address (rwaddr). * */ char * MakeRSCall (cid, rwaddr) register struct he *cid; /* called ruleset identifier */ register char *rwaddr; /* remainder of rewriting address */ { register char *res; /* resultant cf string for the call */ if (!ISRULESET(cid->idtype)) { /* check validity of ruleset */ PrintError ("Undefined ruleset identifier:", cid->psb); return ((char *) NULL); } res = (char *) malloc (strlen (cid->idval.rsn) + strlen (rwaddr) + 3); if (res == NULL) FatalError ("System out of string space in MakeRSCall ()", (char *) NULL); res = strcpy (res, "$>"); /* construct the call string */ res = strcat (res, cid->idval.rsn); res = strcat (res, rwaddr); return (res); } /* * MakeField () -- Construct and return the cf string format for a * field variable. The match count (count), an optional * class (class), and a match repetition flag (fstar) * are used to determine what type of field string to * construct. * */ char * MakeField (count, class, fstar) register int count; /* match count (0 or 1) */ register struct he *class; /* optional class type */ register short fstar; /* repetition flag */ { switch (count) { case 0: if (class == NULL) /* any token is valid */ if (fstar) return (Zfield); else { ErrorReport ("Invalid field type.\n"); return ((char *) NULL); } else { /* match 0 from class */ Cfield[1] = '~'; Cfield[2] = MakeMac (class, ID_CLASS); return (Cfield); } case 1: if (class == NULL) /* any token is valid */ if (fstar) return (Pfield); else return (Ofield); else { /* match 1 from class */ Cfield[1] = '='; Cfield[2] = MakeMac (class, ID_CLASS); return (Cfield); } default: ErrorReport ("Invalid field type.\n"); } /*NOTREACHED*/ } SHAR_EOF if test 10730 -ne "`wc -c strops.c`" then echo shar: error transmitting strops.c '(should have been 10730 characters)' fi cat << \SHAR_EOF > symtab.c /* $Header: /usr/src/local/etc/ease/RCS/symtab.c,v 1.2 85/10/29 23:46:48 jss Exp $ */ /* * symtab.c -- Contains Ease Translator symbol table routines. * * author -- James S. Schoner, Purdue University Computing Center, * West Lafayette, Indiana 47907 * * date -- July 9, 1985 * * Copyright (c) 1985 by Purdue Research Foundation * * All rights reserved. * */ #include <stdio.h> #include <ctype.h> #include "symtab.h" #define ERRORMAILER "error" /* predefined error mailer name */ extern void FatalError (), PrintWarning (); struct he *LookupSymbol (); struct Defmac { /* predefined macro struct def */ char *macname; char macrep; }; struct he *SymTab[SST]; /* hash table base array */ static struct Defmac MacDefs[] = { /* predefined macros */ {"m_smtp", 'e'}, {"m_oname", 'j'}, {"m_ufrom", 'l'}, {"m_daemon", 'n'}, {"m_addrops", 'o'}, {"m_defaddr", 'q'}, {"m_sitename", 'w'}, {"m_odate", 'a'}, {"m_adate", 'b'}, {"m_hops", 'c'}, {"m_udate", 'd'}, {"m_saddr", 'f'}, {"m_sreladdr", 'g'}, {"m_rhost", 'h'}, {"m_qid", 'i'}, {"m_pid", 'p'}, {"m_protocol", 'r'}, {"m_shostname", 's'}, {"m_ctime", 't'}, {"m_ruser", 'u'}, {"m_version", 'v'}, {"m_sname", 'x'}, {"m_stty", 'y'}, {"m_rhdir", 'z'}, {"sentinel", '\0'} }; /* * DefScan () -- Scan symbol table to find macros, classes, mailers, * and rulesets which have been referenced or declared, but * not defined. A warning is printed for each such * occurence. This routine is usually called at the end * of a successful Ease translation. * */ void DefScan () { register int stindex; /* symbol table hash index */ register struct he *hcsearch; /* hash chain search pointer */ for (stindex = 0; stindex < SST; stindex++) { if ((hcsearch = SymTab[stindex]) != NULL) while (hcsearch != NULL) { if ((ISMACRO(hcsearch->idtype) && isupper(hcsearch->idval.idc)) && !ISMACRO(hcsearch->idd)) PrintWarning ("Macro not defined: %s\n", hcsearch->psb); if (ISCLASS(hcsearch->idtype) && !ISCLASS(hcsearch->idd)) PrintWarning ("Class not defined: %s\n", hcsearch->psb); if (ISMAILER(hcsearch->idtype) && !ISMAILER(hcsearch->idd)) PrintWarning ("Mailer not defined: %s\n", hcsearch->psb); if (ISRULESET(hcsearch->idtype) && !ISRULESET(hcsearch->idd)) PrintWarning ("Ruleset not defined: %s\n", hcsearch->psb); hcsearch = hcsearch->phe; } } } /* * InitSymbolTable () -- Invoked by main () to initialize the symbol table. * */ void InitSymbolTable () { int i; for (i = 0; i < SST; i++) /* initialize base array */ SymTab[i] = NULL; } /* * PreLoad () -- Invoked by main () to preload special macro names * and mailer declarations. * */ void PreLoad () { struct Defmac *macptr; struct he *symptr; /* preload special (lower-case) macros */ for (macptr = &MacDefs[0]; (*macptr).macrep != '\0'; macptr++) { symptr = LookupSymbol ((*macptr).macname); symptr->idtype |= ID_MACRO; symptr->idval.idc = (*macptr).macrep; } /* preload error mailer declaration */ symptr = LookupSymbol (ERRORMAILER); symptr->idtype |= ID_MAILER; symptr->idd |= ID_MAILER; } /* * LookupSymbol () -- Returns a pointer to the hash entry already * existing, or newly created, which corresponds * to string sb. * */ struct he * LookupSymbol (sb) char sb[]; /* string buffer containing identifier */ { struct he *phe; /* hash entry search pointer */ int hc; /* hash code of sb identifier */ phe = SymTab[hc = HashCode (sb)]; while (phe != NULL) /* find hash entry for sb */ if (!strcmp (phe->psb, sb)) return (phe); else phe = phe->phe; /* make new symbol table entry */ if ((phe = (struct he *) malloc (sizeof (struct he))) == NULL) FatalError ("System out of space in LookupSymbol ()", (char *) NULL); if ((phe->psb = (char *) malloc (strlen (sb) + 1)) == NULL) FatalError ("System out of space in LookupSymbol ()", (char *) NULL); strcpy (phe->psb, sb); phe->idval.idc = '\0'; phe->idtype = ID_UNTYPED; phe->idd = ID_UNTYPED; phe->phe = SymTab[hc]; return (SymTab[hc] = phe); } /* * RemoveSymbol () -- Removes the symbol table entry phe from the * symbol table. * */ void RemoveSymbol (phe) struct he *phe; /* pointer to hash entry to be removed from symbol table */ { int hc; /* hash code of entry phe */ struct he *sphe; /* search pointer for entry phe */ if (phe == NULL) return; else { /* search and remove entry phe */ sphe = SymTab[hc = HashCode (phe->psb)]; free (phe->psb); if (sphe == phe) SymTab[hc] = phe->phe; else while (sphe != NULL) if (sphe->phe == phe) { sphe->phe = phe->phe; return; } else sphe = sphe->phe; } } /* * HashCode () -- Returns the hash code of the string in sb by adding * the character values and applying mod by the hash * table size. * */ int HashCode (sb) char sb[]; { int ccSum = 0; /* sum of char values in string sb */ int i; for (i = 0; sb[i]; i++) /* add char codes for sb chars */ ccSum += sb[i]; return (ccSum % SST); /* return sum mod table size */ } SHAR_EOF if test 5288 -ne "`wc -c symtab.c`" then echo shar: error transmitting symtab.c '(should have been 5288 characters)' fi cat << \SHAR_EOF > lexan.l %{ /* $Header: /usr/src/local/etc/ease/RCS/lexan.l,v 1.2 85/10/29 23:42:40 jss Exp $ */ /* * lexan.l -- Lexical Analyzer for EASE. * * Contains code for lex(1) which generates a lexical * analyzer (lex.yy.c) for Ease, a high-level specification * format for sendmail configuration files. * * author -- James S. Schoner, Purdue University Computing Center, * West Lafayette, Indiana 47907 * * date -- July 1, 1985 * * Copyright (c) 1985 by Purdue Research Foundation * * All rights reserved. * */ #include "symtab.h" #include "lexdefs.h" #define LEXnewline '\n' #define LEXeof '\0' #define MaxFN 200 /* maximum file name length */ extern struct he *LookupSymbol (); extern void ErrorReport (); int Lcount; /* line counter */ char FNbuf[MaxFN]; /* file name buffer */ short RMatch = FALSE; /* ruleset match flag */ %} /* lex-specific extensions */ %e 1100 %p 3700 %n 500 %% int INch; /* any input character */ [ \t\f]+ ; /* discard whitepsace */ [\n] Lcount++; ^\#[ \t]*[0-9]+[ \t]*\".*\"[ \t]*$ { sscanf (yytext, "%*c%d%s", &Lcount, FNbuf); INch = input (); } match return (MATCH); in return (IN); bind return (BIND); define return (DEFINE); macro return (MACRO); class return (CLASS); options return (OPTIONS); precedence return (PRECEDENCE); trusted return (TRUSTED); header return (HEADER); ruleset return (RULESET); mailer return (MAILER); host return (HOST); user return (USER); hostnum return (HOSTNUM); if return (IF); retry return (RETRY); next return (NEXT); return return (RETURN); resolve return (RESOLVE); for return (FOR); field return (FIELD); concat return (CONCAT); ifset return (IFSET); canon return (CANON); readclass return (READCLASS); Path return (MPATH); Flags return (MFLAGS); Sender return (MSENDER); Recipient return (MRECIPIENT); Argv return (MARGV); Eol return (MEOL); Maxsize return (MMAXSIZE); o_alias return (AAOPT); o_ewait return (AOPT); o_bsub return (BBOPT); o_qwait return (COPT); o_delivery return (DOPT); d_interactive return (DOPTI); d_background return (DOPTB); d_queue return (DOPTQ); o_rebuild return (DDOPT); o_handling return (EOPT); h_print return (EOPTP); h_exit return (EOPTE); h_mail return (EOPTM); h_write return (EOPTW); h_mailz return (EOPTZ); o_tmode return (FFOPT); o_usave return (FOPT); o_gid return (GOPT); o_fsmtp return (HHOPT); o_skipd return (IOPT); o_slog return (LLOPT); o_rsend return (MOPT); o_dnet return (NNOPT); o_hformat return (OOPT); o_qdir return (QQOPT); o_tread return (ROPT); o_flog return (SSOPT); o_safe return (SOPT); o_qtimeout return (TTOPT); o_timezone return (TOPT); o_dmuid return (UOPT); o_verbose return (VOPT); o_wizpass return (WWOPT); o_loadq return (XOPT); o_loadnc return (XXOPT); f_ffrom return (FFLAG); f_rfrom return (RFLAG); f_noreset return (SSFLAG); f_noufrom return (NFLAG); f_locm return (LFLAG); f_strip return (SFLAG); f_mult return (MFLAG); f_from return (FFFLAG); f_date return (DDFLAG); f_mesg return (MMFLAG); f_full return (XFLAG); f_return return (PPFLAG); f_upperu return (UFLAG); f_upperh return (HFLAG); f_arpa return (AAFLAG); f_ufrom return (UUFLAG); f_expensive return (EFLAG); f_dot return (XXFLAG); f_llimit return (LLFLAG); f_retsmtp return (PFLAG); f_smtp return (IIFLAG); f_addrw return (CCFLAG); [A-Za-z][A-Za-z0-9_-]* { /* store identifiers in symbol table */ yylval.phe = LookupSymbol (yytext); return (IDENT); } ["]((\\\n)|(\\\")|[^"\n])* { if ((INch = input()) == LEXnewline) { ErrorReport ("End of line in string.\n"); unput (INch); } yylval.psb = (char *) malloc (strlen (yytext) + 1); strcpy (yylval.psb, yytext + 1); return (SCONST); } [0][0-7]* { sscanf (yytext, "%o", &yylval.ival); /* octal constant */ return (ICONST); } [-]?[1-9][0-9]* { yylval.ival = atoi (yytext); return (ICONST); } "=" return (ASGN); "," return (COMMA); "{" return (LBRACE); "}" return (RBRACE); "(" return (LPAREN); ")" return (RPAREN); ";" return (SEMI); "$" return (DOLLAR); ":" return (COLON); "*" return (STAR); "/*" { /* eat C comments */ INch = input (); while ((INch != '*') || ((INch = input ()) != '/')) { if (INch == LEXnewline) Lcount++; else if (INch == LEXeof) { ErrorReport ("End of file in comment.\n"); break; } if (INch != '*') INch = input (); } } [\\]?. { if (RMatch) { /* in rulesets, return literal character */ yylval.ival = (yytext[0] == '\\') ? yytext[1] : yytext[0]; return (SEPCHAR); } else { ErrorReport ("Illegal delimiter character"); printf (": (octal code) \\%03o\n", *yytext); } } %% SHAR_EOF if test 5031 -ne "`wc -c lexan.l`" then echo shar: error transmitting lexan.l '(should have been 5031 characters)' fi cat << \SHAR_EOF > symtab.h /* $Header: /usr/src/local/etc/ease/RCS/symtab.h,v 1.2 85/10/29 23:47:47 jss Exp $ */ /* * symtab.h -- Definitions related to the "et" symbol table. * * author -- James S. Schoner, Purdue University Computing Center, * West Lafayette, Indiana 47907 * * date -- July 1, 1985 * * Copyright (c) 1985 by Purdue Research Foundation * * All rights reserved. * */ #define TRUE 1 #define FALSE 0 #define SST 101 /* size of hash table (symbol table) */ #define RSNMAX 5 /* size of a ruleset number character buffer */ #define VALRSNMAX 9999 /* max value of ruleset number */ /* identifier types */ #define ID_UNTYPED 0 #define ID_MACRO 01 #define ID_CLASS 02 #define ID_RULESET 04 #define ID_FIELD 010 #define ID_PREC 020 #define ID_MAILER 040 /* identifier type macros */ #define ISTYPED(x) (x|ID_UNTYPED) #define ISMACRO(x) (x&ID_MACRO) #define ISCLASS(x) (x&ID_CLASS) #define ISRULESET(x) (x&ID_RULESET) #define ISFIELD(x) (x&ID_FIELD) #define ISPREC(x) (x&ID_PREC) #define ISMAILER(x) (x&ID_MAILER) /* block definition types */ enum bdefs {def_macro, def_class, def_option, def_prec, def_trusted, def_header, def_mailer, def_ruleset}; /* option types */ enum opts {opt_A, opt_a, opt_B, opt_c, opt_D, opt_d, opt_e, opt_F, opt_f, opt_g, opt_H, opt_i, opt_L, opt_m, opt_N, opt_o, opt_Q, opt_r, opt_S, opt_s, opt_T, opt_t, opt_u, opt_v, opt_W, opt_x, opt_X, d_opt_i, d_opt_b, d_opt_q, e_opt_p, e_opt_e, e_opt_m, e_opt_w, e_opt_z}; /* flag types */ enum flgs {flg_f, flg_r, flg_S, flg_n, flg_l, flg_s, flg_m, flg_F, flg_D, flg_M, flg_x, flg_P, flg_u, flg_h, flg_A, flg_U, flg_e, flg_X, flg_L, flg_p, flg_I, flg_C}; /* mailer parameters */ enum mats {mat_path, mat_flags, mat_sender, mat_recipient, mat_argv, mat_eol, mat_maxsize}; struct he { /* hash entry structure for symbol table node */ unsigned idtype; /* identifier type */ unsigned idd; /* identifier definition flag */ char *psb; /* identifier string buffer */ union { char rsn[RSNMAX]; /* ruleset number */ int prec; /* precedence value */ char idc; /* one char id representation */ char *fstring; /* field string */ } idval; struct he *phe; /* next hash entry */ }; SHAR_EOF if test 2309 -ne "`wc -c symtab.h`" then echo shar: error transmitting symtab.h '(should have been 2309 characters)' fi cat << \SHAR_EOF > Makefile # Makefile for Ease Translator (et). # # $Header: /usr/src/local/etc/ease/RCS/Makefile,v 1.4 85/10/29 22:57:06 jss Exp $ # # James S. Schoner, Purdue University Computing Center, # West Lafayette, Indiana 47907 # # Copyright (c) 1985 by Purdue Research Foundation # # All rights reserved. # INCLUDE = DEST = /usr/local/etc OWNER = binary GROUP = system MODE = 751 DEFS = CFLAGS = -O ${DEFS} ${INCLUDE} LP = lpr LPFLAGS = -J"Ease Source" HDR = symtab.h SRC = main.c emitcf.c errors.c idman.c strops.c symtab.c LST = Makefile lexan.l parser.y ${HDR} ${SRC} DEP = y.tab.c lex.yy.c ${SRC} OBJ = y.tab.o lex.yy.o main.o emitcf.o errors.o idman.o strops.o symtab.o all: et et: ${OBJ} cc ${CFLAGS} -o et ${OBJ} -ll clean: FRC rm -f et *.o lex.yy.c y.tab.c y.output yacc.acts yacc.tmp \ lexdefs.h y.tab.h errs Makefile.bak depend: ${DEP} ${HDR} maketd -a ${DEP} install: et FRC install -c -m ${MODE} -o ${OWNER} -g ${GROUP} -s et ${DEST} lint: ${DEP} symtab.h FRC lint -hxn ${DEP} print: ${LST} FRC @pr -f ${LST} | ${LP} ${LPFLAGS} spotless: clean FRC rcsclean ${LST} lexdefs.h y.tab.c: parser.y yacc -d parser.y -(cmp -s y.tab.h lexdefs.h || cp y.tab.h lexdefs.h) lex.yy.c: lexan.l lex lexan.l ${HDR} ${SRC} lexan.l parser.y: co $@ FRC: # DO NOT DELETE THIS LINE - maketd DEPENDS ON IT # Dependencies generated at: Thu Oct 17 14:55:17 EST 1985 emitcf.o: symtab.h emitcf.o: /usr/include/stdio.h emitcf.o: emitcf.c errors.o: /usr/include/stdio.h errors.o: errors.c idman.o: symtab.h idman.o: /usr/include/stdio.h idman.o: idman.c lex.yy.o: lexdefs.h lex.yy.o: symtab.h lex.yy.o: /usr/include/stdio.h lex.yy.o: lex.yy.c main.o: /usr/include/stdio.h main.o: main.c strops.o: symtab.h strops.o: /usr/include/stdio.h strops.o: /usr/include/strings.h strops.o: strops.c symtab.o: symtab.h symtab.o: /usr/include/ctype.h symtab.o: /usr/include/stdio.h symtab.o: symtab.c y.tab.o: symtab.h y.tab.o: /usr/include/stdio.h y.tab.o: y.tab.c # DO NOT ADD ANYTHING HERE - it will go away. SHAR_EOF if test 2016 -ne "`wc -c Makefile`" then echo shar: error transmitting Makefile '(should have been 2016 characters)' fi chdir .. # End of shell archive exit 0