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