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