114920Sralph %{
223652Smckusick /*
3*63070Sbostic * Copyright (c) 1983, 1993
4*63070Sbostic * The Regents of the University of California. All rights reserved.
533415Sbostic *
642760Sbostic * %sccs.include.redist.c%
723652Smckusick */
823652Smckusick
914920Sralph #ifndef lint
10*63070Sbostic static char sccsid[] = "@(#)gram.y 8.1 (Berkeley) 06/09/93";
1133415Sbostic #endif /* not lint */
1214920Sralph
1314920Sralph #include "defs.h"
1414920Sralph
1516027Sralph struct cmd *cmds = NULL;
1616027Sralph struct cmd *last_cmd;
1716027Sralph struct namelist *last_n;
1816027Sralph struct subcmd *last_sc;
1914920Sralph
2054705Sbostic static char *makestr __P((char *));
2154705Sbostic
2214920Sralph %}
2314920Sralph
2415611Sralph %term EQUAL 1
2515611Sralph %term LP 2
2615611Sralph %term RP 3
2715611Sralph %term SM 4
2815611Sralph %term ARROW 5
2916295Sralph %term COLON 6
3016295Sralph %term DCOLON 7
3116295Sralph %term NAME 8
3216295Sralph %term STRING 9
3316295Sralph %term INSTALL 10
3416295Sralph %term NOTIFY 11
3516295Sralph %term EXCEPT 12
3616434Sralph %term PATTERN 13
3716434Sralph %term SPECIAL 14
3816434Sralph %term OPTION 15
3914920Sralph
4015198Sralph %union {
4115198Sralph int intval;
4215611Sralph char *string;
4316027Sralph struct subcmd *subcmd;
4416027Sralph struct namelist *namel;
4515198Sralph }
4614920Sralph
4715198Sralph %type <intval> OPTION, options
4816027Sralph %type <string> NAME, STRING
4916434Sralph %type <subcmd> INSTALL, NOTIFY, EXCEPT, PATTERN, SPECIAL, cmdlist, cmd
5016027Sralph %type <namel> namelist, names, opt_namelist
5114920Sralph
5214920Sralph %%
5314920Sralph
5414920Sralph file: /* VOID */
5514920Sralph | file command
5614920Sralph ;
5714920Sralph
5814920Sralph command: NAME EQUAL namelist = {
5916027Sralph (void) lookup($1, INSERT, $3);
6014920Sralph }
6114920Sralph | namelist ARROW namelist cmdlist = {
6216295Sralph insert(NULL, $1, $3, $4);
6314920Sralph }
6416295Sralph | NAME COLON namelist ARROW namelist cmdlist = {
6516295Sralph insert($1, $3, $5, $6);
6616295Sralph }
6715611Sralph | namelist DCOLON NAME cmdlist = {
6816295Sralph append(NULL, $1, $3, $4);
6915113Sralph }
7016295Sralph | NAME COLON namelist DCOLON NAME cmdlist = {
7116295Sralph append($1, $3, $5, $6);
7216295Sralph }
7314920Sralph | error
7414920Sralph ;
7514920Sralph
7614920Sralph namelist: NAME = {
7716027Sralph $$ = makenl($1);
7814920Sralph }
7914920Sralph | LP names RP = {
8014920Sralph $$ = $2;
8114920Sralph }
8214920Sralph ;
8314920Sralph
8414920Sralph names: /* VOID */ {
8516027Sralph $$ = last_n = NULL;
8614920Sralph }
8714920Sralph | names NAME = {
8816027Sralph if (last_n == NULL)
8916027Sralph $$ = last_n = makenl($2);
9014920Sralph else {
9116027Sralph last_n->n_next = makenl($2);
9216027Sralph last_n = last_n->n_next;
9314920Sralph $$ = $1;
9414920Sralph }
9514920Sralph }
9614920Sralph ;
9714920Sralph
9814920Sralph cmdlist: /* VOID */ {
9916027Sralph $$ = last_sc = NULL;
10014920Sralph }
10114920Sralph | cmdlist cmd = {
10216027Sralph if (last_sc == NULL)
10316027Sralph $$ = last_sc = $2;
10414920Sralph else {
10516027Sralph last_sc->sc_next = $2;
10616027Sralph last_sc = $2;
10714920Sralph $$ = $1;
10814920Sralph }
10914920Sralph }
11014920Sralph ;
11114920Sralph
11216027Sralph cmd: INSTALL options opt_namelist SM = {
11316027Sralph register struct namelist *nl;
11415113Sralph
11516027Sralph $1->sc_options = $2 | options;
11615270Sralph if ($3 != NULL) {
11716027Sralph nl = expand($3, E_VARS);
11838470Sbostic if (nl) {
11938470Sbostic if (nl->n_next != NULL)
12038470Sbostic yyerror("only one name allowed\n");
12138470Sbostic $1->sc_name = nl->n_name;
12238470Sbostic free(nl);
12338470Sbostic } else
12438470Sbostic $1->sc_name = NULL;
12515270Sralph }
12614920Sralph $$ = $1;
12714920Sralph }
12815270Sralph | NOTIFY namelist SM = {
12916027Sralph if ($2 != NULL)
13016027Sralph $1->sc_args = expand($2, E_VARS);
13114920Sralph $$ = $1;
13214920Sralph }
13315270Sralph | EXCEPT namelist SM = {
13416027Sralph if ($2 != NULL)
13516027Sralph $1->sc_args = expand($2, E_ALL);
13614920Sralph $$ = $1;
13714920Sralph }
13816434Sralph | PATTERN namelist SM = {
13916434Sralph struct namelist *nl;
14016434Sralph char *cp, *re_comp();
14116434Sralph
14216434Sralph for (nl = $2; nl != NULL; nl = nl->n_next)
14316434Sralph if ((cp = re_comp(nl->n_name)) != NULL)
14416434Sralph yyerror(cp);
14518561Sralph $1->sc_args = expand($2, E_VARS);
14616434Sralph $$ = $1;
14716434Sralph }
14815611Sralph | SPECIAL opt_namelist STRING SM = {
14915611Sralph if ($2 != NULL)
15016027Sralph $1->sc_args = expand($2, E_ALL);
15116027Sralph $1->sc_name = $3;
15215611Sralph $$ = $1;
15315611Sralph }
15414920Sralph ;
15515270Sralph
15615198Sralph options: /* VOID */ = {
15715198Sralph $$ = 0;
15815198Sralph }
15915198Sralph | options OPTION = {
16015198Sralph $$ |= $2;
16115198Sralph }
16215198Sralph ;
16314920Sralph
16415611Sralph opt_namelist: /* VOID */ = {
16515611Sralph $$ = NULL;
16615611Sralph }
16715611Sralph | namelist = {
16815611Sralph $$ = $1;
16915611Sralph }
17015611Sralph ;
17115611Sralph
17214920Sralph %%
17314920Sralph
17414920Sralph int yylineno = 1;
17514920Sralph extern FILE *fin;
17614920Sralph
17754705Sbostic int
yylex()17814920Sralph yylex()
17914920Sralph {
18014920Sralph static char yytext[INMAX];
18114920Sralph register int c;
18214920Sralph register char *cp1, *cp2;
18315198Sralph static char quotechars[] = "[]{}*?$";
18414920Sralph
18515113Sralph again:
18615113Sralph switch (c = getc(fin)) {
18715113Sralph case EOF: /* end of file */
18815113Sralph return(0);
18915113Sralph
19015113Sralph case '#': /* start of comment */
19115113Sralph while ((c = getc(fin)) != EOF && c != '\n')
19215113Sralph ;
19315113Sralph if (c == EOF)
19414920Sralph return(0);
19515113Sralph case '\n':
19615113Sralph yylineno++;
19715113Sralph case ' ':
19815113Sralph case '\t': /* skip blanks */
19915113Sralph goto again;
20014920Sralph
20115113Sralph case '=': /* EQUAL */
20215113Sralph return(EQUAL);
20314920Sralph
20415113Sralph case '(': /* LP */
20515113Sralph return(LP);
20614920Sralph
20715113Sralph case ')': /* RP */
20815113Sralph return(RP);
20914920Sralph
21015270Sralph case ';': /* SM */
21115270Sralph return(SM);
21215270Sralph
21315113Sralph case '-': /* -> */
21415113Sralph if ((c = getc(fin)) == '>')
21515113Sralph return(ARROW);
21615113Sralph ungetc(c, fin);
21715113Sralph c = '-';
21815113Sralph break;
21914920Sralph
22015611Sralph case '"': /* STRING */
22115611Sralph cp1 = yytext;
22215611Sralph cp2 = &yytext[INMAX - 1];
22315611Sralph for (;;) {
22415611Sralph if (cp1 >= cp2) {
22515611Sralph yyerror("command string too long\n");
22615611Sralph break;
22715611Sralph }
22815611Sralph c = getc(fin);
22915611Sralph if (c == EOF || c == '"')
23015611Sralph break;
23115611Sralph if (c == '\\') {
23215611Sralph if ((c = getc(fin)) == EOF) {
23315611Sralph *cp1++ = '\\';
23415611Sralph break;
23515611Sralph }
23615611Sralph }
23716295Sralph if (c == '\n') {
23816295Sralph yylineno++;
23915611Sralph c = ' '; /* can't send '\n' */
24016295Sralph }
24115611Sralph *cp1++ = c;
24215611Sralph }
24315611Sralph if (c != '"')
24415611Sralph yyerror("missing closing '\"'\n");
24516027Sralph *cp1 = '\0';
24616027Sralph yylval.string = makestr(yytext);
24715611Sralph return(STRING);
24815611Sralph
24916295Sralph case ':': /* : or :: */
25015113Sralph if ((c = getc(fin)) == ':')
25115113Sralph return(DCOLON);
25215113Sralph ungetc(c, fin);
25316295Sralph return(COLON);
25415113Sralph }
25515113Sralph cp1 = yytext;
25615113Sralph cp2 = &yytext[INMAX - 1];
25715113Sralph for (;;) {
25815113Sralph if (cp1 >= cp2) {
25915611Sralph yyerror("input line too long\n");
26015113Sralph break;
26114920Sralph }
26215113Sralph if (c == '\\') {
26315113Sralph if ((c = getc(fin)) != EOF) {
26415113Sralph if (any(c, quotechars))
26515113Sralph c |= QUOTE;
26615113Sralph } else {
26715113Sralph *cp1++ = '\\';
26814920Sralph break;
26914920Sralph }
27014920Sralph }
27115113Sralph *cp1++ = c;
27215113Sralph c = getc(fin);
27316295Sralph if (c == EOF || any(c, " \"'\t()=;:\n")) {
27415113Sralph ungetc(c, fin);
27515113Sralph break;
27615113Sralph }
27714920Sralph }
27815113Sralph *cp1 = '\0';
27915198Sralph if (yytext[0] == '-' && yytext[2] == '\0') {
28015198Sralph switch (yytext[1]) {
28115292Sralph case 'b':
28215292Sralph yylval.intval = COMPARE;
28315292Sralph return(OPTION);
28415292Sralph
28515611Sralph case 'R':
28615270Sralph yylval.intval = REMOVE;
28715270Sralph return(OPTION);
28815270Sralph
28915198Sralph case 'v':
29015198Sralph yylval.intval = VERIFY;
29115198Sralph return(OPTION);
29215198Sralph
29315198Sralph case 'w':
29415198Sralph yylval.intval = WHOLE;
29515198Sralph return(OPTION);
29615198Sralph
29715198Sralph case 'y':
29815198Sralph yylval.intval = YOUNGER;
29915198Sralph return(OPTION);
30016650Sralph
30116650Sralph case 'h':
30216650Sralph yylval.intval = FOLLOW;
30316650Sralph return(OPTION);
30416650Sralph
30516650Sralph case 'i':
30616650Sralph yylval.intval = IGNLNKS;
30716650Sralph return(OPTION);
30815198Sralph }
30915198Sralph }
31015113Sralph if (!strcmp(yytext, "install"))
31115113Sralph c = INSTALL;
31215113Sralph else if (!strcmp(yytext, "notify"))
31315113Sralph c = NOTIFY;
31415113Sralph else if (!strcmp(yytext, "except"))
31515113Sralph c = EXCEPT;
31617913Sralph else if (!strcmp(yytext, "except_pat"))
31716434Sralph c = PATTERN;
31815611Sralph else if (!strcmp(yytext, "special"))
31915611Sralph c = SPECIAL;
32016027Sralph else {
32116027Sralph yylval.string = makestr(yytext);
32216027Sralph return(NAME);
32316027Sralph }
32416027Sralph yylval.subcmd = makesubcmd(c);
32515113Sralph return(c);
32614920Sralph }
32714920Sralph
32854705Sbostic int
any(c,str)32914920Sralph any(c, str)
33014920Sralph register int c;
33114920Sralph register char *str;
33214920Sralph {
33314920Sralph while (*str)
33414920Sralph if (c == *str++)
33514920Sralph return(1);
33614920Sralph return(0);
33714920Sralph }
33814920Sralph
33914920Sralph /*
34016027Sralph * Insert or append ARROW command to list of hosts to be updated.
34116027Sralph */
34254705Sbostic void
insert(label,files,hosts,subcmds)34316295Sralph insert(label, files, hosts, subcmds)
34416295Sralph char *label;
34516027Sralph struct namelist *files, *hosts;
34616027Sralph struct subcmd *subcmds;
34716027Sralph {
34816027Sralph register struct cmd *c, *prev, *nc;
34916027Sralph register struct namelist *h;
35016027Sralph
35116027Sralph files = expand(files, E_VARS|E_SHELL);
35216027Sralph hosts = expand(hosts, E_ALL);
35316027Sralph for (h = hosts; h != NULL; free(h), h = h->n_next) {
35416027Sralph /*
35516027Sralph * Search command list for an update to the same host.
35616027Sralph */
35716027Sralph for (prev = NULL, c = cmds; c!=NULL; prev = c, c = c->c_next) {
35816027Sralph if (strcmp(c->c_name, h->n_name) == 0) {
35916027Sralph do {
36016027Sralph prev = c;
36116027Sralph c = c->c_next;
36216027Sralph } while (c != NULL &&
36316027Sralph strcmp(c->c_name, h->n_name) == 0);
36416027Sralph break;
36516027Sralph }
36616027Sralph }
36716027Sralph /*
36816027Sralph * Insert new command to update host.
36916027Sralph */
37016027Sralph nc = ALLOC(cmd);
37116027Sralph if (nc == NULL)
37216027Sralph fatal("ran out of memory\n");
37316027Sralph nc->c_type = ARROW;
37416027Sralph nc->c_name = h->n_name;
37516295Sralph nc->c_label = label;
37616027Sralph nc->c_files = files;
37716027Sralph nc->c_cmds = subcmds;
37816027Sralph nc->c_next = c;
37916027Sralph if (prev == NULL)
38016027Sralph cmds = nc;
38116027Sralph else
38216027Sralph prev->c_next = nc;
38316027Sralph /* update last_cmd if appending nc to cmds */
38416027Sralph if (c == NULL)
38516027Sralph last_cmd = nc;
38616027Sralph }
38716027Sralph }
38816027Sralph
38916027Sralph /*
39016027Sralph * Append DCOLON command to the end of the command list since these are always
39116027Sralph * executed in the order they appear in the distfile.
39216027Sralph */
39354705Sbostic void
append(label,files,stamp,subcmds)39416295Sralph append(label, files, stamp, subcmds)
39516295Sralph char *label;
39616027Sralph struct namelist *files;
39716027Sralph char *stamp;
39816027Sralph struct subcmd *subcmds;
39916027Sralph {
40016027Sralph register struct cmd *c;
40116027Sralph
40216027Sralph c = ALLOC(cmd);
40316027Sralph if (c == NULL)
40416027Sralph fatal("ran out of memory\n");
40516027Sralph c->c_type = DCOLON;
40616027Sralph c->c_name = stamp;
40716295Sralph c->c_label = label;
40816027Sralph c->c_files = expand(files, E_ALL);
40916027Sralph c->c_cmds = subcmds;
41016027Sralph c->c_next = NULL;
41116027Sralph if (cmds == NULL)
41216027Sralph cmds = last_cmd = c;
41316027Sralph else {
41416027Sralph last_cmd->c_next = c;
41516027Sralph last_cmd = c;
41616027Sralph }
41716027Sralph }
41816027Sralph
41916027Sralph /*
42014920Sralph * Error printing routine in parser.
42114920Sralph */
42254705Sbostic void
yyerror(s)42314920Sralph yyerror(s)
42414920Sralph char *s;
42514920Sralph {
42654705Sbostic ++nerrs;
42715292Sralph fflush(stdout);
42814920Sralph fprintf(stderr, "rdist: line %d: %s\n", yylineno, s);
42914920Sralph }
43016027Sralph
43116027Sralph /*
43216027Sralph * Return a copy of the string.
43316027Sralph */
43454705Sbostic static char *
makestr(str)43516027Sralph makestr(str)
43616027Sralph char *str;
43716027Sralph {
43816027Sralph register char *cp, *s;
43916027Sralph
44016027Sralph str = cp = malloc(strlen(s = str) + 1);
44116027Sralph if (cp == NULL)
44216027Sralph fatal("ran out of memory\n");
44316027Sralph while (*cp++ = *s++)
44416027Sralph ;
44516027Sralph return(str);
44616027Sralph }
44716027Sralph
44816027Sralph /*
44916027Sralph * Allocate a namelist structure.
45016027Sralph */
45116027Sralph struct namelist *
makenl(name)45216027Sralph makenl(name)
45316027Sralph char *name;
45416027Sralph {
45516027Sralph register struct namelist *nl;
45616027Sralph
45716027Sralph nl = ALLOC(namelist);
45816027Sralph if (nl == NULL)
45916027Sralph fatal("ran out of memory\n");
46016027Sralph nl->n_name = name;
46116027Sralph nl->n_next = NULL;
46216027Sralph return(nl);
46316027Sralph }
46416027Sralph
46516027Sralph /*
46616027Sralph * Make a sub command for lists of variables, commands, etc.
46716027Sralph */
46816027Sralph struct subcmd *
makesubcmd(type)46954705Sbostic makesubcmd(type)
47016027Sralph int type;
47116027Sralph {
47216027Sralph register struct subcmd *sc;
47316027Sralph
47416027Sralph sc = ALLOC(subcmd);
47516027Sralph if (sc == NULL)
47616027Sralph fatal("ran out of memory\n");
47716027Sralph sc->sc_type = type;
47816027Sralph sc->sc_args = NULL;
47916027Sralph sc->sc_next = NULL;
48016027Sralph sc->sc_name = NULL;
48116027Sralph return(sc);
48216027Sralph }
483