home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume3 / pathalias2 / part2 / parse.y < prev    next >
Encoding:
Lex Description  |  1986-11-30  |  7.3 KB  |  391 lines

  1. %{
  2. /* pathalias -- by steve bellovin, as told to peter honeyman */
  3. #ifndef lint
  4. static char    *sccsid = "@(#)parse.y    8.1 (down!honey) 86/01/19";
  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    buf[BUFSIZ], errbuf[128];
  200.  
  201. tailrecursion:
  202.     if (feof(stdin) && yywrap())
  203.         return(EOF);
  204.  
  205.     if ((c = getchar()) == EOF)
  206.         goto tailrecursion;
  207.  
  208.     while (c == ' ' || c == '\t')
  209.         c = getchar();
  210.  
  211.     if (c == '\n') {
  212.         Lineno++;
  213.         c = getchar();
  214.         if (c == ' ' || c == '\t')
  215.             goto tailrecursion;
  216.         ungetc(c, stdin);
  217.         Scanstate = NEWLINE;
  218.         return(NL);
  219.     }
  220.  
  221.     if (c == '#') {
  222.         while ((c = getchar()) != '\n')
  223.             if (c == EOF)
  224.                 goto tailrecursion;
  225.         ungetc(c, stdin);
  226.         goto tailrecursion;
  227.     }
  228.  
  229.     ungetc(c, stdin);
  230.  
  231.     switch(Scanstate) {
  232.     case COSTING:
  233.         if (isdigit(c)) {
  234.             cost = 0;
  235.             for (c = getchar(); isdigit(c); c = getchar())
  236.                 cost = (cost * 10) + c - '0';
  237.  
  238.             ungetc(c, stdin);
  239.             yylval.y_cost = cost;
  240.             return(COST);
  241.         }
  242.  
  243.         
  244.         if (getword(buf) == 0) {
  245.             if ((yylval.y_cost = isacost(buf)) == 0) {
  246.                 sprintf(errbuf, "unknown cost (%s), using default", buf);
  247.                 yyerror(errbuf);
  248.                 yylval.y_cost = DEFCOST;
  249.             }
  250.             return(COST);
  251.         }
  252.  
  253.         return(getchar());    /* can't be EOF */
  254.  
  255.     case NEWLINE:
  256.         Scanstate = OTHER;
  257.         if (getword(buf) != 0)
  258.             return(getchar());    /* can't be EOF */
  259.         /* `private' (but not `"private"')? */
  260.         if (c == 'p' && strcmp(buf, "private") == 0)
  261.             return(PRIVATE);
  262.  
  263.         yylval.y_name = buf;
  264.         return(HOST);
  265.     }
  266.  
  267.     if (getword(buf) == 0) {
  268.         yylval.y_name = buf;
  269.         return(SITE);
  270.     }
  271.  
  272.     c = getchar();    /* can't be EOF */
  273.  
  274.     if (index(Netchars, c)) {
  275.         yylval.y_net = c;
  276.         return(NET);
  277.     }
  278.  
  279.     return(c);
  280. }
  281.  
  282. /*
  283.  * fill str with the next word in [0-9A-Za-z][-._0-9A-Za-z]+ or a quoted
  284.  * string that contains no newline.  return -1 on failure or EOF, 0 o.w.
  285.  */ 
  286. getword(str)
  287. register char    *str;
  288. {
  289.     register int    c;
  290.  
  291.     c = getchar();
  292.     if (c == QUOTE) {
  293.         for ( ; (*str = getchar()) != '"'; str++) {
  294.             if (*str == '\n') {
  295.                 yyerror("newline in quoted string\n");
  296.                 ungetc('\n', stdin);
  297.                 return(-1);
  298.             }
  299.         }
  300.         *str = 0;
  301.         return(0);
  302.     }
  303.  
  304.     /* host name must start with alphanumeric or `.' */
  305.     if (!isalnum(c) && c != '.') {
  306.         ungetc(c, stdin);
  307.         return(-1);
  308.     }
  309.  
  310. yymore:
  311.     do {
  312.         *str++ = c;
  313.         c = getchar();
  314.     } while (isalnum(c) || c == '.' || c == '_');
  315.  
  316.     if (c == '-' && Scanstate != COSTING)
  317.         goto yymore;
  318.  
  319.     ungetc(c, stdin);
  320.     *str = 0;
  321.     return(0);
  322. }
  323.  
  324. static struct ctable {
  325.     char *cname;
  326.     Cost cval;
  327. } ctable[] = {
  328.     /*
  329.      * this list is searched sequentially (with strcmps!).
  330.      * it is too long.  (they are ordered by frequency of
  331.      * appearance in a "typical" dataset.)
  332.      *
  333.      * adding a 0 cost token breaks isacost().  don't do it.
  334.      */
  335.     {"DEMAND", 300},
  336.     {"DAILY", 5000},
  337.     {"DIRECT", 200},
  338.     {"EVENING", 1800},
  339.     {"LOCAL", 25},
  340.     {"LOW", 5},    /* baud rate penalty */
  341.     {"HOURLY", 500},
  342.     {"POLLED", 5000},
  343.     {"DEDICATED", 95},
  344.     {"WEEKLY", 30000},
  345.     {"DEAD", INF/2},
  346.     {"HIGH", -5},    /* baud rate bonus */
  347.     /* the remainder are reviled */
  348.     {"ARPA", 100},
  349.     {"DIALED", 300},
  350.     {"A", 300},
  351.     {"B", 500},
  352.     {"C", 1800},
  353.     {"D", 5000},
  354.     {"E", 30000},
  355.     {"F", INF/2},
  356.     0
  357. };
  358.  
  359. STATIC Cost
  360. isacost(buf)
  361. register char    *buf;
  362. {
  363.     register struct ctable    *ct;
  364.  
  365.     for (ct = ctable; ct->cname; ct++)
  366.         if (strcmp(buf, ct->cname) == 0)
  367.             return(ct->cval);
  368.  
  369.     return((Cost) 0);
  370. }
  371.  
  372. yywrap()
  373. {
  374.     char    errbuf[100];
  375.  
  376.     fixprivate();    /* munge private host definitions */
  377.  
  378.     if (Ifiles == 0) 
  379.         return(1);
  380.  
  381.     fclose(stdin);
  382.     while (*Ifiles) {
  383.         Lineno = 1;
  384.         if (fopen((Cfile = *Ifiles++), "r"))
  385.             return(0);
  386.         sprintf(errbuf, "%s: %s", ProgName, Cfile);
  387.         perror(errbuf);
  388.     }
  389.     return(1);
  390. }
  391.