v17i088: Ease2.0, a language for sendmail.cf files, Part02/03
Rich Salz
rsalz at uunet.uu.net
Thu Feb 9 07:58:49 AEST 1989
Submitted-by: Arnold D. Robbins <arnold at EMORYU1.ARPA>
Posting-number: Volume 17, Issue 88
Archive-name: ease2/part02
#! /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 2 (of 3)."
# Contents: src/emitcf.c src/lexan.l src/parser.y src/strops.c
# Wrapped by rsalz at papaya.bbn.com on Wed Feb 8 16:55:43 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
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'\" \(7475 characters\)
sed "s/^X//" >'src/emitcf.c' <<'END_OF_FILE'
X/* $Header: emitcf.c,v 2.0 88/06/15 14:40:47 root Exp $ */
X
X/*
X * $Log: emitcf.c,v $
X * Revision 2.0 88/06/15 14:40:47 root
X * Baseline release for net posting. ADR.
X *
X */
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#include "fixstrings.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: if (defstr1 == NULL)
X FatalError ("No option passed in EmitDef()", (char *)NULL);
X 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 if (dstr == (char *)NULL)
X dstr = "";
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 7475 -ne `wc -c <'src/emitcf.c'`; then
echo shar: \"'src/emitcf.c'\" unpacked with wrong size!
fi
chmod +x 'src/emitcf.c'
# end of 'src/emitcf.c'
fi
if test -f 'src/lexan.l' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'src/lexan.l'\"
else
echo shar: Extracting \"'src/lexan.l'\" \(6834 characters\)
sed "s/^X//" >'src/lexan.l' <<'END_OF_FILE'
X%{
X/* $Header: lexan.l,v 2.0 88/06/15 15:11:30 root Exp $ */
X
X/*
X * $Log: lexan.l,v $
X * Revision 2.0 88/06/15 15:11:30 root
X * Baseline release for net posting. ADR.
X *
X */
X
X/*
X * lexan.l -- Lexical Analyzer for EASE.
X *
X * Contains code for lex(1) which generates a lexical
X * analyzer (lex.yy.c) for Ease, a high-level specification
X * format for sendmail configuration files.
X *
X * author -- James S. Schoner, Purdue University Computing Center,
X * West Lafayette, Indiana 47907
X *
X * date -- July 1, 1985
X *
X * Copyright (c) 1985 by Purdue Research Foundation
X *
X * All rights reserved.
X *
X */
X
X#include "fixstrings.h"
X#include "symtab.h"
X#include "lexdefs.h"
X
X#define LEXnewline '\n'
X#define LEXeof '\0'
X#define MaxFN 200 /* maximum file name length */
X
Xextern struct he *LookupSymbol ();
Xextern void ErrorReport ();
X
Xint Lcount; /* line counter */
Xchar FNbuf[MaxFN]; /* file name buffer */
Xshort RMatch = FALSE; /* ruleset match flag */
X
X#undef input
X# define input() (((yytchar=yysptr>yysbuf?U(*--yysptr):Getc(yyin,yyout))==10?(yylineno++,yytchar):yytchar)==EOF?0:yytchar)
X
Xchar
XGetc (yyin, yyout)
X FILE *yyin, *yyout;
X{
X static char linbuf[BUFSIZ], *pc = linbuf;
X char c;
X
X /* initialize buffer: first call only */
X if (*pc == '\0' && pc == linbuf) {
X if (fgets(linbuf, BUFSIZ, yyin)==NULL)
X return EOF;
X fprintf(yyout, "# %s", linbuf); /* echo input as comment */
X }
X c = *pc++;
X if (c == '\n') {
X pc = linbuf;
X if (fgets(linbuf, BUFSIZ, yyin) == NULL)
X *pc = EOF;
X else
X /* echo input as comment */
X fprintf(yyout, "# %s", linbuf);
X }
X return c;
X}
X
X/*
X * Table of keywords. NOTE: This is in sorted order, and
X * must stay that way if anything else is added to it.
X */
Xstatic struct resword {
X char *r_text;
X int r_tokval;
X} reswords[] = {
X { "Argv", MARGV },
X { "Eol", MEOL },
X { "Flags", MFLAGS },
X { "Maxsize", MMAXSIZE },
X { "Path", MPATH },
X { "Recipient", MRECIPIENT },
X { "Sender", MSENDER },
X { "bind", BIND },
X { "canon", CANON },
X { "class", CLASS },
X { "concat", CONCAT },
X { "d_background", DOPTB },
X { "d_interactive", DOPTI },
X { "d_queue", DOPTQ },
X { "define", DEFINE },
X { "f_addrw", CCFLAG },
X { "f_arpa", AAFLAG },
X { "f_date", DDFLAG },
X { "f_dot", XXFLAG },
X { "f_escape", EEFLAG },
X { "f_expensive", EFLAG },
X { "f_ffrom", FFLAG },
X { "f_from", FFFLAG },
X { "f_full", XFLAG },
X { "f_llimit", LLFLAG },
X { "f_locm", LFLAG },
X { "f_mesg", MMFLAG },
X { "f_mult", MFLAG },
X { "f_noreset", SSFLAG },
X { "f_noufrom", NFLAG },
X { "f_retsmtp", PFLAG },
X { "f_return", PPFLAG },
X { "f_rfrom", RFLAG },
X { "f_rport", RRFLAG },
X { "f_smtp", IIFLAG },
X { "f_strip", SFLAG },
X { "f_ufrom", UUFLAG },
X { "f_upperh", HFLAG },
X { "f_upperu", UFLAG },
X { "field", FIELD },
X { "for", FOR },
X { "h_exit", EOPTE },
X { "h_mail", EOPTM },
X { "h_mailz", EOPTZ },
X { "h_print", EOPTP },
X { "h_write", EOPTW },
X { "header", HEADER },
X { "host", HOST },
X { "hostnum", HOSTNUM },
X { "if", IF },
X { "ifset", IFSET },
X { "in", IN },
X { "macro", MACRO },
X { "mailer", MAILER },
X { "map", MAP },
X { "match", MATCH },
X { "next", NEXT },
X { "o_alias", AAOPT },
X { "o_bsub", BBOPT },
X { "o_checkpoint", CCOPT },
X { "o_delivery", DOPT },
X { "o_dmuid", UOPT },
X { "o_dnet", NNOPT },
X { "o_ewait", AOPT },
X { "o_flog", SSOPT },
X { "o_fsmtp", HHOPT },
X { "o_gid", GOPT },
X { "o_handling", EOPT },
X { "o_hformat", OOPT },
X { "o_loadnc", XXOPT },
X { "o_loadq", XOPT },
X { "o_newproc", YYOPT },
X { "o_pmaster", PPOPT },
X { "o_prifactor", ZOPT },
X { "o_qdir", QQOPT },
X { "o_qfactor", QOPT },
X { "o_qtimeout", TTOPT },
X { "o_qwait", COPT },
X { "o_rebuild", DDOPT },
X { "o_recipfactor", YOPT },
X { "o_rsend", MOPT },
X { "o_safe", SOPT },
X { "o_skipd", IOPT },
X { "o_slog", LLOPT },
X { "o_timezone", TOPT },
X { "o_tmode", FFOPT },
X { "o_tread", ROPT },
X { "o_usave", FOPT },
X { "o_validate", NOPT },
X { "o_verbose", VOPT },
X { "o_waitfactor", ZZOPT },
X { "o_wizpass", WWOPT },
X { "options", OPTIONS },
X { "precedence", PRECEDENCE },
X { "readclass", READCLASS },
X { "resolve", RESOLVE },
X { "retry", RETRY },
X { "return", RETURN },
X { "ruleset", RULESET },
X { "trusted", TRUSTED },
X { "user", USER },
X { "while", IF },
X};
X%}
X
X%%
X int INch; /* any input character */
X
X[ \t\f]+ ; /* discard whitepsace */
X[\n] Lcount++;
X^\#[ \t]*[0-9]+[ \t]*\".*\"[ \t]*[\n] {
X sscanf (yytext, "%*c%d%s", &Lcount, FNbuf);
X }
X[A-Za-z][A-Za-z0-9_-]* {
X register int l, h, m, r, c;
X
X l = 0;
X h = (sizeof (reswords) / sizeof(reswords[0])) - 1;
X while (l <= h) {
X m = (h + l) / 2;
X c = yytext[0] - reswords[m].r_text[0];
X r = c ? c : strcmp (yytext, reswords[m].r_text);
X if (r < 0)
X h = m - 1;
X else if (r > 0)
X l = m + 1;
X else
X return reswords[m].r_tokval;
X }
X
X /* not a keyword */
X
X /* store identifiers in symbol table */
X yylval.phe = LookupSymbol (yytext);
X return (IDENT);
X }
X["]((\\\n)|(\\\")|[^"\n])* {
X if ((INch = input()) == LEXnewline) {
X ErrorReport ("End of line in string.\n");
X unput (INch);
X }
X fixquotes ();
X yylval.psb = (char *) malloc (strlen (yytext) + 1);
X strcpy (yylval.psb, yytext + 1);
X return (SCONST);
X }
X[0][0-7]* {
X sscanf (yytext, "%o", &yylval.ival); /* octal constant */
X return (ICONST);
X }
X[-]?[1-9][0-9]* {
X yylval.ival = atoi (yytext);
X return (ICONST);
X }
X"=" return (ASGN);
X"," return (COMMA);
X"{" return (LBRACE);
X"}" return (RBRACE);
X"(" return (LPAREN);
X")" return (RPAREN);
X";" return (SEMI);
X"$" return (DOLLAR);
X":" return (COLON);
X"*" return (STAR);
X"/*" {
X /* eat C comments */
X INch = input ();
X while ((INch != '*') ||
X ((INch = input ()) != '/')) {
X if (INch == LEXnewline)
X Lcount++;
X else
X if (INch == LEXeof) {
X ErrorReport ("End of file in comment.\n");
X break;
X }
X if (INch != '*')
X INch = input ();
X }
X }
X[\\]?. {
X if (RMatch) { /* in rulesets, return literal character */
X yylval.ival = (yytext[0] == '\\') ? yytext[1] : yytext[0];
X return (SEPCHAR);
X } else {
X ErrorReport ("Illegal delimiter character");
X printf (": (octal code) \\%03o\n", *yytext);
X }
X }
X%%
X
X/*
X * fixquotes --- inside a "quoted string", turn `\"' into just `"'
X *
X * this is most useful inside the Argv strings for mailers,
X * particularly when debugging.
X */
X
Xfixquotes ()
X{
X register char *cp1, *cp2;
X
X cp1 = cp2 = yytext;
X while (*cp2) {
X /*
X * if we really wanted to get fancy,
X * at this point we'd handle C escapes,
X * but I don't think it's necessary.
X */
X if (*cp2 == '\\' && cp2[1] == '"')
X cp2++;
X *cp1++ = *cp2++;
X }
X *cp1++ = *cp2++; /* final '\0' */
X}
END_OF_FILE
if test 6834 -ne `wc -c <'src/lexan.l'`; then
echo shar: \"'src/lexan.l'\" unpacked with wrong size!
fi
chmod +x 'src/lexan.l'
# end of 'src/lexan.l'
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'\" \(15988 characters\)
sed "s/^X//" >'src/parser.y' <<'END_OF_FILE'
X%{
X/* $Header: parser.y,v 2.0 88/06/15 14:42:46 root Exp $ */
X
X/*
X * $Log: parser.y,v $
X * Revision 2.0 88/06/15 14:42:46 root
X * Baseline release for net posting. ADR.
X *
X */
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 "fixstrings.h"
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 CANON CLASS CONCAT FOR HEADER HOST HOSTNUM IF IFSET IN
X%token MACRO MAILER MAP MARGV MATCH MEOL MFLAGS MMAXSIZE MPATH
X%token MRECIPIENT MSENDER NEXT OPTIONS PRECEDENCE READCLASS RESOLVE
X%token RETRY RETURN RULESET TRUSTED USER
X
X%token ASGN COLON COMMA DEFINE DOLLAR FIELD LBRACE LPAREN RBRACE
X%token RPAREN SEMI STAR
X
X%token AAOPT AOPT BBOPT CCOPT COPT DDOPT DOPT DOPTB DOPTI DOPTQ EOPT
X%token EOPTE EOPTM EOPTP EOPTW EOPTZ FFOPT FOPT GOPT HHOPT IOPT LLOPT
X%token MOPT NNOPT NOPT OOPT PPOPT QOPT QQOPT ROPT SOPT SSOPT TOPT TTOPT
X%token UOPT VOPT WWOPT XOPT XXOPT YOPT YYOPT ZOPT ZZOPT
X
X%token AAFLAG CCFLAG DDFLAG EEFLAG EFLAG FFFLAG FFLAG HFLAG IIFLAG LFLAG
X%token LLFLAG MFLAG MMFLAG NFLAG PFLAG PPFLAG RFLAG RRFLAG SFLAG SSFLAG
X%token UFLAG UUFLAG XFLAG XXFLAG
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 <psb> catstring canval canvaltok
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 | CCOPT {
X $$ = opt_C;
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 | NOPT {
X $$ = opt_n;
X }
X | PPOPT {
X $$ = opt_P;
X }
X | OOPT {
X $$ = opt_o;
X }
X | QQOPT {
X $$ = opt_Q;
X }
X | QOPT {
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 | YOPT {
X $$ = opt_y;
X }
X | YYOPT {
X $$ = opt_Y;
X }
X | ZOPT {
X $$ = opt_z;
X }
X | ZZOPT {
X $$ = opt_Z;
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 | EEFLAG {
X $$ = flg_E;
X }
X | RRFLAG {
X $$ = flg_R;
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 catstring RPAREN {
X $$ = ListAppend ($2, MacScan ($4), " ");
X free ($2);
X free ($4);
X }
X | LPAREN error RPAREN {
X $$ = NULL;
X }
X ;
X
Xcatstring : SCONST {
X $$ = $1;
X }
X | ifcon {
X $$ = $1;
X }
X | CONCAT LPAREN conval RPAREN {
X $$ = $3;
X }
X | catstring SCONST {
X $$ = ListAppend ($1, $2, (char *) NULL);
X free ($1);
X }
X | catstring ifcon {
X $$ = ListAppend ($1, $2, (char *) NULL);
X free ($2);
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 canval RPAREN {
X $$ = Bracket ($3, TRUE);
X free ($3);
X }
X
Xcanval : canvaltok {
X $$ = $1;
X }
X | canval canvaltok {
X $$ = ListAppend ($1, $2, (char *) NULL);
X free ($1);
X free ($2);
X }
X ;
X
Xcanvaltok : IDENT {
X $$ = ListAppend ($1->psb, (char *) NULL, (char *) NULL);
X RemoveSymbol ($1);
X }
X | SCONST {
X $$ = ListAppend (MacScan ($1), (char *) NULL, (char *) NULL);
X free ($1);
X }
X | reftok {
X $$ = $1;
X }
X | SEPCHAR {
X *Cbuf = $1;
X $$ = ListAppend (Cbuf, (char *) NULL, (char *) NULL);
X }
X | HOSTNUM LPAREN reftok RPAREN {
X $$ = Bracket ($3, FALSE);
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, FALSE),
X (char *) NULL, (char *) NULL);
X }
X | MATCH LPAREN ICONST RPAREN MAP IDENT {
X $$ = ListAppend (MakeField ($3, $6, FALSE, TRUE),
X (char *) NULL, (char *) NULL);
X }
X | MATCH HOST {
X $$ = ListAppend ("$%y",
X (char *) NULL, (char *) NULL);
X }
X | MATCH LPAREN ICONST STAR RPAREN {
X $$ = ListAppend (MakeField ($3, (struct he *) NULL, TRUE, FALSE),
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 15988 -ne `wc -c <'src/parser.y'`; then
echo shar: \"'src/parser.y'\" unpacked with wrong size!
fi
chmod +x 'src/parser.y'
# 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'\" \(12669 characters\)
sed "s/^X//" >'src/strops.c' <<'END_OF_FILE'
X/* $Header: strops.c,v 2.0 88/06/15 14:42:55 root Exp $ */
X
X/*
X * $Log: strops.c,v $
X * Revision 2.0 88/06/15 14:42:55 root
X * Baseline release for net posting. ADR.
X *
X */
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 "fixstrings.h"
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 */
X
X/*
X * FLUKE jps 25-apr-86
X *
X * Add the three new $%x, $%y, and $!x match operators that Sun introduced
X * with release 3.0.
X *
X * BUG (probably) - Sun has assigned a predefined meaning to the $y macro;
X * I imagine we will need to teach ease to avoid this letter.
X */
Xstatic char *Hfield = "$%y"; /* match in /etc/hosts */
Xstatic char *Mfield = "$% "; /* match in specified YP map */
Xstatic char *Nfield = "$! "; /* no match in specified YP map */
X
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_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_n : return ("n");
X case opt_o : return ("o");
X case opt_P : return ("P");
X case e_opt_p: return ("p");
X case opt_Q : return ("Q");
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 opt_y : return ("y");
X case opt_Y : return ("Y");
X case opt_z : return ("z");
X case opt_Z : return ("Z");
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 case flg_E: return ("E");
X case flg_R: return ("R");
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 /*
X * FLUKE jps - 8-may-86 - boost string size by 1 to accomodate space
X * character.
X */
X res = (char *) malloc (strlen (cid->idval.rsn) + strlen (rwaddr) + 4);
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, " "); /* FLUKE jps - work around sendmail bug:
X * whitespace is needed to separate tokens:
X * for example: $>30$D will confuse
X * sendmail, but $>30 $D is OK.
X */
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 * FLUKE jps 25-apr-86 - Modified to add a fourth parameter "isYPmap". This
X * supports Sun's new Yellow Pages match patterns added in release 3.0.
X *
X */
Xchar *
X MakeField (count, class, fstar, isYPmap)
Xregister int count; /* match count (0 or 1) */
Xregister struct he *class; /* optional class type */
Xregister short fstar; /* repetition flag */
Xregister short isYPmap; /* "class" name is really a YP map name */
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 or map */
X if (isYPmap) {
X /* "class" is a misnomer here; it's really
X * a simple macro name for a YP map.
X * FLUKE jps 25-apr-86
X */
X Nfield[2] = MakeMac (class, ID_MACRO);
X return (Nfield);
X } else {
X Cfield[1] = '~';
X Cfield[2] = MakeMac (class, ID_CLASS);
X return (Cfield);
X }
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 or map */
X if (isYPmap) {
X /* "class" is a misnomer here; it's really
X * a simple macro name for a YP map.
X * FLUKE jps 25-apr-86
X */
X Mfield[2] = MakeMac (class, ID_MACRO);
X return (Mfield);
X } else {
X Cfield[1] = '=';
X Cfield[2] = MakeMac (class, ID_CLASS);
X return (Cfield);
X }
X }
X default: ErrorReport ("Invalid field type.\n");
X }
X /*NOTREACHED*/
X}
END_OF_FILE
if test 12669 -ne `wc -c <'src/strops.c'`; then
echo shar: \"'src/strops.c'\" unpacked with wrong size!
fi
chmod +x 'src/strops.c'
# end of 'src/strops.c'
fi
echo shar: End of archive 2 \(of 3\).
cp /dev/null ark2isdone
MISSING=""
for I in 1 2 3 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 3 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
--
Please send comp.sources.unix-related mail to rsalz at uunet.uu.net.
More information about the Comp.sources.unix
mailing list