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