home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume12 / pathalias9 / part02 / parse.y < prev    next >
Encoding:
Lex Description  |  1987-10-08  |  8.2 KB  |  413 lines

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