rsalz@uunet.uu.net (Rich Salz) (02/09/89)
Submitted-by: Arnold D. Robbins <arnold@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@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@uunet.uu.net.