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