|
|
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.