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

Defined functions

_fixnet defined in line 159; used 3 times
_getword defined in line 287; used 3 times
_isacost defined in line 360; used 2 times
_yyerror defined in line 132; used 5 times
_yylex defined in line 195; never used
_yywrap defined in line 373; used 1 times

Defined variables

_ctable defined in line 328; used 1 times

Defined struct's

ctable defined in line 325; used 2 times
  • in line 364(2)

Defined macros

LBRACE defined in line 187; never used
LPAREN defined in line 189; never used
QUOTE defined in line 191; used 1 times
RBRACE defined in line 188; never used
RPAREN defined in line 190; never used
Last modified: 1986-02-01
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1466
Valid CSS Valid XHTML 1.0 Strict