xref: /csrg-svn/usr.bin/rdist/gram.y (revision 63070)
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