|
|
1.1 root 1: %{
2: /*
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
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.
17: */
18:
19: #ifndef lint
20: static char sccsid[] = "@(#)gram.y 5.4 (Berkeley) 6/29/88";
21: #endif /* not lint */
22:
23: #include "defs.h"
24:
25: struct cmd *cmds = NULL;
26: struct cmd *last_cmd;
27: struct namelist *last_n;
28: struct subcmd *last_sc;
29:
30: %}
31:
32: %term EQUAL 1
33: %term LP 2
34: %term RP 3
35: %term SM 4
36: %term ARROW 5
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
44: %term PATTERN 13
45: %term SPECIAL 14
46: %term OPTION 15
47:
48: %union {
49: int intval;
50: char *string;
51: struct subcmd *subcmd;
52: struct namelist *namel;
53: }
54:
55: %type <intval> OPTION, options
56: %type <string> NAME, STRING
57: %type <subcmd> INSTALL, NOTIFY, EXCEPT, PATTERN, SPECIAL, cmdlist, cmd
58: %type <namel> namelist, names, opt_namelist
59:
60: %%
61:
62: file: /* VOID */
63: | file command
64: ;
65:
66: command: NAME EQUAL namelist = {
67: (void) lookup($1, INSERT, $3);
68: }
69: | namelist ARROW namelist cmdlist = {
70: insert(NULL, $1, $3, $4);
71: }
72: | NAME COLON namelist ARROW namelist cmdlist = {
73: insert($1, $3, $5, $6);
74: }
75: | namelist DCOLON NAME cmdlist = {
76: append(NULL, $1, $3, $4);
77: }
78: | NAME COLON namelist DCOLON NAME cmdlist = {
79: append($1, $3, $5, $6);
80: }
81: | error
82: ;
83:
84: namelist: NAME = {
85: $$ = makenl($1);
86: }
87: | LP names RP = {
88: $$ = $2;
89: }
90: ;
91:
92: names: /* VOID */ {
93: $$ = last_n = NULL;
94: }
95: | names NAME = {
96: if (last_n == NULL)
97: $$ = last_n = makenl($2);
98: else {
99: last_n->n_next = makenl($2);
100: last_n = last_n->n_next;
101: $$ = $1;
102: }
103: }
104: ;
105:
106: cmdlist: /* VOID */ {
107: $$ = last_sc = NULL;
108: }
109: | cmdlist cmd = {
110: if (last_sc == NULL)
111: $$ = last_sc = $2;
112: else {
113: last_sc->sc_next = $2;
114: last_sc = $2;
115: $$ = $1;
116: }
117: }
118: ;
119:
120: cmd: INSTALL options opt_namelist SM = {
121: register struct namelist *nl;
122:
123: $1->sc_options = $2 | options;
124: if ($3 != NULL) {
125: nl = expand($3, E_VARS);
126: if (nl->n_next != NULL)
127: yyerror("only one name allowed\n");
128: $1->sc_name = nl->n_name;
129: free(nl);
130: }
131: $$ = $1;
132: }
133: | NOTIFY namelist SM = {
134: if ($2 != NULL)
135: $1->sc_args = expand($2, E_VARS);
136: $$ = $1;
137: }
138: | EXCEPT namelist SM = {
139: if ($2 != NULL)
140: $1->sc_args = expand($2, E_ALL);
141: $$ = $1;
142: }
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);
150: $1->sc_args = expand($2, E_VARS);
151: $$ = $1;
152: }
153: | SPECIAL opt_namelist STRING SM = {
154: if ($2 != NULL)
155: $1->sc_args = expand($2, E_ALL);
156: $1->sc_name = $3;
157: $$ = $1;
158: }
159: ;
160:
161: options: /* VOID */ = {
162: $$ = 0;
163: }
164: | options OPTION = {
165: $$ |= $2;
166: }
167: ;
168:
169: opt_namelist: /* VOID */ = {
170: $$ = NULL;
171: }
172: | namelist = {
173: $$ = $1;
174: }
175: ;
176:
177: %%
178:
179: int yylineno = 1;
180: extern FILE *fin;
181:
182: yylex()
183: {
184: static char yytext[INMAX];
185: register int c;
186: register char *cp1, *cp2;
187: static char quotechars[] = "[]{}*?$";
188:
189: again:
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)
198: return(0);
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:
214: case ';': /* SM */
215: return(SM);
216:
217: case '-': /* -> */
218: if ((c = getc(fin)) == '>')
219: return(ARROW);
220: ungetc(c, fin);
221: c = '-';
222: break;
223:
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: }
241: if (c == '\n') {
242: yylineno++;
243: c = ' '; /* can't send '\n' */
244: }
245: *cp1++ = c;
246: }
247: if (c != '"')
248: yyerror("missing closing '\"'\n");
249: *cp1 = '\0';
250: yylval.string = makestr(yytext);
251: return(STRING);
252:
253: case ':': /* : or :: */
254: if ((c = getc(fin)) == ':')
255: return(DCOLON);
256: ungetc(c, fin);
257: return(COLON);
258: }
259: cp1 = yytext;
260: cp2 = &yytext[INMAX - 1];
261: for (;;) {
262: if (cp1 >= cp2) {
263: yyerror("input line too long\n");
264: break;
265: }
266: if (c == '\\') {
267: if ((c = getc(fin)) != EOF) {
268: if (any(c, quotechars))
269: c |= QUOTE;
270: } else {
271: *cp1++ = '\\';
272: break;
273: }
274: }
275: *cp1++ = c;
276: c = getc(fin);
277: if (c == EOF || any(c, " \"'\t()=;:\n")) {
278: ungetc(c, fin);
279: break;
280: }
281: }
282: *cp1 = '\0';
283: if (yytext[0] == '-' && yytext[2] == '\0') {
284: switch (yytext[1]) {
285: case 'b':
286: yylval.intval = COMPARE;
287: return(OPTION);
288:
289: case 'R':
290: yylval.intval = REMOVE;
291: return(OPTION);
292:
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);
304:
305: case 'h':
306: yylval.intval = FOLLOW;
307: return(OPTION);
308:
309: case 'i':
310: yylval.intval = IGNLNKS;
311: return(OPTION);
312: }
313: }
314: if (!strcmp(yytext, "install"))
315: c = INSTALL;
316: else if (!strcmp(yytext, "notify"))
317: c = NOTIFY;
318: else if (!strcmp(yytext, "except"))
319: c = EXCEPT;
320: else if (!strcmp(yytext, "except_pat"))
321: c = PATTERN;
322: else if (!strcmp(yytext, "special"))
323: c = SPECIAL;
324: else {
325: yylval.string = makestr(yytext);
326: return(NAME);
327: }
328: yylval.subcmd = makesubcmd(c);
329: return(c);
330: }
331:
332: any(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:
342: /*
343: * Insert or append ARROW command to list of hosts to be updated.
344: */
345: insert(label, files, hosts, subcmds)
346: char *label;
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;
377: nc->c_label = label;
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: */
395: append(label, files, stamp, subcmds)
396: char *label;
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;
408: c->c_label = label;
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:
420: /*
421: * Error printing routine in parser.
422: */
423: yyerror(s)
424: char *s;
425: {
426: extern int yychar;
427:
428: nerrs++;
429: fflush(stdout);
430: fprintf(stderr, "rdist: line %d: %s\n", yylineno, s);
431: }
432:
433: /*
434: * Return a copy of the string.
435: */
436: char *
437: makestr(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: */
453: struct namelist *
454: makenl(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: */
470: struct subcmd *
471: makesubcmd(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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.