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