home *** CD-ROM | disk | FTP | other *** search
/ back2roots/padua / padua.7z / padua / uucp / pathalias_V10.lzh / parse.y < prev    next >
Text File  |  1992-01-23  |  11KB  |  547 lines

  1. %{
  2. /* pathalias -- by steve bellovin, as told to peter honeyman */
  3. #ifndef lint
  4. static char    *sccsid = "@(#)parse.y    9.11 91/06/01";
  5. #endif /* lint */
  6.  
  7. #include "def.h"
  8.  
  9. /* scanner states (yylex, parse) */
  10. #define OTHER        0
  11. #define COSTING        1
  12. #define NEWLINE        2
  13. #define FILENAME    3
  14.  
  15. /* exports */
  16. long Tcount;
  17. extern void yyerror();
  18.  
  19. /* imports */
  20. extern node *addnode(), *addprivate();
  21. extern void fixprivate(), alias(), deadlink(), deletelink();
  22. extern link *addlink();
  23. extern int strcmp();
  24. extern char *strsave();
  25. extern int optind;
  26. extern char *Cfile, *Netchars, **Argv;
  27. extern int Lineno, Argc;
  28. extern node *Home;
  29.  
  30. /* privates */
  31. STATIC void fixnet(), adjust();
  32. STATIC int yylex(), yywrap(), getword();
  33. static int Scanstate = NEWLINE;    /* scanner (yylex) state */
  34.  
  35. /* flags for ys_flags */
  36. #define TERMINAL 1
  37. %}
  38.  
  39. %union {
  40.     node    *y_node;
  41.     Cost    y_cost;
  42.     char    y_net;
  43.     char    *y_name;
  44.     struct {
  45.         node *ys_node;
  46.         Cost ys_cost;
  47.         short ys_flag;
  48.         char ys_net;
  49.         char ys_dir;
  50.     } y_s;
  51. }
  52.  
  53. %type <y_s>    site asite
  54. %type <y_node>    links aliases plist network nlist host nhost
  55. %type <y_node>    usite delem dlist
  56. %type <y_cost>    cost cexpr
  57.  
  58. %token <y_name>    SITE HOST STRING
  59. %token <y_cost>    COST
  60. %token <y_net>    NET
  61. %token EOL PRIVATE DEAD DELETE FILETOK ADJUST
  62.  
  63. %left    '+' '-'
  64. %left    '*' '/'
  65.  
  66. %%
  67. map    :    /* empty */
  68.     |    map        EOL
  69.     |    map links    EOL
  70.     |    map aliases    EOL
  71.     |    map network    EOL
  72.     |    map private    EOL
  73.     |    map dead    EOL
  74.     |    map delete    EOL
  75.     |    map file    EOL
  76.     |    map adjust    EOL
  77.     |    error        EOL
  78.     ;
  79.  
  80. links    : host site cost {
  81.         struct link *l;
  82.  
  83.         l = addlink($1, $2.ys_node, $3, $2.ys_net, $2.ys_dir);
  84.         if (GATEWAYED($2.ys_node))
  85.             l->l_flag |= LGATEWAY;
  86.         if ($2.ys_flag & TERMINAL)
  87.             l->l_flag |= LTERMINAL;
  88.       }            
  89.     | links ',' site cost {
  90.         struct link *l;
  91.  
  92.         l = addlink($1, $3.ys_node, $4, $3.ys_net, $3.ys_dir);
  93.         if (GATEWAYED($3.ys_node))
  94.             l->l_flag |= LGATEWAY;
  95.         if ($3.ys_flag & TERMINAL)
  96.             l->l_flag |= LTERMINAL;
  97.       }
  98.     | links ','    /* benign error */
  99.     ;
  100.  
  101. host    : HOST        {$$ = addnode($1);}
  102.     | PRIVATE    {$$ = addnode("private");}
  103.     | DEAD        {$$ = addnode("dead");}
  104.     | DELETE    {$$ = addnode("delete");}
  105.     | FILETOK    {$$ = addnode("file");}
  106.     | ADJUST    {$$ = addnode("adjust");}
  107.     ;
  108.  
  109. site    : asite {
  110.         $$ = $1;
  111.         $$.ys_net = DEFNET;
  112.         $$.ys_dir = DEFDIR;
  113.       }
  114.     | NET asite {
  115.         $$ = $2;
  116.         $$.ys_net = $1;
  117.         $$.ys_dir = LRIGHT;
  118.       }
  119.     | asite NET {
  120.         $$ = $1;
  121.         $$.ys_net = $2;
  122.         $$.ys_dir = LLEFT;
  123.       }
  124.     ;
  125.  
  126. asite    : SITE {
  127.         $$.ys_node = addnode($1);
  128.         $$.ys_flag = 0;
  129.       }
  130.     | '<' SITE '>' {
  131.         Tcount++;
  132.         $$.ys_node = addnode($2);
  133.         $$.ys_flag = TERMINAL;
  134.       }
  135.     ;
  136.  
  137. aliases    : host '=' SITE    {alias($1, addnode($3));}
  138.     | aliases ',' SITE    {alias($1, addnode($3));}
  139.     | aliases ','    /* benign error */
  140.     ;
  141.  
  142. network    : nhost '{' nlist '}' cost    {fixnet($1, $3, $5, DEFNET, DEFDIR);}
  143.     | nhost NET '{' nlist '}' cost    {fixnet($1, $4, $6, $2, LRIGHT);}
  144.     | nhost '{' nlist '}' NET cost    {fixnet($1, $3, $6, $5, LLEFT);}
  145.     ;
  146.  
  147. nhost    : '='        {$$ = 0;    /* anonymous net */}
  148.     | host '='    {$$ = $1;    /* named net */}
  149.     ;
  150.  
  151. nlist    : SITE        {$$ = addnode($1);}
  152.     | nlist ',' SITE {
  153.         node *n;
  154.  
  155.         n = addnode($3);
  156.         if (n->n_net == 0) {
  157.             n->n_net = $1;
  158.             $$ = n;
  159.         }
  160.       }
  161.     | nlist ','    /* benign error */
  162.     ;
  163.         
  164. private    : PRIVATE '{' plist '}'            /* list of privates */
  165.     | PRIVATE '{' '}'    {fixprivate();}    /* end scope of privates */
  166.     ;
  167.  
  168. plist    : SITE            {addprivate($1)->n_flag |= ISPRIVATE;}
  169.     | plist ',' SITE    {addprivate($3)->n_flag |= ISPRIVATE;}
  170.     | plist ','        /* benign error */
  171.     ;
  172.  
  173. dead    : DEAD '{' dlist '}';
  174.  
  175. dlist    : delem
  176.     | dlist ',' delem
  177.     | dlist ','        /* benign error */
  178.     ;
  179.  
  180. delem    : SITE            {deadlink(addnode($1), (node *) 0);}
  181.     | usite NET usite    {deadlink($1, $3);}
  182.     ;
  183.  
  184. usite    : SITE    {$$ = addnode($1);} ;    /* necessary unit production */
  185.  
  186. delete    : DELETE '{' dellist '}';
  187.  
  188. dellist    : delelem
  189.     | dellist ',' delelem
  190.     | dellist ','        /* benign error */
  191.     ;
  192.  
  193. delelem    : SITE {
  194.         node *n;
  195.  
  196.         n = addnode($1);
  197.         deletelink(n, (node *) 0);
  198.         n->n_flag |= ISPRIVATE;
  199.         /* reset Home if it's deleted */
  200.         if (n == Home)
  201.             Home = addnode(Home->n_name);
  202.       }
  203.     | usite NET usite    {deletelink($1, $3);}
  204.     ;
  205.  
  206. file    : FILETOK '{' {Scanstate = FILENAME;} STRING {Scanstate = OTHER;} '}' {
  207.         Lineno = 0;
  208.         Cfile = strsave($4);
  209.     }
  210.  
  211. adjust    : ADJUST '{' adjlist '}' ;
  212.  
  213. adjlist    : adjelem
  214.     | adjlist ',' adjelem
  215.     | adjlist ','        /* benign error */
  216.     ;
  217.  
  218. adjelem    : usite cost    {adjust($1, $2);} ;
  219.  
  220. cost    : {$$ = DEFCOST;    /* empty -- cost is always optional */}
  221.     | '(' {Scanstate = COSTING;} cexpr {Scanstate = OTHER;} ')'
  222.         {$$ = $3;}
  223.     ;
  224.  
  225. cexpr    : COST
  226.     | '-' cexpr      {$$ = -$2;}
  227.     | '(' cexpr ')'   {$$ = $2;}
  228.     | cexpr '+' cexpr {$$ = $1 + $3;}
  229.     | cexpr '-' cexpr {$$ = $1 - $3;}
  230.     | cexpr '*' cexpr {$$ = $1 * $3;}
  231.     | cexpr '/' cexpr {
  232.         if ($3 == 0)
  233.             yyerror("zero divisor\n");
  234.         else
  235.             $$ = $1 / $3;
  236.       }
  237.     ;
  238. %%
  239.  
  240. void
  241. #ifdef YYDEBUG
  242. /*VARARGS1*/
  243. yyerror(fmt, arg)
  244.     char *fmt, *arg;
  245. #else
  246. yyerror(s)
  247.     char *s;
  248. #endif
  249. {
  250.     /* a concession to bsd error(1) */
  251.     fprintf(stderr, "\"%s\", ", Cfile);
  252. #ifdef YYDEBUG
  253.     fprintf(stderr, "line %d: ", Lineno);
  254.     fprintf(stderr, fmt, arg);
  255.     putc('\n', stderr);
  256. #else
  257.     fprintf(stderr, "line %d: %s\n", Lineno, s);
  258. #endif
  259. }
  260.  
  261. /*
  262.  * patch in the costs of getting on/off the network.
  263.  *
  264.  * for each network member on netlist, add links:
  265.  *    network -> member    cost = 0;
  266.  *    member -> network    cost = parameter.
  267.  *
  268.  * if network and member both require gateways, assume network
  269.  * is a gateway to member (but not v.v., to avoid such travesties
  270.  * as topaz!seismo.css.gov.edu.rutgers).
  271.  *
  272.  * note that members can have varying costs to a network, by suitable
  273.  * multiple declarations.  this is a feechur, albeit a useless one.
  274.  */
  275. STATIC void
  276. fixnet(network, nlist, cost, netchar, netdir)
  277.     register node *network;
  278.     node *nlist;
  279.     Cost cost;
  280.     char netchar, netdir;
  281. {    register node *member, *nextnet;
  282.     link *l;
  283.     static int netanon = 0;
  284.     char anon[25];
  285.  
  286.     if (network == 0) {
  287.         sprintf(anon, "[unnamed net %d]", netanon++);
  288.         network = addnode(anon);
  289.     }
  290.     network->n_flag |= NNET;
  291.  
  292.     /* insert the links */
  293.     for (member = nlist ; member; member = nextnet) {
  294.  
  295.         /* network -> member, cost is 0 */
  296.         l = addlink(network, member, (Cost) 0, netchar, netdir);
  297.         if (GATEWAYED(network) && GATEWAYED(member))
  298.             l->l_flag |= LGATEWAY;
  299.  
  300.         /* member -> network, cost is parameter */
  301.         /* never ever ever crawl up from a domain*/
  302.         if (!ISADOMAIN(network))
  303.             (void) addlink(member, network, cost, netchar, netdir);
  304.  
  305.         nextnet = member->n_net;
  306.         member->n_net = 0;    /* clear for later use */
  307.     }
  308. }
  309.  
  310. /* scanner */
  311.  
  312. #define QUOTE '"'
  313. #define STR_EQ(s1, s2) (s1[2] == s2[2] && strcmp(s1, s2) == 0)
  314. #define NLRETURN() {Scanstate = NEWLINE; return EOL;}
  315.  
  316. static struct ctable {
  317.     char *cname;
  318.     Cost cval;
  319. } ctable[] = {
  320.     /* ordered by frequency of appearance in a "typical" dataset */
  321.     {"DIRECT", 200},
  322.     {"DEMAND", 300},
  323.     {"DAILY", 5000},
  324.     {"HOURLY", 500},
  325.     {"DEDICATED", 100},
  326.     {"EVENING", 2000},
  327.     {"LOCAL", 25},
  328.     {"LOW", 5},    /* baud rate, quality penalty */
  329.     {"DEAD", MILLION},
  330.     {"POLLED", 5000},
  331.     {"WEEKLY", 30000},
  332.     {"HIGH", -5},    /* baud rate, quality bonus */
  333.     {"FAST", -80},    /* high speed (>= 9.6 kbps) modem */
  334.     /* deprecated */
  335.     {"ARPA", 100},
  336.     {"DIALED", 300},
  337.     {0, 0}
  338. };
  339.  
  340. STATIC int
  341. yylex()
  342. {    static char retbuf[128];    /* for return to yacc part */
  343.     register int c;
  344.     register char *buf = retbuf;
  345.     register struct ctable *ct;
  346.     register Cost cost;
  347.     char errbuf[128];
  348.  
  349.     if (feof(stdin) && yywrap())
  350.         return EOF;
  351.  
  352.     /* count lines, skip over space and comments */
  353.     if ((c = getchar()) == EOF)
  354.         NLRETURN();
  355.     
  356. continuation:
  357.     while (c == ' ' || c == '\t')
  358.         if ((c = getchar()) == EOF)
  359.             NLRETURN();
  360.  
  361.     if (c == '#')
  362.         while ((c = getchar()) != '\n')
  363.             if (c == EOF)
  364.                 NLRETURN();
  365.  
  366.     /* scan token */
  367.     if (c == '\n') {
  368.         Lineno++;
  369.         if ((c = getchar()) != EOF) {
  370.             if (c == ' ' || c == '\t')
  371.                 goto continuation;
  372.             ungetc(c, stdin);
  373.         }
  374.         NLRETURN();
  375.     }
  376.  
  377.     switch(Scanstate) {
  378.     case COSTING:
  379.         if (isdigit(c)) {
  380.             cost = c - '0';
  381.             for (c = getchar(); isdigit(c); c = getchar())
  382.                 cost = (cost * 10) + c - '0';
  383.             ungetc(c, stdin);
  384.             yylval.y_cost = cost;
  385.             return COST;
  386.         }
  387.  
  388.         if (getword(buf, c) == 0) {
  389.             for (ct = ctable; ct->cname; ct++)
  390.                 if (STR_EQ(buf, ct->cname)) {
  391.                     yylval.y_cost = ct->cval;
  392.                     return COST;
  393.                 }
  394.             sprintf(errbuf, "unknown cost (%s), using default", buf);
  395.             yyerror(errbuf);
  396.             yylval.y_cost = DEFCOST;
  397.             return COST;
  398.         }
  399.  
  400.         return c;    /* pass the buck */
  401.  
  402.     case NEWLINE:
  403.         Scanstate = OTHER;
  404.         if (getword(buf, c) != 0)
  405.             return c;
  406.         /*
  407.          * special purpose tokens.
  408.          *
  409.          * the "switch" serves the dual-purpose of recognizing
  410.          * unquoted tokens only.
  411.          */
  412.         switch(c) {
  413.         case 'p':
  414.             if (STR_EQ(buf, "private"))
  415.                 return PRIVATE;
  416.             break;
  417.         case 'd':
  418.             if (STR_EQ(buf, "dead"))
  419.                 return DEAD;
  420.             if (STR_EQ(buf, "delete"))
  421.                 return DELETE;
  422.             break;
  423.         case 'f':
  424.             if (STR_EQ(buf, "file"))
  425.                 return FILETOK;
  426.             break;
  427.         case 'a':
  428.             if (STR_EQ(buf, "adjust"))
  429.                 return ADJUST;
  430.             break;
  431.         }
  432.  
  433.         yylval.y_name = buf;
  434.         return HOST;
  435.  
  436.     case FILENAME:
  437.         while (c != EOF && isprint(c)) {
  438.             if (c == ' ' || c == '\t' || c == '\n' || c == '}')
  439.                 break;
  440.             *buf++ = c;
  441.             c = getchar();
  442.         }
  443.         if (c != EOF)
  444.             ungetc(c, stdin);
  445.         *buf = 0;
  446.         yylval.y_name = retbuf;
  447.         return STRING;
  448.     }
  449.  
  450.     if (getword(buf, c) == 0) {
  451.         yylval.y_name = buf;
  452.         return SITE;
  453.     }
  454.  
  455.     if (index(Netchars, c)) {
  456.         yylval.y_net = c;
  457.         return NET;
  458.     }
  459.  
  460.     return c;
  461. }
  462.  
  463. /*
  464.  * fill str with the next word in [0-9A-Za-z][-._0-9A-Za-z]+ or a quoted
  465.  * string that contains no newline.  return -1 on failure or EOF, 0 o.w.
  466.  */ 
  467. STATIC int
  468. getword(str, c)
  469.     register char *str;
  470.     register int c;
  471. {
  472.     if (c == QUOTE) {
  473.         while ((c = getchar()) != QUOTE) {
  474.             if (c == '\n') {
  475.                 yyerror("newline in quoted string\n");
  476.                 ungetc(c, stdin);
  477.                 return -1;
  478.             }
  479.             if (c == EOF) {
  480.                 yyerror("EOF in quoted string\n");
  481.                 return -1;
  482.             }
  483.             *str++ = c;
  484.         }
  485.         *str = 0;
  486.         return 0;
  487.     }
  488.  
  489.     /* host name must start with alphanumeric or `.' */
  490.     if (!isalnum(c) && c != '.')
  491.         return -1;
  492.  
  493. yymore:
  494.     do {
  495.         *str++ = c;
  496.         c = getchar();
  497.     } while (isalnum(c) || c == '.' || c == '_');
  498.  
  499.     if (c == '-' && Scanstate != COSTING)
  500.         goto yymore;
  501.  
  502.     ungetc(c, stdin);
  503.     *str = 0;
  504.     return 0;
  505. }
  506.  
  507. STATIC int
  508. yywrap()
  509. {    char errbuf[100];
  510.  
  511.     fixprivate();    /* munge private host definitions */
  512.     Lineno = 1;
  513.     while (optind < Argc) {
  514.         if (freopen((Cfile = Argv[optind++]), "r", stdin) != 0)
  515.             return 0;
  516.         sprintf(errbuf, "%s: %s", Argv[0], Cfile);
  517.         perror(errbuf);
  518.     }
  519. #ifdef AMIGA
  520.     freopen("nil:", "r", stdin);
  521. #else
  522.     freopen("/dev/null", "r", stdin);
  523. #endif
  524.     return -1;
  525. }
  526.  
  527. STATIC void
  528. adjust(n, cost)
  529.     node *n;
  530.     Cost cost;
  531. {    link *l;
  532.  
  533.     n->n_cost += cost;    /* cumulative */
  534.  
  535.     /* hit existing links */
  536.     for (l = n->n_link; l; l = l->l_next) {
  537.         if ((l->l_cost += cost) < 0) {
  538.             char buf[100];
  539.  
  540.             l->l_flag |= LDEAD;
  541.             sprintf(buf, "link to %s deleted with negative cost",
  542.                             l->l_to->n_name);
  543.             yyerror(buf);
  544.         }
  545.     }
  546. }
  547.