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