usched: Allow process to change self cpu affinity
[dragonfly.git] / usr.bin / rdist / gram.y
blob82e5f56562de02cc3e96e447194af57e2203d486
1 %{
2 /*
3 * Copyright (c) 1983, 1993
4 * The Regents of the University of California. All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of the University nor the names of its contributors
15 * may be used to endorse or promote products derived from this software
16 * without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
30 * @(#)gram.y 8.1 (Berkeley) 6/9/93
31 * $FreeBSD: src/usr.bin/rdist/gram.y,v 1.6 1999/08/28 01:05:07 peter Exp $
32 * $DragonFly: src/usr.bin/rdist/gram.y,v 1.5 2008/10/16 01:52:33 swildner Exp $
35 #include <sys/types.h>
37 #include <limits.h>
38 #include <regex.h>
40 #include "defs.h"
42 struct cmd *cmds = NULL;
43 struct cmd *last_cmd;
44 struct namelist *last_n;
45 struct subcmd *last_sc;
47 static char *makestr(char *);
51 %term EQUAL 1
52 %term LP 2
53 %term RP 3
54 %term SM 4
55 %term ARROW 5
56 %term COLON 6
57 %term DCOLON 7
58 %term NAME 8
59 %term STRING 9
60 %term INSTALL 10
61 %term NOTIFY 11
62 %term EXCEPT 12
63 %term PATTERN 13
64 %term SPECIAL 14
65 %term OPTION 15
67 %union {
68 int intval;
69 char *string;
70 struct subcmd *subcmd;
71 struct namelist *namel;
74 %type <intval> OPTION, options
75 %type <string> NAME, STRING
76 %type <subcmd> INSTALL, NOTIFY, EXCEPT, PATTERN, SPECIAL, cmdlist, cmd
77 %type <namel> namelist, names, opt_namelist
81 file: /* VOID */
82 | file command
85 command: NAME EQUAL namelist = {
86 (void) lookup($1, INSERT, $3);
88 | namelist ARROW namelist cmdlist = {
89 insert(NULL, $1, $3, $4);
91 | NAME COLON namelist ARROW namelist cmdlist = {
92 insert($1, $3, $5, $6);
94 | namelist DCOLON NAME cmdlist = {
95 append(NULL, $1, $3, $4);
97 | NAME COLON namelist DCOLON NAME cmdlist = {
98 append($1, $3, $5, $6);
100 | error
103 namelist: NAME = {
104 $$ = makenl($1);
106 | LP names RP = {
107 $$ = $2;
111 names: /* VOID */ {
112 $$ = last_n = NULL;
114 | names NAME = {
115 if (last_n == NULL)
116 $$ = last_n = makenl($2);
117 else {
118 last_n->n_next = makenl($2);
119 last_n = last_n->n_next;
120 $$ = $1;
125 cmdlist: /* VOID */ {
126 $$ = last_sc = NULL;
128 | cmdlist cmd = {
129 if (last_sc == NULL)
130 $$ = last_sc = $2;
131 else {
132 last_sc->sc_next = $2;
133 last_sc = $2;
134 $$ = $1;
139 cmd: INSTALL options opt_namelist SM = {
140 struct namelist *nl;
142 $1->sc_options = $2 | options;
143 if ($3 != NULL) {
144 nl = expand($3, E_VARS);
145 if (nl) {
146 if (nl->n_next != NULL)
147 yyerror("only one name allowed\n");
148 $1->sc_name = nl->n_name;
149 free(nl);
150 } else
151 $1->sc_name = NULL;
153 $$ = $1;
155 | NOTIFY namelist SM = {
156 if ($2 != NULL)
157 $1->sc_args = expand($2, E_VARS);
158 $$ = $1;
160 | EXCEPT namelist SM = {
161 if ($2 != NULL)
162 $1->sc_args = expand($2, E_ALL);
163 $$ = $1;
165 | PATTERN namelist SM = {
166 struct namelist *nl;
167 regex_t rx;
168 int val;
169 char errbuf[_POSIX2_LINE_MAX];
171 for (nl = $2; nl != NULL; nl = nl->n_next) {
172 if ((val = regcomp(&rx, nl->n_name,
173 REG_EXTENDED))) {
174 regerror(val, &rx, errbuf,
175 sizeof errbuf);
176 yyerror(errbuf);
178 regfree(&rx);
180 $1->sc_args = expand($2, E_VARS);
181 $$ = $1;
183 | SPECIAL opt_namelist STRING SM = {
184 if ($2 != NULL)
185 $1->sc_args = expand($2, E_ALL);
186 $1->sc_name = $3;
187 $$ = $1;
191 options: /* VOID */ = {
192 $$ = 0;
194 | options OPTION = {
195 $$ |= $2;
199 opt_namelist: /* VOID */ = {
200 $$ = NULL;
202 | namelist = {
203 $$ = $1;
209 int yylineno = 1;
210 extern FILE *fin;
213 yylex(void)
215 static char yytext[INMAX];
216 int c;
217 char *cp1, *cp2;
218 static char quotechars[] = "[]{}*?$";
220 again:
221 switch (c = getc(fin)) {
222 case EOF: /* end of file */
223 return(0);
225 case '#': /* start of comment */
226 while ((c = getc(fin)) != EOF && c != '\n')
228 if (c == EOF)
229 return(0);
230 case '\n':
231 yylineno++;
232 case ' ':
233 case '\t': /* skip blanks */
234 goto again;
236 case '=': /* EQUAL */
237 return(EQUAL);
239 case '(': /* LP */
240 return(LP);
242 case ')': /* RP */
243 return(RP);
245 case ';': /* SM */
246 return(SM);
248 case '-': /* -> */
249 if ((c = getc(fin)) == '>')
250 return(ARROW);
251 ungetc(c, fin);
252 c = '-';
253 break;
255 case '"': /* STRING */
256 cp1 = yytext;
257 cp2 = &yytext[INMAX - 1];
258 for (;;) {
259 if (cp1 >= cp2) {
260 yyerror("command string too long\n");
261 break;
263 c = getc(fin);
264 if (c == EOF || c == '"')
265 break;
266 if (c == '\\') {
267 if ((c = getc(fin)) == EOF) {
268 *cp1++ = '\\';
269 break;
272 if (c == '\n') {
273 yylineno++;
274 c = ' '; /* can't send '\n' */
276 *cp1++ = c;
278 if (c != '"')
279 yyerror("missing closing '\"'\n");
280 *cp1 = '\0';
281 yylval.string = makestr(yytext);
282 return(STRING);
284 case ':': /* : or :: */
285 if ((c = getc(fin)) == ':')
286 return(DCOLON);
287 ungetc(c, fin);
288 return(COLON);
290 cp1 = yytext;
291 cp2 = &yytext[INMAX - 1];
292 for (;;) {
293 if (cp1 >= cp2) {
294 yyerror("input line too long\n");
295 break;
297 if (c == '\\') {
298 if ((c = getc(fin)) != EOF) {
299 if (any(c, quotechars))
300 c |= QUOTE;
301 } else {
302 *cp1++ = '\\';
303 break;
306 *cp1++ = c;
307 c = getc(fin);
308 if (c == EOF || any(c, " \"'\t()=;:\n")) {
309 ungetc(c, fin);
310 break;
313 *cp1 = '\0';
314 if (yytext[0] == '-' && yytext[2] == '\0') {
315 switch (yytext[1]) {
316 case 'b':
317 yylval.intval = COMPARE;
318 return(OPTION);
320 case 'R':
321 yylval.intval = REMOVE;
322 return(OPTION);
324 case 'v':
325 yylval.intval = VERIFY;
326 return(OPTION);
328 case 'w':
329 yylval.intval = WHOLE;
330 return(OPTION);
332 case 'y':
333 yylval.intval = YOUNGER;
334 return(OPTION);
336 case 'h':
337 yylval.intval = FOLLOW;
338 return(OPTION);
340 case 'i':
341 yylval.intval = IGNLNKS;
342 return(OPTION);
345 if (!strcmp(yytext, "install"))
346 c = INSTALL;
347 else if (!strcmp(yytext, "notify"))
348 c = NOTIFY;
349 else if (!strcmp(yytext, "except"))
350 c = EXCEPT;
351 else if (!strcmp(yytext, "except_pat"))
352 c = PATTERN;
353 else if (!strcmp(yytext, "special"))
354 c = SPECIAL;
355 else {
356 yylval.string = makestr(yytext);
357 return(NAME);
359 yylval.subcmd = makesubcmd(c);
360 return(c);
364 any(int c, char *str)
366 while (*str)
367 if (c == *str++)
368 return(1);
369 return(0);
373 * Insert or append ARROW command to list of hosts to be updated.
375 void
376 insert(char *label, struct namelist *files, struct namelist *hosts, struct subcmd *subcmds)
378 struct cmd *c, *prev, *nc;
379 struct namelist *h, *next_h;
381 files = expand(files, E_VARS|E_SHELL);
382 hosts = expand(hosts, E_ALL);
383 for (h = hosts; h != NULL; next_h = h->n_next, free(h), h = next_h) {
385 * Search command list for an update to the same host.
387 for (prev = NULL, c = cmds; c!=NULL; prev = c, c = c->c_next) {
388 if (strcmp(c->c_name, h->n_name) == 0) {
389 do {
390 prev = c;
391 c = c->c_next;
392 } while (c != NULL &&
393 strcmp(c->c_name, h->n_name) == 0);
394 break;
398 * Insert new command to update host.
400 nc = ALLOC(cmd);
401 if (nc == NULL)
402 fatal("ran out of memory\n");
403 nc->c_type = ARROW;
404 nc->c_name = h->n_name;
405 nc->c_label = label;
406 nc->c_files = files;
407 nc->c_cmds = subcmds;
408 nc->c_next = c;
409 if (prev == NULL)
410 cmds = nc;
411 else
412 prev->c_next = nc;
413 /* update last_cmd if appending nc to cmds */
414 if (c == NULL)
415 last_cmd = nc;
420 * Append DCOLON command to the end of the command list since these are always
421 * executed in the order they appear in the distfile.
423 void
424 append(char *label, struct namelist *files, char *stamp, struct subcmd *subcmds)
426 struct cmd *c;
428 c = ALLOC(cmd);
429 if (c == NULL)
430 fatal("ran out of memory\n");
431 c->c_type = DCOLON;
432 c->c_name = stamp;
433 c->c_label = label;
434 c->c_files = expand(files, E_ALL);
435 c->c_cmds = subcmds;
436 c->c_next = NULL;
437 if (cmds == NULL)
438 cmds = last_cmd = c;
439 else {
440 last_cmd->c_next = c;
441 last_cmd = c;
446 * Error printing routine in parser.
448 void
449 yyerror(char *s)
451 ++nerrs;
452 fflush(stdout);
453 fprintf(stderr, "rdist: line %d: %s\n", yylineno, s);
457 * Return a copy of the string.
459 static char *
460 makestr(char *str)
462 char *cp, *s;
464 str = cp = malloc(strlen(s = str) + 1);
465 if (cp == NULL)
466 fatal("ran out of memory\n");
467 while ((*cp++ = *s++))
469 return(str);
473 * Allocate a namelist structure.
475 struct namelist *
476 makenl(char *name)
478 struct namelist *nl;
480 nl = ALLOC(namelist);
481 if (nl == NULL)
482 fatal("ran out of memory\n");
483 nl->n_name = name;
484 nl->n_next = NULL;
485 return(nl);
489 * Make a sub command for lists of variables, commands, etc.
491 struct subcmd *
492 makesubcmd(int type)
494 struct subcmd *sc;
496 sc = ALLOC(subcmd);
497 if (sc == NULL)
498 fatal("ran out of memory\n");
499 sc->sc_type = type;
500 sc->sc_args = NULL;
501 sc->sc_next = NULL;
502 sc->sc_name = NULL;
503 return(sc);