home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / usr.bin / rdist / gram.y < prev    next >
Encoding:
Lex Description  |  1991-04-18  |  9.7 KB  |  506 lines

  1. %{
  2. /*
  3.  * Copyright (c) 1983 Regents of the University of California.
  4.  * All rights reserved.
  5.  *
  6.  * Redistribution and use in source and binary forms, with or without
  7.  * modification, are permitted provided that the following conditions
  8.  * are met:
  9.  * 1. Redistributions of source code must retain the above copyright
  10.  *    notice, this list of conditions and the following disclaimer.
  11.  * 2. Redistributions in binary form must reproduce the above copyright
  12.  *    notice, this list of conditions and the following disclaimer in the
  13.  *    documentation and/or other materials provided with the distribution.
  14.  * 3. All advertising materials mentioning features or use of this software
  15.  *    must display the following acknowledgement:
  16.  *    This product includes software developed by the University of
  17.  *    California, Berkeley and its contributors.
  18.  * 4. Neither the name of the University nor the names of its contributors
  19.  *    may be used to endorse or promote products derived from this software
  20.  *    without specific prior written permission.
  21.  *
  22.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  23.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  24.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  25.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  26.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  27.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  28.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  29.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  30.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  31.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  32.  * SUCH DAMAGE.
  33.  */
  34.  
  35. #ifndef lint
  36. static char sccsid[] = "@(#)gram.y    5.6 (Berkeley) 6/1/90";
  37. #endif /* not lint */
  38.  
  39. #include "defs.h"
  40.  
  41. struct    cmd *cmds = NULL;
  42. struct    cmd *last_cmd;
  43. struct    namelist *last_n;
  44. struct    subcmd *last_sc;
  45.  
  46. %}
  47.  
  48. %term EQUAL    1
  49. %term LP    2
  50. %term RP    3
  51. %term SM    4
  52. %term ARROW    5
  53. %term COLON    6
  54. %term DCOLON    7
  55. %term NAME    8
  56. %term STRING    9
  57. %term INSTALL    10
  58. %term NOTIFY    11
  59. %term EXCEPT    12
  60. %term PATTERN    13
  61. %term SPECIAL    14
  62. %term OPTION    15
  63.  
  64. %union {
  65.     int intval;
  66.     char *string;
  67.     struct subcmd *subcmd;
  68.     struct namelist *namel;
  69. }
  70.  
  71. %type <intval> OPTION, options
  72. %type <string> NAME, STRING
  73. %type <subcmd> INSTALL, NOTIFY, EXCEPT, PATTERN, SPECIAL, cmdlist, cmd
  74. %type <namel> namelist, names, opt_namelist
  75.  
  76. %%
  77.  
  78. file:          /* VOID */
  79.         | file command
  80.         ;
  81.  
  82. command:      NAME EQUAL namelist = {
  83.             (void) lookup($1, INSERT, $3);
  84.         }
  85.         | namelist ARROW namelist cmdlist = {
  86.             insert(NULL, $1, $3, $4);
  87.         }
  88.         | NAME COLON namelist ARROW namelist cmdlist = {
  89.             insert($1, $3, $5, $6);
  90.         }
  91.         | namelist DCOLON NAME cmdlist = {
  92.             append(NULL, $1, $3, $4);
  93.         }
  94.         | NAME COLON namelist DCOLON NAME cmdlist = {
  95.             append($1, $3, $5, $6);
  96.         }
  97.         | error
  98.         ;
  99.  
  100. namelist:      NAME = {
  101.             $$ = makenl($1);
  102.         }
  103.         | LP names RP = {
  104.             $$ = $2;
  105.         }
  106.         ;
  107.  
  108. names:          /* VOID */ {
  109.             $$ = last_n = NULL;
  110.         }
  111.         | names NAME = {
  112.             if (last_n == NULL)
  113.                 $$ = last_n = makenl($2);
  114.             else {
  115.                 last_n->n_next = makenl($2);
  116.                 last_n = last_n->n_next;
  117.                 $$ = $1;
  118.             }
  119.         }
  120.         ;
  121.  
  122. cmdlist:      /* VOID */ {
  123.             $$ = last_sc = NULL;
  124.         }
  125.         | cmdlist cmd = {
  126.             if (last_sc == NULL)
  127.                 $$ = last_sc = $2;
  128.             else {
  129.                 last_sc->sc_next = $2;
  130.                 last_sc = $2;
  131.                 $$ = $1;
  132.             }
  133.         }
  134.         ;
  135.  
  136. cmd:          INSTALL options opt_namelist SM = {
  137.             register struct namelist *nl;
  138.  
  139.             $1->sc_options = $2 | options;
  140.             if ($3 != NULL) {
  141.                 nl = expand($3, E_VARS);
  142.                 if (nl) {
  143.                     if (nl->n_next != NULL)
  144.                         yyerror("only one name allowed\n");
  145.                     $1->sc_name = nl->n_name;
  146.                     free(nl);
  147.                 } else
  148.                     $1->sc_name = NULL;
  149.             }
  150.             $$ = $1;
  151.         }
  152.         | NOTIFY namelist SM = {
  153.             if ($2 != NULL)
  154.                 $1->sc_args = expand($2, E_VARS);
  155.             $$ = $1;
  156.         }
  157.         | EXCEPT namelist SM = {
  158.             if ($2 != NULL)
  159.                 $1->sc_args = expand($2, E_ALL);
  160.             $$ = $1;
  161.         }
  162.         | PATTERN namelist SM = {
  163.             struct namelist *nl;
  164.             char *cp, *re_comp();
  165.  
  166.             for (nl = $2; nl != NULL; nl = nl->n_next)
  167.                 if ((cp = re_comp(nl->n_name)) != NULL)
  168.                     yyerror(cp);
  169.             $1->sc_args = expand($2, E_VARS);
  170.             $$ = $1;
  171.         }
  172.         | SPECIAL opt_namelist STRING SM = {
  173.             if ($2 != NULL)
  174.                 $1->sc_args = expand($2, E_ALL);
  175.             $1->sc_name = $3;
  176.             $$ = $1;
  177.         }
  178.         ;
  179.  
  180. options:      /* VOID */ = {
  181.             $$ = 0;
  182.         }
  183.         | options OPTION = {
  184.             $$ |= $2;
  185.         }
  186.         ;
  187.  
  188. opt_namelist:      /* VOID */ = {
  189.             $$ = NULL;
  190.         }
  191.         | namelist = {
  192.             $$ = $1;
  193.         }
  194.         ;
  195.  
  196. %%
  197.  
  198. int    yylineno = 1;
  199. extern    FILE *fin;
  200.  
  201. yylex()
  202. {
  203.     static char yytext[INMAX];
  204.     register int c;
  205.     register char *cp1, *cp2;
  206.     static char quotechars[] = "[]{}*?$";
  207.     
  208. again:
  209.     switch (c = getc(fin)) {
  210.     case EOF:  /* end of file */
  211.         return(0);
  212.  
  213.     case '#':  /* start of comment */
  214.         while ((c = getc(fin)) != EOF && c != '\n')
  215.             ;
  216.         if (c == EOF)
  217.             return(0);
  218.     case '\n':
  219.         yylineno++;
  220.     case ' ':
  221.     case '\t':  /* skip blanks */
  222.         goto again;
  223.  
  224.     case '=':  /* EQUAL */
  225.         return(EQUAL);
  226.  
  227.     case '(':  /* LP */
  228.         return(LP);
  229.  
  230.     case ')':  /* RP */
  231.         return(RP);
  232.  
  233.     case ';':  /* SM */
  234.         return(SM);
  235.  
  236.     case '-':  /* -> */
  237.         if ((c = getc(fin)) == '>')
  238.             return(ARROW);
  239.         ungetc(c, fin);
  240.         c = '-';
  241.         break;
  242.  
  243.     case '"':  /* STRING */
  244.         cp1 = yytext;
  245.         cp2 = &yytext[INMAX - 1];
  246.         for (;;) {
  247.             if (cp1 >= cp2) {
  248.                 yyerror("command string too long\n");
  249.                 break;
  250.             }
  251.             c = getc(fin);
  252.             if (c == EOF || c == '"')
  253.                 break;
  254.             if (c == '\\') {
  255.                 if ((c = getc(fin)) == EOF) {
  256.                     *cp1++ = '\\';
  257.                     break;
  258.                 }
  259.             }
  260.             if (c == '\n') {
  261.                 yylineno++;
  262.                 c = ' '; /* can't send '\n' */
  263.             }
  264.             *cp1++ = c;
  265.         }
  266.         if (c != '"')
  267.             yyerror("missing closing '\"'\n");
  268.         *cp1 = '\0';
  269.         yylval.string = makestr(yytext);
  270.         return(STRING);
  271.  
  272.     case ':':  /* : or :: */
  273.         if ((c = getc(fin)) == ':')
  274.             return(DCOLON);
  275.         ungetc(c, fin);
  276.         return(COLON);
  277.     }
  278.     cp1 = yytext;
  279.     cp2 = &yytext[INMAX - 1];
  280.     for (;;) {
  281.         if (cp1 >= cp2) {
  282.             yyerror("input line too long\n");
  283.             break;
  284.         }
  285.         if (c == '\\') {
  286.             if ((c = getc(fin)) != EOF) {
  287.                 if (any(c, quotechars))
  288.                     c |= QUOTE;
  289.             } else {
  290.                 *cp1++ = '\\';
  291.                 break;
  292.             }
  293.         }
  294.         *cp1++ = c;
  295.         c = getc(fin);
  296.         if (c == EOF || any(c, " \"'\t()=;:\n")) {
  297.             ungetc(c, fin);
  298.             break;
  299.         }
  300.     }
  301.     *cp1 = '\0';
  302.     if (yytext[0] == '-' && yytext[2] == '\0') {
  303.         switch (yytext[1]) {
  304.         case 'b':
  305.             yylval.intval = COMPARE;
  306.             return(OPTION);
  307.  
  308.         case 'R':
  309.             yylval.intval = REMOVE;
  310.             return(OPTION);
  311.  
  312.         case 'v':
  313.             yylval.intval = VERIFY;
  314.             return(OPTION);
  315.  
  316.         case 'w':
  317.             yylval.intval = WHOLE;
  318.             return(OPTION);
  319.  
  320.         case 'y':
  321.             yylval.intval = YOUNGER;
  322.             return(OPTION);
  323.  
  324.         case 'h':
  325.             yylval.intval = FOLLOW;
  326.             return(OPTION);
  327.  
  328.         case 'i':
  329.             yylval.intval = IGNLNKS;
  330.             return(OPTION);
  331.         }
  332.     }
  333.     if (!strcmp(yytext, "install"))
  334.         c = INSTALL;
  335.     else if (!strcmp(yytext, "notify"))
  336.         c = NOTIFY;
  337.     else if (!strcmp(yytext, "except"))
  338.         c = EXCEPT;
  339.     else if (!strcmp(yytext, "except_pat"))
  340.         c = PATTERN;
  341.     else if (!strcmp(yytext, "special"))
  342.         c = SPECIAL;
  343.     else {
  344.         yylval.string = makestr(yytext);
  345.         return(NAME);
  346.     }
  347.     yylval.subcmd = makesubcmd(c);
  348.     return(c);
  349. }
  350.  
  351. any(c, str)
  352.     register int c;
  353.     register char *str;
  354. {
  355.     while (*str)
  356.         if (c == *str++)
  357.             return(1);
  358.     return(0);
  359. }
  360.  
  361. /*
  362.  * Insert or append ARROW command to list of hosts to be updated.
  363.  */
  364. insert(label, files, hosts, subcmds)
  365.     char *label;
  366.     struct namelist *files, *hosts;
  367.     struct subcmd *subcmds;
  368. {
  369.     register struct cmd *c, *prev, *nc;
  370.     register struct namelist *h;
  371.  
  372.     files = expand(files, E_VARS|E_SHELL);
  373.     hosts = expand(hosts, E_ALL);
  374.     for (h = hosts; h != NULL; free(h), h = h->n_next) {
  375.         /*
  376.          * Search command list for an update to the same host.
  377.          */
  378.         for (prev = NULL, c = cmds; c!=NULL; prev = c, c = c->c_next) {
  379.             if (strcmp(c->c_name, h->n_name) == 0) {
  380.                 do {
  381.                     prev = c;
  382.                     c = c->c_next;
  383.                 } while (c != NULL &&
  384.                     strcmp(c->c_name, h->n_name) == 0);
  385.                 break;
  386.             }
  387.         }
  388.         /*
  389.          * Insert new command to update host.
  390.          */
  391.         nc = ALLOC(cmd);
  392.         if (nc == NULL)
  393.             fatal("ran out of memory\n");
  394.         nc->c_type = ARROW;
  395.         nc->c_name = h->n_name;
  396.         nc->c_label = label;
  397.         nc->c_files = files;
  398.         nc->c_cmds = subcmds;
  399.         nc->c_next = c;
  400.         if (prev == NULL)
  401.             cmds = nc;
  402.         else
  403.             prev->c_next = nc;
  404.         /* update last_cmd if appending nc to cmds */
  405.         if (c == NULL)
  406.             last_cmd = nc;
  407.     }
  408. }
  409.  
  410. /*
  411.  * Append DCOLON command to the end of the command list since these are always
  412.  * executed in the order they appear in the distfile.
  413.  */
  414. append(label, files, stamp, subcmds)
  415.     char *label;
  416.     struct namelist *files;
  417.     char *stamp;
  418.     struct subcmd *subcmds;
  419. {
  420.     register struct cmd *c;
  421.  
  422.     c = ALLOC(cmd);
  423.     if (c == NULL)
  424.         fatal("ran out of memory\n");
  425.     c->c_type = DCOLON;
  426.     c->c_name = stamp;
  427.     c->c_label = label;
  428.     c->c_files = expand(files, E_ALL);
  429.     c->c_cmds = subcmds;
  430.     c->c_next = NULL;
  431.     if (cmds == NULL)
  432.         cmds = last_cmd = c;
  433.     else {
  434.         last_cmd->c_next = c;
  435.         last_cmd = c;
  436.     }
  437. }
  438.  
  439. /*
  440.  * Error printing routine in parser.
  441.  */
  442. yyerror(s)
  443.     char *s;
  444. {
  445.     extern int yychar;
  446.  
  447.     nerrs++;
  448.     fflush(stdout);
  449.     fprintf(stderr, "rdist: line %d: %s\n", yylineno, s);
  450. }
  451.  
  452. /*
  453.  * Return a copy of the string.
  454.  */
  455. char *
  456. makestr(str)
  457.     char *str;
  458. {
  459.     register char *cp, *s;
  460.  
  461.     str = cp = malloc(strlen(s = str) + 1);
  462.     if (cp == NULL)
  463.         fatal("ran out of memory\n");
  464.     while (*cp++ = *s++)
  465.         ;
  466.     return(str);
  467. }
  468.  
  469. /*
  470.  * Allocate a namelist structure.
  471.  */
  472. struct namelist *
  473. makenl(name)
  474.     char *name;
  475. {
  476.     register struct namelist *nl;
  477.  
  478.     nl = ALLOC(namelist);
  479.     if (nl == NULL)
  480.         fatal("ran out of memory\n");
  481.     nl->n_name = name;
  482.     nl->n_next = NULL;
  483.     return(nl);
  484. }
  485.  
  486. /*
  487.  * Make a sub command for lists of variables, commands, etc.
  488.  */
  489. struct subcmd *
  490. makesubcmd(type, name)
  491.     int type;
  492.     register char *name;
  493. {
  494.     register char *cp;
  495.     register struct subcmd *sc;
  496.  
  497.     sc = ALLOC(subcmd);
  498.     if (sc == NULL)
  499.         fatal("ran out of memory\n");
  500.     sc->sc_type = type;
  501.     sc->sc_args = NULL;
  502.     sc->sc_next = NULL;
  503.     sc->sc_name = NULL;
  504.     return(sc);
  505. }
  506.