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

Defined functions

_fixnet defined in line 217; used 4 times
_getword defined in line 367; used 4 times
_yyerror defined in line 189; used 8 times
_yylex defined in line 273; used 1 times
  • in line 31
_yywrap defined in line 407; used 2 times

Defined variables

_STATIC defined in line 367; used 5 times
_ctable defined in line 252; used 1 times

Defined struct's

ctable defined in line 249; used 2 times
  • in line 278(2)

Defined macros

NLRETURN defined in line 247; used 4 times
QUOTE defined in line 245; used 2 times
STR_EQ defined in line 246; used 3 times
TERMINAL defined in line 35; used 3 times
getlink defined in line 19; used 6 times
getnode defined in line 18; used 12 times
Last modified: 1988-04-16
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3933
Valid CSS Valid XHTML 1.0 Strict