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