|
|
1.1 root 1: %{
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:
8: #ifndef lint
9: static char *sccsid = "@(#)gram.y 5.2 (Berkeley) 85/06/21";
10: #endif
11:
12: #include "defs.h"
13:
14: struct cmd *cmds = NULL;
15: struct cmd *last_cmd;
16: struct namelist *last_n;
17: struct subcmd *last_sc;
18:
19: %}
20:
21: %term EQUAL 1
22: %term LP 2
23: %term RP 3
24: %term SM 4
25: %term ARROW 5
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
33: %term PATTERN 13
34: %term SPECIAL 14
35: %term OPTION 15
36:
37: %union {
38: int intval;
39: char *string;
40: struct subcmd *subcmd;
41: struct namelist *namel;
42: }
43:
44: %type <intval> OPTION, options
45: %type <string> NAME, STRING
46: %type <subcmd> INSTALL, NOTIFY, EXCEPT, PATTERN, SPECIAL, cmdlist, cmd
47: %type <namel> namelist, names, opt_namelist
48:
49: %%
50:
51: file: /* VOID */
52: | file command
53: ;
54:
55: command: NAME EQUAL namelist = {
56: (void) lookup($1, INSERT, $3);
57: }
58: | namelist ARROW namelist cmdlist = {
59: insert(NULL, $1, $3, $4);
60: }
61: | NAME COLON namelist ARROW namelist cmdlist = {
62: insert($1, $3, $5, $6);
63: }
64: | namelist DCOLON NAME cmdlist = {
65: append(NULL, $1, $3, $4);
66: }
67: | NAME COLON namelist DCOLON NAME cmdlist = {
68: append($1, $3, $5, $6);
69: }
70: | error
71: ;
72:
73: namelist: NAME = {
74: $$ = makenl($1);
75: }
76: | LP names RP = {
77: $$ = $2;
78: }
79: ;
80:
81: names: /* VOID */ {
82: $$ = last_n = NULL;
83: }
84: | names NAME = {
85: if (last_n == NULL)
86: $$ = last_n = makenl($2);
87: else {
88: last_n->n_next = makenl($2);
89: last_n = last_n->n_next;
90: $$ = $1;
91: }
92: }
93: ;
94:
95: cmdlist: /* VOID */ {
96: $$ = last_sc = NULL;
97: }
98: | cmdlist cmd = {
99: if (last_sc == NULL)
100: $$ = last_sc = $2;
101: else {
102: last_sc->sc_next = $2;
103: last_sc = $2;
104: $$ = $1;
105: }
106: }
107: ;
108:
109: cmd: INSTALL options opt_namelist SM = {
110: register struct namelist *nl;
111:
112: $1->sc_options = $2 | options;
113: if ($3 != NULL) {
114: nl = expand($3, E_VARS);
115: if (nl->n_next != NULL)
116: yyerror("only one name allowed\n");
117: $1->sc_name = nl->n_name;
118: free(nl);
119: }
120: $$ = $1;
121: }
122: | NOTIFY namelist SM = {
123: if ($2 != NULL)
124: $1->sc_args = expand($2, E_VARS);
125: $$ = $1;
126: }
127: | EXCEPT namelist SM = {
128: if ($2 != NULL)
129: $1->sc_args = expand($2, E_ALL);
130: $$ = $1;
131: }
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);
139: $1->sc_args = expand($2, E_VARS);
140: $$ = $1;
141: }
142: | SPECIAL opt_namelist STRING SM = {
143: if ($2 != NULL)
144: $1->sc_args = expand($2, E_ALL);
145: $1->sc_name = $3;
146: $$ = $1;
147: }
148: ;
149:
150: options: /* VOID */ = {
151: $$ = 0;
152: }
153: | options OPTION = {
154: $$ |= $2;
155: }
156: ;
157:
158: opt_namelist: /* VOID */ = {
159: $$ = NULL;
160: }
161: | namelist = {
162: $$ = $1;
163: }
164: ;
165:
166: %%
167:
168: int yylineno = 1;
169: extern FILE *fin;
170:
171: yylex()
172: {
173: static char yytext[INMAX];
174: register int c;
175: register char *cp1, *cp2;
176: static char quotechars[] = "[]{}*?$";
177:
178: again:
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)
187: return(0);
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:
203: case ';': /* SM */
204: return(SM);
205:
206: case '-': /* -> */
207: if ((c = getc(fin)) == '>')
208: return(ARROW);
209: ungetc(c, fin);
210: c = '-';
211: break;
212:
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: }
230: if (c == '\n') {
231: yylineno++;
232: c = ' '; /* can't send '\n' */
233: }
234: *cp1++ = c;
235: }
236: if (c != '"')
237: yyerror("missing closing '\"'\n");
238: *cp1 = '\0';
239: yylval.string = makestr(yytext);
240: return(STRING);
241:
242: case ':': /* : or :: */
243: if ((c = getc(fin)) == ':')
244: return(DCOLON);
245: ungetc(c, fin);
246: return(COLON);
247: }
248: cp1 = yytext;
249: cp2 = &yytext[INMAX - 1];
250: for (;;) {
251: if (cp1 >= cp2) {
252: yyerror("input line too long\n");
253: break;
254: }
255: if (c == '\\') {
256: if ((c = getc(fin)) != EOF) {
257: if (any(c, quotechars))
258: c |= QUOTE;
259: } else {
260: *cp1++ = '\\';
261: break;
262: }
263: }
264: *cp1++ = c;
265: c = getc(fin);
266: if (c == EOF || any(c, " \"'\t()=;:\n")) {
267: ungetc(c, fin);
268: break;
269: }
270: }
271: *cp1 = '\0';
272: if (yytext[0] == '-' && yytext[2] == '\0') {
273: switch (yytext[1]) {
274: case 'b':
275: yylval.intval = COMPARE;
276: return(OPTION);
277:
278: case 'R':
279: yylval.intval = REMOVE;
280: return(OPTION);
281:
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);
293:
294: case 'h':
295: yylval.intval = FOLLOW;
296: return(OPTION);
297:
298: case 'i':
299: yylval.intval = IGNLNKS;
300: return(OPTION);
301: }
302: }
303: if (!strcmp(yytext, "install"))
304: c = INSTALL;
305: else if (!strcmp(yytext, "notify"))
306: c = NOTIFY;
307: else if (!strcmp(yytext, "except"))
308: c = EXCEPT;
309: else if (!strcmp(yytext, "except_pat"))
310: c = PATTERN;
311: else if (!strcmp(yytext, "special"))
312: c = SPECIAL;
313: else {
314: yylval.string = makestr(yytext);
315: return(NAME);
316: }
317: yylval.subcmd = makesubcmd(c);
318: return(c);
319: }
320:
321: any(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:
331: /*
332: * Insert or append ARROW command to list of hosts to be updated.
333: */
334: insert(label, files, hosts, subcmds)
335: char *label;
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;
366: nc->c_label = label;
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: */
384: append(label, files, stamp, subcmds)
385: char *label;
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;
397: c->c_label = label;
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:
409: /*
410: * Error printing routine in parser.
411: */
412: yyerror(s)
413: char *s;
414: {
415: extern int yychar;
416:
417: nerrs++;
418: fflush(stdout);
419: fprintf(stderr, "rdist: line %d: %s\n", yylineno, s);
420: }
421:
422: /*
423: * Return a copy of the string.
424: */
425: char *
426: makestr(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: */
442: struct namelist *
443: makenl(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: */
459: struct subcmd *
460: makesubcmd(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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.