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: }