|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T p
Length: 7970 (0x1f22)
Types: TextFile
Names: »parse.y«
└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki
└─⟦this⟧ »EUUGD11/euug-87hel/sec8/pathalias/parse.y«
%{
/* pathalias -- by steve bellovin, as told to peter honeyman */
#ifndef lint
static char *sccsid = "@(#)parse.y 8.5 (down!honey) 86/07/18";
#endif lint
#include "def.h"
/* exports */
extern void yyerror();
/* imports */
extern node *addnode(), *addprivate();
extern char *Cfile, *ProgName, *Netchars, **Ifiles;
extern int Lineno, Scan;
extern void fixprivate(), alias(), addgateway();
extern link *addlink();
/* privates */
STATIC void fixnet();
STATIC int yylex(), yywrap(), getword();
STATIC Cost isacost();
static int Scanstate = NEWLINE; /* scanner (yylex) state */
%}
%union {
node *y_node;
Cost y_cost;
char y_net;
char *y_name;
struct {
node *ys_node;
Cost ys_cost;
char ys_net;
char ys_dir;
} y_s;
}
%type <y_s> site
%type <y_node> links aliases plist network nlist host Psite Site
%type <y_cost> cost cexpr
%token <y_name> SITE HOST
%token <y_cost> COST
%token <y_net> NET
%token NL PRIVATE
%left '+' '-'
%left '*' '/'
%%
map : /* empty */
| map NL
| map links NL
| map aliases NL
| map network NL
| map private NL
| error NL
;
links : host site cost {
if (GATEWAYED($2.ys_node))
addgateway($1, $2.ys_node, $3, $2.ys_net, $2.ys_dir);
else
(void) addlink($1, $2.ys_node, $3, $2.ys_net, $2.ys_dir);
}
| links ',' site cost {
if (GATEWAYED($3.ys_node))
addgateway($1, $3.ys_node, $4, $3.ys_net, $3.ys_dir);
else
(void) addlink($1, $3.ys_node, $4, $3.ys_net, $3.ys_dir);
}
| links ',' /* permit this benign error */
;
aliases : host '=' Site {alias($1, $3);}
| aliases ',' Site {alias($1, $3);}
| aliases ',' /* permit this benign error */
;
network : host '=' '{' nlist '}' cost {fixnet($1, $4, $6, DEFNET, DEFDIR);}
| host '=' NET '{' nlist '}' cost {fixnet($1, $5, $7, $3, LRIGHT);}
| host '=' '{' nlist '}' NET cost {fixnet($1, $4, $7, $6, LLEFT);}
;
private : PRIVATE '{' plist '}' ;
host : HOST {$$ = addnode($1);}
| PRIVATE {$$ = addnode("private");}
;
Site : SITE {$$ = addnode($1);} ;
site : Site {
$$.ys_node = $1;
$$.ys_net = DEFNET;
$$.ys_dir = DEFDIR;
}
| NET Site {
$$.ys_node = $2;
$$.ys_net = $1;
$$.ys_dir = LRIGHT;
}
| Site NET {
$$.ys_node = $1;
$$.ys_net = $2;
$$.ys_dir = LLEFT;
}
;
Psite : SITE {$$ = addprivate($1);} ;
plist : Psite {$1->n_flag |= ISPRIVATE;}
| plist ',' Psite {$3->n_flag |= ISPRIVATE;}
| plist ',' /* permit this benign error */
;
nlist : Site
| nlist ',' Site {
if ($3->n_net == 0) {
$3->n_net = $1;
$$ = $3;
}
}
| nlist ',' /* permit this benign error */
;
cost : {$$ = DEFCOST; /* empty -- cost is always optional */}
| '(' {Scanstate = COSTING;} cexpr {Scanstate = OTHER;} ')'
{$$ = $3;}
;
cexpr : COST
| '(' cexpr ')' {$$ = $2;}
| cexpr '+' cexpr {$$ = $1 + $3;}
| cexpr '-' cexpr {$$ = $1 - $3;}
| cexpr '*' cexpr {$$ = $1 * $3;}
| cexpr '/' cexpr {
if ($3 == 0)
yyerror("zero divisor\n");
else
$$ = $1 / $3;
}
;
%%
void
yyerror(s)
char *s;
{
/* a concession to bsd error(1) */
if (Cfile)
fprintf(stderr, "\"%s\", ", Cfile);
else
fprintf(stderr, "%s: ", ProgName);
fprintf(stderr, "line %d: %s\n", Lineno, s);
}
/*
* patch in the costs of getting on/off the network.
*
* for each network member on netlist, add links:
* network -> member cost = 0;
* member -> network cost = parameter.
*
* if network and member both require gateways, assume network
* is a gateway to member (but not v.v., to avoid such travesties
* as topaz!seismo.css.gov.edu.rutgers).
*
* note that members can have varying costs to a network, by suitable
* multiple declarations. this is a feechur, albeit a useless one.
*/
STATIC void
fixnet(network, nlist, cost, netchar, netdir)
register node *network;
node *nlist;
Cost cost;
char netchar, netdir;
{ register node *member, *nextnet;
link *l;
network->n_flag |= NNET;
/* now insert the links */
for (member = nlist ; member; member = nextnet) {
/* network -> member, cost is 0 */
if (GATEWAYED(network) && GATEWAYED(member))
addgateway(network, member, (Cost) 0, netchar, netdir);
else
(void) addlink(network, member, (Cost) 0, netchar, netdir);
/* member -> network, cost is parameter */
(void) addlink(member, network, cost, netchar, netdir);
nextnet = member->n_net;
member->n_net = 0; /* clear for later use */
}
}
/* scanner */
#define LBRACE '{'
#define RBRACE '}'
#define LPAREN '('
#define RPAREN ')'
#define QUOTE '"'
STATIC int
yylex()
{ register int c;
Cost cost;
char errbuf[128];
static char buf[128]; /* for return to yacc part */
/* count lines, skip over space and comments */
tailrecursion:
if (feof(stdin) && yywrap())
return(EOF);
if ((c = getchar()) == EOF)
goto tailrecursion;
while (c == ' ' || c == '\t')
c = getchar();
if (c == '#') {
while ((c = getchar()) != '\n')
if (c == EOF)
goto tailrecursion;
/* fall into ... */
}
if (c == '\n') {
Lineno++;
c = getchar();
if (c == ' ' || c == '\t')
goto tailrecursion; /* continuation line */
ungetc(c, stdin);
Scanstate = NEWLINE;
return(NL);
}
ungetc(c, stdin);
switch(Scanstate) {
case COSTING:
if (isdigit(c)) {
cost = 0;
for (c = getchar(); isdigit(c); c = getchar())
cost = (cost * 10) + c - '0';
ungetc(c, stdin);
yylval.y_cost = cost;
return(COST);
}
if (getword(buf) == 0) {
if ((yylval.y_cost = isacost(buf)) == 0) {
sprintf(errbuf, "unknown cost (%s), using default", buf);
yyerror(errbuf);
yylval.y_cost = DEFCOST;
}
return(COST);
}
return(getchar()); /* can't be EOF */
case NEWLINE:
Scanstate = OTHER;
if (getword(buf) != 0)
return(getchar()); /* can't be EOF */
/* `private' (but not `"private"')? */
if (c == 'p' && strcmp(buf, "private") == 0)
return(PRIVATE);
yylval.y_name = buf;
return(HOST);
}
if (getword(buf) == 0) {
yylval.y_name = buf;
return(SITE);
}
c = getchar(); /* can't be EOF */
if (index(Netchars, c)) {
yylval.y_net = c;
return(NET);
}
return(c);
}
/*
* fill str with the next word in [0-9A-Za-z][-._0-9A-Za-z]+ or a quoted
* string that contains no newline. return -1 on failure or EOF, 0 o.w.
*/
STATIC int
getword(str)
register char *str;
{ register int c;
c = getchar();
if (c == QUOTE) {
for ( ; (*str = getchar()) != '"'; str++) {
if (*str == '\n') {
yyerror("newline in quoted string\n");
ungetc('\n', stdin);
return(-1);
}
}
*str = 0;
return(0);
}
/* host name must start with alphanumeric or `.' */
if (!isalnum(c) && c != '.') {
ungetc(c, stdin);
return(-1);
}
yymore:
do {
*str++ = c;
c = getchar();
} while (isalnum(c) || c == '.' || c == '_');
if (c == '-' && Scanstate != COSTING)
goto yymore;
ungetc(c, stdin);
*str = 0;
return(0);
}
static struct ctable {
char *cname;
Cost cval;
} ctable[] = {
/*
* this list is searched sequentially (with strcmps!).
* it is too long. (they are ordered by frequency of
* appearance in a "typical" dataset.)
*
* adding a 0 cost token breaks isacost(). don't do it.
*/
{"DEMAND", 300},
{"DAILY", 5000},
{"DIRECT", 200},
{"EVENING", 1800},
{"LOCAL", 25},
{"LOW", 5}, /* baud rate penalty */
{"HOURLY", 500},
{"POLLED", 5000},
{"DEDICATED", 95},
{"WEEKLY", 30000},
{"DEAD", INF/2},
{"HIGH", -5}, /* baud rate bonus */
/* the remainder are reviled */
{"ARPA", 100},
{"DIALED", 300},
{"A", 300},
{"B", 500},
{"C", 1800},
{"D", 5000},
{"E", 30000},
{"F", INF/2},
0
};
STATIC Cost
isacost(buf)
register char *buf;
{ register struct ctable *ct;
for (ct = ctable; ct; ct++)
if (strcmp(buf, ct->cname) == 0)
return(ct->cval);
return((Cost) 0);
}
STATIC int
yywrap()
{ char errbuf[100];
fixprivate(); /* munge private host definitions */
if (Ifiles == 0)
return(1);
fclose(stdin);
while (*Ifiles) {
Lineno = 1;
if (fopen((Cfile = *Ifiles++), "r"))
return(0);
sprintf(errbuf, "%s: %s", ProgName, Cfile);
perror(errbuf);
}
return(1);
}