|
|
1.1 root 1: %{
2: /* pathalias -- by steve bellovin, as told to peter honeyman */
3: #ifndef lint
4: static char *sccsid = "@(#)parse.y 8.2 (down!honey) 86/01/29";
5: #endif lint
6:
7: #include "def.h"
8:
9: /* I thank Paul Haahr and Greg Noel for helping to clean this up. */
10: %}
11:
12: %union {
13: node *y_node;
14: Cost y_cost;
15: char y_net;
16: char *y_name;
17: struct {
18: node *ys_node;
19: Cost ys_cost;
20: char ys_net;
21: char ys_dir;
22: } y_s;
23: }
24:
25: %type <y_s> site
26: %type <y_node> links aliases plist network nlist host Psite Site
27: %type <y_cost> cost cexpr
28:
29: %token <y_name> SITE HOST
30: %token <y_cost> COST
31: %token <y_net> NET
32: %token NL PRIVATE
33:
34: %left '+' '-'
35: %left '*' '/'
36:
37: %%
38: map : /* empty */
39: | map NL
40: | map links NL
41: | map aliases NL
42: | map network NL
43: | map private NL
44: | error NL
45: ;
46:
47: links : host site cost {
48: if (GATEWAYED($2.ys_node))
49: addgateway($1, $2.ys_node, $3, $2.ys_net, $2.ys_dir);
50: else
51: addlink($1, $2.ys_node, $3, $2.ys_net, $2.ys_dir);
52: }
53:
54: | links ',' site cost {
55: if (GATEWAYED($3.ys_node))
56: addgateway($1, $3.ys_node, $4, $3.ys_net, $3.ys_dir);
57: else
58: addlink($1, $3.ys_node, $4, $3.ys_net, $3.ys_dir);
59: }
60: | links ',' /* permit this benign error */
61: ;
62:
63: aliases : host '=' Site {alias($1, $3);}
64: | aliases ',' Site {alias($1, $3);}
65: | aliases ',' /* permit this benign error */
66: ;
67:
68: network : host '=' '{' nlist '}' cost {fixnet($1, $4, $6, DEFNET, DEFDIR);}
69: | host '=' NET '{' nlist '}' cost {fixnet($1, $5, $7, $3, LRIGHT);}
70: | host '=' '{' nlist '}' NET cost {fixnet($1, $4, $7, $6, LLEFT);}
71: ;
72:
73: private : PRIVATE '{' plist '}' ;
74:
75: host : HOST {$$ = addnode($1);}
76: | PRIVATE {$$ = addnode("private");}
77: ;
78:
79: Site : SITE {$$ = addnode($1);} ;
80:
81: site : Site {
82: $$.ys_node = $1;
83: $$.ys_net = DEFNET;
84: $$.ys_dir = DEFDIR;
85: }
86: | NET Site {
87: $$.ys_node = $2;
88: $$.ys_net = $1;
89: $$.ys_dir = LRIGHT;
90: }
91: | Site NET {
92: $$.ys_node = $1;
93: $$.ys_net = $2;
94: $$.ys_dir = LLEFT;
95: }
96: ;
97:
98: Psite : SITE {$$ = addprivate($1);} ;
99:
100: plist : Psite {$1->n_flag |= ISPRIVATE;}
101: | plist ',' Psite {$3->n_flag |= ISPRIVATE;}
102: | plist ',' /* permit this benign error */
103: ;
104:
105: nlist : Site
106: | nlist ',' Site {
107: if ($3->n_net == 0) {
108: $3->n_net = $1;
109: $$ = $3;
110: }
111: }
112: | nlist ',' /* permit this benign error */
113: ;
114:
115: cost : {$$ = DEFCOST; /* empty -- cost is always optional */}
116: | '(' {Scanstate = COSTING;} cexpr {Scanstate = OTHER;} ')'
117: {$$ = $3;}
118: ;
119:
120: cexpr : COST
121: | '(' cexpr ')' {$$ = $2;}
122: | cexpr '+' cexpr {$$ = $1 + $3;}
123: | cexpr '-' cexpr {$$ = $1 - $3;}
124: | cexpr '*' cexpr {$$ = $1 * $3;}
125: | cexpr '/' cexpr {
126: if ($3 == 0)
127: yyerror("zero divisor\n");
128: else
129: $$ = $1 / $3;
130: }
131: ;
132: %%
133:
134: yyerror(s)
135: char *s;
136: {
137: /* a concession to bsd error(1) */
138: if (Cfile)
139: fprintf(stderr, "\"%s\", ", Cfile);
140: else
141: fprintf(stderr, "%s: ", ProgName);
142: fprintf(stderr, "line %d: %s\n", Lineno, s);
143: }
144:
145: /*
146: * patch in the costs of getting on/off the network.
147: *
148: * for each network member on netlist, add links:
149: * network -> member cost = 0;
150: * member -> network cost = parameter.
151: *
152: * if network and member both require gateways, assume network
153: * is a gateway to member (but not v.v., to avoid such travesties
154: * as topaz!seismo.css.gov.edu.rutgers).
155: *
156: * note that members can have varying costs to a network, by suitable
157: * multiple declarations. this is a feechur, albeit a useless one.
158: */
159: fixnet(network, nlist, cost, netchar, netdir)
160: register node *network;
161: node *nlist;
162: Cost cost;
163: char netchar, netdir;
164: {
165: register node *member, *nextnet;
166: link *l;
167:
168: network->n_flag |= NNET;
169:
170: /* now insert the links */
171: for (member = nlist ; member; member = nextnet) {
172: /* network -> member, cost is 0 */
173: if (GATEWAYED(network) && GATEWAYED(member))
174: (void) addgateway(network, member, (Cost) 0, netchar, netdir);
175: else
176: (void) addlink(network, member, (Cost) 0, netchar, netdir);
177:
178: /* member -> network, cost is parameter */
179: (void) addlink(member, network, cost, netchar, netdir);
180: nextnet = member->n_net;
181: member->n_net = 0; /* clear for later use */
182: }
183: }
184:
185: /* scanner */
186:
187: #define LBRACE '{'
188: #define RBRACE '}'
189: #define LPAREN '('
190: #define RPAREN ')'
191: #define QUOTE '"'
192:
193: Cost isacost();
194:
195: yylex()
196: {
197: register int c;
198: Cost cost;
199: char errbuf[128];
200: static char buf[128]; /* for return to yacc part */
201:
202: tailrecursion:
203: if (feof(stdin) && yywrap())
204: return(EOF);
205:
206: if ((c = getchar()) == EOF)
207: goto tailrecursion;
208:
209: while (c == ' ' || c == '\t')
210: c = getchar();
211:
212: if (c == '\n') {
213: Lineno++;
214: c = getchar();
215: if (c == ' ' || c == '\t')
216: goto tailrecursion;
217: ungetc(c, stdin);
218: Scanstate = NEWLINE;
219: return(NL);
220: }
221:
222: if (c == '#') {
223: while ((c = getchar()) != '\n')
224: if (c == EOF)
225: goto tailrecursion;
226: ungetc(c, stdin);
227: goto tailrecursion;
228: }
229:
230: ungetc(c, stdin);
231:
232: switch(Scanstate) {
233: case COSTING:
234: if (isdigit(c)) {
235: cost = 0;
236: for (c = getchar(); isdigit(c); c = getchar())
237: cost = (cost * 10) + c - '0';
238:
239: ungetc(c, stdin);
240: yylval.y_cost = cost;
241: return(COST);
242: }
243:
244:
245: if (getword(buf) == 0) {
246: if ((yylval.y_cost = isacost(buf)) == 0) {
247: sprintf(errbuf, "unknown cost (%s), using default", buf);
248: yyerror(errbuf);
249: yylval.y_cost = DEFCOST;
250: }
251: return(COST);
252: }
253:
254: return(getchar()); /* can't be EOF */
255:
256: case NEWLINE:
257: Scanstate = OTHER;
258: if (getword(buf) != 0)
259: return(getchar()); /* can't be EOF */
260: /* `private' (but not `"private"')? */
261: if (c == 'p' && strcmp(buf, "private") == 0)
262: return(PRIVATE);
263:
264: yylval.y_name = buf;
265: return(HOST);
266: }
267:
268: if (getword(buf) == 0) {
269: yylval.y_name = buf;
270: return(SITE);
271: }
272:
273: c = getchar(); /* can't be EOF */
274:
275: if (index(Netchars, c)) {
276: yylval.y_net = c;
277: return(NET);
278: }
279:
280: return(c);
281: }
282:
283: /*
284: * fill str with the next word in [0-9A-Za-z][-._0-9A-Za-z]+ or a quoted
285: * string that contains no newline. return -1 on failure or EOF, 0 o.w.
286: */
287: getword(str)
288: register char *str;
289: {
290: register int c;
291:
292: c = getchar();
293: if (c == QUOTE) {
294: for ( ; (*str = getchar()) != '"'; str++) {
295: if (*str == '\n') {
296: yyerror("newline in quoted string\n");
297: ungetc('\n', stdin);
298: return(-1);
299: }
300: }
301: *str = 0;
302: return(0);
303: }
304:
305: /* host name must start with alphanumeric or `.' */
306: if (!isalnum(c) && c != '.') {
307: ungetc(c, stdin);
308: return(-1);
309: }
310:
311: yymore:
312: do {
313: *str++ = c;
314: c = getchar();
315: } while (isalnum(c) || c == '.' || c == '_');
316:
317: if (c == '-' && Scanstate != COSTING)
318: goto yymore;
319:
320: ungetc(c, stdin);
321: *str = 0;
322: return(0);
323: }
324:
325: static struct ctable {
326: char *cname;
327: Cost cval;
328: } ctable[] = {
329: /*
330: * this list is searched sequentially (with strcmps!).
331: * it is too long. (they are ordered by frequency of
332: * appearance in a "typical" dataset.)
333: *
334: * adding a 0 cost token breaks isacost(). don't do it.
335: */
336: {"DEMAND", 300},
337: {"DAILY", 5000},
338: {"DIRECT", 200},
339: {"EVENING", 1800},
340: {"LOCAL", 25},
341: {"LOW", 5}, /* baud rate penalty */
342: {"HOURLY", 500},
343: {"POLLED", 5000},
344: {"DEDICATED", 95},
345: {"WEEKLY", 30000},
346: {"DEAD", INF/2},
347: {"HIGH", -5}, /* baud rate bonus */
348: /* the remainder are reviled */
349: {"ARPA", 100},
350: {"DIALED", 300},
351: {"A", 300},
352: {"B", 500},
353: {"C", 1800},
354: {"D", 5000},
355: {"E", 30000},
356: {"F", INF/2},
357: 0
358: };
359:
360: STATIC Cost
361: isacost(buf)
362: register char *buf;
363: {
364: register struct ctable *ct;
365:
366: for (ct = ctable; ct->cname; ct++)
367: if (strcmp(buf, ct->cname) == 0)
368: return(ct->cval);
369:
370: return((Cost) 0);
371: }
372:
373: yywrap()
374: {
375: char errbuf[100];
376:
377: fixprivate(); /* munge private host definitions */
378:
379: if (Ifiles == 0)
380: return(1);
381:
382: fclose(stdin);
383: while (*Ifiles) {
384: Lineno = 1;
385: if (fopen((Cfile = *Ifiles++), "r"))
386: return(0);
387: sprintf(errbuf, "%s: %s", ProgName, Cfile);
388: perror(errbuf);
389: }
390: return(1);
391: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.