|
|
1.1 ! root 1: /* ! 2: * sh/sh.y ! 3: * The Bourne shell. ! 4: * This shell is dedicated to Ciaran Gerald Aidan O'Donnell. ! 5: * May he live a thousand minutes (long enough to fix up YACC). ! 6: * It is also dedicated to Steve Bourne. ! 7: * May he live a thousand seconds. ! 8: */ ! 9: %{ ! 10: #include "sh.h" ! 11: ! 12: #define YYERROR { yyerrflag=1; goto YYerract; } ! 13: ! 14: extern NODE *node(); ! 15: %} ! 16: ! 17: %union { ! 18: NODE *yu_node; ! 19: char *yu_strp; ! 20: int yu_nval; ! 21: } ! 22: ! 23: %token _ANDF ! 24: %token _ASGN ! 25: %token _CASE ! 26: %token _CBRAC ! 27: %token _DO ! 28: %token _DONE ! 29: %token _DSEMI ! 30: %token _ELIF ! 31: %token _ELSE ! 32: %token _ESAC ! 33: %token _FI ! 34: %token _FOR ! 35: %token _IF ! 36: %token _IN ! 37: %token _IORS ! 38: %token _NAME ! 39: %token _NULL ! 40: %token _OBRAC ! 41: %token _ORF ! 42: %token _THEN ! 43: %token _UNTIL ! 44: %token _WHILE ! 45: ! 46: %type <yu_node> arg arg_list case_line case_list ! 47: %type <yu_node> cmd cmd_line cmd_list cmd_seq ! 48: %type <yu_node> control do_list else_part in_name_list ! 49: %type <yu_node> logical_cmd name_list opt_cmd_seq pattern_list ! 50: %type <yu_node> pipe_cmd sub_shell ! 51: ! 52: %type <yu_strp> asgn name redirect ! 53: ! 54: %type <yu_nval> whuntile ! 55: ! 56: %% ! 57: ! 58: session: ! 59: session cmd_line ! 60: | ! 61: ; ! 62: ! 63: cmd_line: ! 64: '\n' { ! 65: sesp->s_node = NULL; ! 66: reset(RCMD); ! 67: NOTREACHED; ! 68: } ! 69: | ! 70: cmd_list '\n' { ! 71: sesp->s_node = $1; ! 72: reset(errflag ? RERR : RCMD); ! 73: NOTREACHED; ! 74: } ! 75: | error '\n' { ! 76: keyflush(); ! 77: keyflag = 1; ! 78: reset(RERR); ! 79: NOTREACHED; ! 80: } ! 81: ; ! 82: ! 83: if: _IF optnls ; ! 84: ! 85: then: _THEN optnls ; ! 86: ! 87: elif: _ELIF optnls ; ! 88: ! 89: else: _ELSE optnls ; ! 90: ! 91: whuntile: _WHILE optnls { $$ = NWHILE; } ! 92: | _UNTIL optnls { $$ = NUNTIL; } ! 93: ; ! 94: ! 95: do: _DO optnls | _DO ';' optnls ; ! 96: ! 97: in: _IN | _IN sep ; ! 98: ! 99: oror: _ORF optnls; ! 100: ! 101: andand: _ANDF optnls; ! 102: ! 103: or: '|' optnls; ! 104: ! 105: oparen: '(' optnls ; ! 106: ! 107: obrack: _OBRAC optnls ; ! 108: ! 109: cparen: ')' optnls ; ! 110: ! 111: dsemi: _DSEMI optnls ; ! 112: ! 113: cmd_list: ! 114: logical_cmd { ! 115: $$ = $1; ! 116: } ! 117: | logical_cmd '&' { ! 118: $$ = node(NBACK, $1, NULL); ! 119: } ! 120: | logical_cmd ';' { ! 121: $$ = $1; ! 122: } ! 123: | logical_cmd '&' cmd_list { ! 124: $$ = node(NBACK, $1, $3); ! 125: } ! 126: | logical_cmd ';' cmd_list { ! 127: $$ = node(NLIST, $1, $3); ! 128: } ! 129: ; ! 130: ! 131: logical_cmd: ! 132: pipe_cmd { ! 133: $$ = $1; ! 134: } ! 135: | pipe_cmd oror logical_cmd { ! 136: $$ = node(NORF, $1, $3); ! 137: } ! 138: | pipe_cmd andand logical_cmd { ! 139: $$ = node(NANDF, $1, $3); ! 140: } ! 141: ; ! 142: ! 143: pipe_cmd: ! 144: cmd or pipe_cmd { ! 145: $$ = node(NPIPE, $1, $3); ! 146: } ! 147: | cmd { ! 148: $$ = $1; ! 149: } ! 150: ; ! 151: ! 152: cmd: ! 153: arg_list_init arg_list { ! 154: $$ = node(NCOMS, $2, NULL); ! 155: keypop(); ! 156: } ! 157: ; ! 158: ! 159: arg_list_init: ! 160: { ! 161: keypush(); ! 162: keyflag = 1; ! 163: } ! 164: ; ! 165: ! 166: arg_list: ! 167: arg arg_list { ! 168: if (($1->n_type == NCTRL && $2->n_type == NARGS) ! 169: || ($1->n_type == NARGS && $2->n_type == NCTRL)) { ! 170: YYERROR; ! 171: } ! 172: ($$ = $1)->n_next = $2; ! 173: } ! 174: | arg { ! 175: $$ = $1; ! 176: } ! 177: ; ! 178: ! 179: arg: ! 180: redirect { ! 181: $$ = node(NIORS, $1, NULL); ! 182: } ! 183: | name { ! 184: $$ = node(NARGS, $1, NULL); ! 185: keyflag = 0; ! 186: } ! 187: | asgn { ! 188: $$ = node(NASSG, $1, NULL); ! 189: } ! 190: | control { ! 191: if (!keyflag) { ! 192: YYERROR; ! 193: } ! 194: $$ = node(NCTRL, $1, NULL); ! 195: keyflag = 0; ! 196: } ! 197: ; ! 198: ! 199: redirect: _IORS { ! 200: $$ = duplstr(strt, 0); ! 201: } ! 202: ; ! 203: ! 204: name: _NAME { ! 205: $$ = duplstr(strt, 0); ! 206: } ! 207: ; ! 208: ! 209: asgn: _ASGN { ! 210: $$ = duplstr(strt, 0); ! 211: } ! 212: ; ! 213: ! 214: control: ! 215: _FOR name in_name_list sep do_list _DONE { ! 216: $$ = node(NFOR, $2, node(NFOR2, $3, node(NLIST, $5, NULL))); ! 217: $$->n_next->n_next->n_next = $$->n_next; ! 218: } ! 219: | _FOR name in_name_list do_list _DONE { ! 220: $$ = node(NFOR, $2, node(NFOR2, $3, node(NLIST, $4, NULL))); ! 221: $$->n_next->n_next->n_next = $$->n_next; ! 222: } ! 223: | _CASE name sep in case_list _ESAC { ! 224: $$ = node(NCASE, $2, $5); ! 225: } ! 226: | _CASE name in case_list _ESAC { ! 227: $$ = node(NCASE, $2, $4); ! 228: } ! 229: | whuntile cmd_seq do_list _DONE { ! 230: $$ = node($1, $2, node(NLIST, $3, NULL)); ! 231: $$->n_next->n_next = $$; ! 232: } ! 233: | if cmd_seq then opt_cmd_seq else_part _FI { ! 234: $$ = node(NIF, node(NNULL, $2, $4), $5); ! 235: } ! 236: | oparen opt_cmd_seq ')' { ! 237: $$ = node(NPARN, $2, NULL); ! 238: } ! 239: | obrack opt_cmd_seq _CBRAC { ! 240: $$ = node(NBRAC, $2, NULL); ! 241: } ! 242: ; ! 243: ! 244: in_name_list: ! 245: _IN name_list { ! 246: $$ = $2; ! 247: } ! 248: | { ! 249: $$ = node(NARGS, "\"$@\"", NULL); ! 250: } ! 251: ; ! 252: ! 253: name_list: ! 254: name name_list { ! 255: $$ = node(NARGS, $1, $2); ! 256: } ! 257: | { ! 258: $$ = NULL; ! 259: } ! 260: ; ! 261: ! 262: case_list: ! 263: case_line dsemi case_list { ! 264: register NODE *np; ! 265: ! 266: for (np=$1; np->n_next; np=np->n_next) ! 267: ; ! 268: np->n_next = $3; ! 269: $$ = $1; ! 270: } ! 271: | case_line { ! 272: $$ = $1; ! 273: } ! 274: | { ! 275: $$ = NULL; ! 276: } ! 277: ; ! 278: ! 279: case_line: ! 280: pattern_list cparen opt_cmd_seq { ! 281: $$ = node(NCASE2, $3, $1); ! 282: } ! 283: ; ! 284: ! 285: pattern_list: ! 286: name '|' pattern_list { ! 287: $$ = node(NCASE3, $1, $3); ! 288: } ! 289: | name { ! 290: $$ = node(NCASE3, $1, NULL); ! 291: } ! 292: ; ! 293: ! 294: do_list: ! 295: do opt_cmd_seq { ! 296: $$ = $2; ! 297: } ! 298: | { ! 299: $$ = NULL; ! 300: } ! 301: ; ! 302: ! 303: else_part: ! 304: elif cmd_seq then opt_cmd_seq else_part { ! 305: $$ = node(NIF, node(NNULL, $2, $4), $5); ! 306: } ! 307: | else opt_cmd_seq { ! 308: $$ = node(NELSE, $2, NULL); ! 309: } ! 310: | { ! 311: $$ = NULL; ! 312: } ! 313: ; ! 314: ! 315: opt_cmd_seq: ! 316: cmd_seq { ! 317: $$ = $1; ! 318: } ! 319: | ! 320: { ! 321: $$ = NULL; ! 322: } ! 323: ; ! 324: ! 325: cmd_seq: ! 326: cmd_list nls cmd_seq { ! 327: $$ = node(NLIST, $1, $3); ! 328: } ! 329: | cmd_list optnls { ! 330: $$ = $1; ! 331: } ! 332: ; ! 333: ! 334: sep: nls ! 335: | ';' ! 336: | ';' nls ! 337: ; ! 338: ! 339: optnls: nls ! 340: | ! 341: ; ! 342: ! 343: nls: '\n' ! 344: | nls '\n' ! 345: ; ! 346: ! 347: %% ! 348: /* ! 349: * Create a node. ! 350: */ ! 351: NODE * ! 352: node(type, auxp, next) ! 353: NODE *auxp, *next; ! 354: { ! 355: register NODE *np; ! 356: ! 357: np = (NODE *) balloc(sizeof (NODE)); ! 358: np->n_type = type; ! 359: np->n_auxp = auxp; ! 360: np->n_next = next; ! 361: return np; ! 362: } ! 363: ! 364: #define NBPC 8 ! 365: #define NKEY 8 ! 366: static char keys[NKEY] = { 0 }; ! 367: static int keyi = NKEY * NBPC; ! 368: ! 369: keyflush() ! 370: { ! 371: register char *kp; ! 372: ! 373: for (kp = keys+NKEY; kp > keys; *--kp = 0) ! 374: ; ! 375: keyi = NKEY * NBPC; ! 376: } ! 377: ! 378: keypop() ! 379: { ! 380: register char *kp; ! 381: register int km; ! 382: ! 383: if ((km = keyi++) >= NKEY * NBPC) { ! 384: panic(11); ! 385: NOTREACHED; ! 386: } ! 387: kp = keys + (km / NBPC); ! 388: km = 1 << (km %= NBPC); ! 389: keyflag = (*kp & km) ? 1 : 0; ! 390: *kp &= ~km; ! 391: } ! 392: ! 393: keypush() ! 394: { ! 395: register char *kp; ! 396: register int km; ! 397: ! 398: if ((km = --keyi) < 0) { ! 399: panic(12); ! 400: NOTREACHED; ! 401: } ! 402: if (keyflag) { ! 403: kp = keys + (km / NBPC); ! 404: km = 1 << (km %= NBPC); ! 405: *kp |= km; ! 406: } ! 407: } ! 408: /* ! 409: * The following fragments might implement named pipes. ! 410: * The token declaration goes in the header. ! 411: * The nopen production should go with the others of its ilk. ! 412: * The production fragment goes into arg: ! 413: %token _NOPEN _NCLOSE ! 414: nopen: _NOPEN optnls ; ! 415: ! 416: | nopen pipe_cmd ')' { ! 417: $$ = node(NRPIPE, $2, NULL); ! 418: } ! 419: | oparen pipe_cmd _NCLOSE { ! 420: $$ = node(NWPIPE, $2, NULL); ! 421: } ! 422: * ! 423: */ ! 424: ! 425: /* end of sh/sh.y */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.