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