1 1.11 kamil /* $NetBSD: syn.c,v 1.11 2018/05/08 16:37:59 kamil Exp $ */ 2 1.2 tls 3 1.1 jtc /* 4 1.1 jtc * shell parser (C version) 5 1.1 jtc */ 6 1.5 agc #include <sys/cdefs.h> 7 1.5 agc 8 1.5 agc #ifndef lint 9 1.11 kamil __RCSID("$NetBSD: syn.c,v 1.11 2018/05/08 16:37:59 kamil Exp $"); 10 1.5 agc #endif 11 1.5 agc 12 1.1 jtc 13 1.1 jtc #include "sh.h" 14 1.1 jtc #include "c_test.h" 15 1.8 christos #include <assert.h> 16 1.1 jtc 17 1.4 hubertf struct nesting_state { 18 1.4 hubertf int start_token; /* token than began nesting (eg, FOR) */ 19 1.4 hubertf int start_line; /* line nesting began on */ 20 1.1 jtc }; 21 1.1 jtc 22 1.1 jtc static void yyparse ARGS((void)); 23 1.1 jtc static struct op *pipeline ARGS((int cf)); 24 1.1 jtc static struct op *andor ARGS((void)); 25 1.4 hubertf static struct op *c_list ARGS((int multi)); 26 1.1 jtc static struct ioword *synio ARGS((int cf)); 27 1.1 jtc static void musthave ARGS((int c, int cf)); 28 1.1 jtc static struct op *nested ARGS((int type, int smark, int emark)); 29 1.1 jtc static struct op *get_command ARGS((int cf)); 30 1.1 jtc static struct op *dogroup ARGS((void)); 31 1.1 jtc static struct op *thenpart ARGS((void)); 32 1.1 jtc static struct op *elsepart ARGS((void)); 33 1.1 jtc static struct op *caselist ARGS((void)); 34 1.1 jtc static struct op *casepart ARGS((int endtok)); 35 1.1 jtc static struct op *function_body ARGS((char *name, int ksh_func)); 36 1.1 jtc static char ** wordlist ARGS((void)); 37 1.1 jtc static struct op *block ARGS((int type, struct op *t1, struct op *t2, 38 1.1 jtc char **wp)); 39 1.1 jtc static struct op *newtp ARGS((int type)); 40 1.1 jtc static void syntaxerr ARGS((const char *what)) 41 1.1 jtc GCC_FUNC_ATTR(noreturn); 42 1.4 hubertf static void nesting_push ARGS((struct nesting_state *save, int tok)); 43 1.4 hubertf static void nesting_pop ARGS((struct nesting_state *saved)); 44 1.1 jtc static int assign_command ARGS((char *s)); 45 1.2 tls static int inalias ARGS((struct source *s)); 46 1.1 jtc #ifdef KSH 47 1.1 jtc static int dbtestp_isa ARGS((Test_env *te, Test_meta meta)); 48 1.1 jtc static const char *dbtestp_getopnd ARGS((Test_env *te, Test_op op, 49 1.1 jtc int do_eval)); 50 1.1 jtc static int dbtestp_eval ARGS((Test_env *te, Test_op op, const char *opnd1, 51 1.1 jtc const char *opnd2, int do_eval)); 52 1.1 jtc static void dbtestp_error ARGS((Test_env *te, int offset, const char *msg)); 53 1.1 jtc #endif /* KSH */ 54 1.1 jtc 55 1.1 jtc static struct op *outtree; /* yyparse output */ 56 1.1 jtc 57 1.4 hubertf static struct nesting_state nesting; /* \n changed to ; */ 58 1.1 jtc 59 1.1 jtc static int reject; /* token(cf) gets symbol again */ 60 1.1 jtc static int symbol; /* yylex value */ 61 1.1 jtc 62 1.1 jtc #define REJECT (reject = 1) 63 1.1 jtc #define ACCEPT (reject = 0) 64 1.1 jtc #define token(cf) \ 65 1.1 jtc ((reject) ? (ACCEPT, symbol) : (symbol = yylex(cf))) 66 1.1 jtc #define tpeek(cf) \ 67 1.1 jtc ((reject) ? (symbol) : (REJECT, symbol = yylex(cf))) 68 1.1 jtc 69 1.1 jtc static void 70 1.1 jtc yyparse() 71 1.1 jtc { 72 1.1 jtc int c; 73 1.1 jtc 74 1.1 jtc ACCEPT; 75 1.1 jtc 76 1.4 hubertf outtree = c_list(source->type == SSTRING); 77 1.1 jtc c = tpeek(0); 78 1.1 jtc if (c == 0 && !outtree) 79 1.1 jtc outtree = newtp(TEOF); 80 1.1 jtc else if (c != '\n' && c != 0) 81 1.1 jtc syntaxerr((char *) 0); 82 1.1 jtc } 83 1.1 jtc 84 1.1 jtc static struct op * 85 1.1 jtc pipeline(cf) 86 1.1 jtc int cf; 87 1.1 jtc { 88 1.11 kamil struct op *t, *p, *tl = NULL; 89 1.1 jtc 90 1.1 jtc t = get_command(cf); 91 1.1 jtc if (t != NULL) { 92 1.1 jtc while (token(0) == '|') { 93 1.1 jtc if ((p = get_command(CONTIN)) == NULL) 94 1.1 jtc syntaxerr((char *) 0); 95 1.1 jtc if (tl == NULL) 96 1.1 jtc t = tl = block(TPIPE, t, p, NOWORDS); 97 1.1 jtc else 98 1.1 jtc tl = tl->right = block(TPIPE, tl->right, p, NOWORDS); 99 1.1 jtc } 100 1.1 jtc REJECT; 101 1.1 jtc } 102 1.1 jtc return (t); 103 1.1 jtc } 104 1.1 jtc 105 1.1 jtc static struct op * 106 1.1 jtc andor() 107 1.1 jtc { 108 1.11 kamil struct op *t, *p; 109 1.11 kamil int c; 110 1.1 jtc 111 1.1 jtc t = pipeline(0); 112 1.1 jtc if (t != NULL) { 113 1.1 jtc while ((c = token(0)) == LOGAND || c == LOGOR) { 114 1.1 jtc if ((p = pipeline(CONTIN)) == NULL) 115 1.1 jtc syntaxerr((char *) 0); 116 1.1 jtc t = block(c == LOGAND? TAND: TOR, t, p, NOWORDS); 117 1.1 jtc } 118 1.1 jtc REJECT; 119 1.1 jtc } 120 1.1 jtc return (t); 121 1.1 jtc } 122 1.1 jtc 123 1.1 jtc static struct op * 124 1.4 hubertf c_list(multi) 125 1.4 hubertf int multi; 126 1.1 jtc { 127 1.11 kamil struct op *t = NULL, *p, *tl = NULL; 128 1.11 kamil int c; 129 1.4 hubertf int have_sep; 130 1.1 jtc 131 1.4 hubertf while (1) { 132 1.4 hubertf p = andor(); 133 1.2 tls /* Token has always been read/rejected at this point, so 134 1.4 hubertf * we don't worry about what flags to pass token() 135 1.2 tls */ 136 1.4 hubertf c = token(0); 137 1.4 hubertf have_sep = 1; 138 1.4 hubertf if (c == '\n' && (multi || inalias(source))) { 139 1.4 hubertf if (!p) /* ignore blank lines */ 140 1.4 hubertf continue; 141 1.4 hubertf } else if (!p) 142 1.4 hubertf break; 143 1.4 hubertf else if (c == '&' || c == COPROC) 144 1.4 hubertf p = block(c == '&' ? TASYNC : TCOPROC, 145 1.4 hubertf p, NOBLOCK, NOWORDS); 146 1.4 hubertf else if (c != ';') 147 1.4 hubertf have_sep = 0; 148 1.4 hubertf if (!t) 149 1.4 hubertf t = p; 150 1.4 hubertf else if (!tl) 151 1.4 hubertf t = tl = block(TLIST, t, p, NOWORDS); 152 1.4 hubertf else 153 1.4 hubertf tl = tl->right = block(TLIST, tl->right, p, NOWORDS); 154 1.4 hubertf if (!have_sep) 155 1.4 hubertf break; 156 1.1 jtc } 157 1.4 hubertf REJECT; 158 1.4 hubertf return t; 159 1.1 jtc } 160 1.1 jtc 161 1.1 jtc static struct ioword * 162 1.1 jtc synio(cf) 163 1.1 jtc int cf; 164 1.1 jtc { 165 1.11 kamil struct ioword *iop; 166 1.1 jtc int ishere; 167 1.1 jtc 168 1.1 jtc if (tpeek(cf) != REDIR) 169 1.1 jtc return NULL; 170 1.1 jtc ACCEPT; 171 1.1 jtc iop = yylval.iop; 172 1.1 jtc ishere = (iop->flag&IOTYPE) == IOHERE; 173 1.1 jtc musthave(LWORD, ishere ? HEREDELIM : 0); 174 1.1 jtc if (ishere) { 175 1.1 jtc iop->delim = yylval.cp; 176 1.1 jtc if (*ident != 0) /* unquoted */ 177 1.1 jtc iop->flag |= IOEVAL; 178 1.1 jtc if (herep >= &heres[HERES]) 179 1.1 jtc yyerror("too many <<'s\n"); 180 1.1 jtc *herep++ = iop; 181 1.1 jtc } else 182 1.1 jtc iop->name = yylval.cp; 183 1.1 jtc return iop; 184 1.1 jtc } 185 1.1 jtc 186 1.1 jtc static void 187 1.1 jtc musthave(c, cf) 188 1.1 jtc int c, cf; 189 1.1 jtc { 190 1.1 jtc if ((token(cf)) != c) 191 1.1 jtc syntaxerr((char *) 0); 192 1.1 jtc } 193 1.1 jtc 194 1.1 jtc static struct op * 195 1.1 jtc nested(type, smark, emark) 196 1.1 jtc int type, smark, emark; 197 1.1 jtc { 198 1.11 kamil struct op *t; 199 1.4 hubertf struct nesting_state old_nesting; 200 1.1 jtc 201 1.4 hubertf nesting_push(&old_nesting, smark); 202 1.10 kamil t = c_list(true); 203 1.1 jtc musthave(emark, KEYWORD|ALIAS); 204 1.4 hubertf nesting_pop(&old_nesting); 205 1.1 jtc return (block(type, t, NOBLOCK, NOWORDS)); 206 1.1 jtc } 207 1.1 jtc 208 1.1 jtc static struct op * 209 1.1 jtc get_command(cf) 210 1.1 jtc int cf; 211 1.1 jtc { 212 1.11 kamil struct op *t; 213 1.11 kamil int c, iopn = 0, syniocf; 214 1.1 jtc struct ioword *iop, **iops; 215 1.1 jtc XPtrV args, vars; 216 1.4 hubertf struct nesting_state old_nesting; 217 1.1 jtc 218 1.1 jtc iops = (struct ioword **) alloc(sizeofN(struct ioword *, NUFILE+1), 219 1.1 jtc ATEMP); 220 1.1 jtc XPinit(args, 16); 221 1.1 jtc XPinit(vars, 16); 222 1.1 jtc 223 1.1 jtc syniocf = KEYWORD|ALIAS; 224 1.1 jtc switch (c = token(cf|KEYWORD|ALIAS|VARASN)) { 225 1.1 jtc default: 226 1.1 jtc REJECT; 227 1.1 jtc afree((void*) iops, ATEMP); 228 1.1 jtc XPfree(args); 229 1.1 jtc XPfree(vars); 230 1.1 jtc return NULL; /* empty line */ 231 1.1 jtc 232 1.1 jtc case LWORD: 233 1.1 jtc case REDIR: 234 1.1 jtc REJECT; 235 1.1 jtc syniocf &= ~(KEYWORD|ALIAS); 236 1.1 jtc t = newtp(TCOM); 237 1.4 hubertf t->lineno = source->line; 238 1.1 jtc while (1) { 239 1.1 jtc cf = (t->u.evalflags ? ARRAYVAR : 0) 240 1.1 jtc | (XPsize(args) == 0 ? ALIAS|VARASN : CMDWORD); 241 1.1 jtc switch (tpeek(cf)) { 242 1.1 jtc case REDIR: 243 1.1 jtc if (iopn >= NUFILE) 244 1.1 jtc yyerror("too many redirections\n"); 245 1.1 jtc iops[iopn++] = synio(cf); 246 1.1 jtc break; 247 1.1 jtc 248 1.1 jtc case LWORD: 249 1.1 jtc ACCEPT; 250 1.1 jtc /* the iopn == 0 and XPsize(vars) == 0 are 251 1.1 jtc * dubious but at&t ksh acts this way 252 1.1 jtc */ 253 1.1 jtc if (iopn == 0 && XPsize(vars) == 0 254 1.1 jtc && XPsize(args) == 0 255 1.1 jtc && assign_command(ident)) 256 1.1 jtc t->u.evalflags = DOVACHECK; 257 1.1 jtc if ((XPsize(args) == 0 || Flag(FKEYWORD)) 258 1.1 jtc && is_wdvarassign(yylval.cp)) 259 1.1 jtc XPput(vars, yylval.cp); 260 1.1 jtc else 261 1.1 jtc XPput(args, yylval.cp); 262 1.1 jtc break; 263 1.1 jtc 264 1.1 jtc case '(': 265 1.1 jtc /* Check for "> foo (echo hi)", which at&t ksh 266 1.1 jtc * allows (not POSIX, but not disallowed) 267 1.1 jtc */ 268 1.1 jtc afree(t, ATEMP); 269 1.1 jtc if (XPsize(args) == 0 && XPsize(vars) == 0) { 270 1.1 jtc ACCEPT; 271 1.1 jtc goto Subshell; 272 1.1 jtc } 273 1.1 jtc /* Must be a function */ 274 1.1 jtc if (iopn != 0 || XPsize(args) != 1 275 1.1 jtc || XPsize(vars) != 0) 276 1.1 jtc syntaxerr((char *) 0); 277 1.1 jtc ACCEPT; 278 1.1 jtc /*(*/ 279 1.1 jtc musthave(')', 0); 280 1.10 kamil t = function_body(XPptrv(args)[0], false); 281 1.1 jtc goto Leave; 282 1.1 jtc 283 1.1 jtc default: 284 1.1 jtc goto Leave; 285 1.1 jtc } 286 1.1 jtc } 287 1.1 jtc Leave: 288 1.1 jtc break; 289 1.1 jtc 290 1.1 jtc Subshell: 291 1.1 jtc case '(': 292 1.1 jtc t = nested(TPAREN, '(', ')'); 293 1.1 jtc break; 294 1.1 jtc 295 1.1 jtc case '{': /*}*/ 296 1.1 jtc t = nested(TBRACE, '{', '}'); 297 1.1 jtc break; 298 1.1 jtc 299 1.2 tls #ifdef KSH 300 1.1 jtc case MDPAREN: 301 1.1 jtc { 302 1.1 jtc static const char let_cmd[] = { CHAR, 'l', CHAR, 'e', 303 1.1 jtc CHAR, 't', EOS }; 304 1.4 hubertf /* Leave KEYWORD in syniocf (allow if (( 1 )) then ...) */ 305 1.1 jtc t = newtp(TCOM); 306 1.4 hubertf t->lineno = source->line; 307 1.1 jtc ACCEPT; 308 1.1 jtc XPput(args, wdcopy(let_cmd, ATEMP)); 309 1.1 jtc musthave(LWORD,LETEXPR); 310 1.1 jtc XPput(args, yylval.cp); 311 1.1 jtc break; 312 1.1 jtc } 313 1.2 tls #endif /* KSH */ 314 1.1 jtc 315 1.1 jtc #ifdef KSH 316 1.1 jtc case DBRACKET: /* [[ .. ]] */ 317 1.4 hubertf /* Leave KEYWORD in syniocf (allow if [[ -n 1 ]] then ...) */ 318 1.1 jtc t = newtp(TDBRACKET); 319 1.1 jtc ACCEPT; 320 1.1 jtc { 321 1.1 jtc Test_env te; 322 1.1 jtc 323 1.1 jtc te.flags = TEF_DBRACKET; 324 1.1 jtc te.pos.av = &args; 325 1.1 jtc te.isa = dbtestp_isa; 326 1.1 jtc te.getopnd = dbtestp_getopnd; 327 1.1 jtc te.eval = dbtestp_eval; 328 1.1 jtc te.error = dbtestp_error; 329 1.1 jtc 330 1.1 jtc test_parse(&te); 331 1.1 jtc } 332 1.1 jtc break; 333 1.1 jtc #endif /* KSH */ 334 1.1 jtc 335 1.1 jtc case FOR: 336 1.1 jtc case SELECT: 337 1.1 jtc t = newtp((c == FOR) ? TFOR : TSELECT); 338 1.1 jtc musthave(LWORD, ARRAYVAR); 339 1.10 kamil if (!is_wdvarname(yylval.cp, true)) 340 1.1 jtc yyerror("%s: bad identifier\n", 341 1.1 jtc c == FOR ? "for" : "select"); 342 1.1 jtc t->str = str_save(ident, ATEMP); 343 1.4 hubertf nesting_push(&old_nesting, c); 344 1.1 jtc t->vars = wordlist(); 345 1.1 jtc t->left = dogroup(); 346 1.4 hubertf nesting_pop(&old_nesting); 347 1.1 jtc break; 348 1.1 jtc 349 1.1 jtc case WHILE: 350 1.1 jtc case UNTIL: 351 1.4 hubertf nesting_push(&old_nesting, c); 352 1.1 jtc t = newtp((c == WHILE) ? TWHILE : TUNTIL); 353 1.10 kamil t->left = c_list(true); 354 1.1 jtc t->right = dogroup(); 355 1.4 hubertf nesting_pop(&old_nesting); 356 1.1 jtc break; 357 1.1 jtc 358 1.1 jtc case CASE: 359 1.1 jtc t = newtp(TCASE); 360 1.1 jtc musthave(LWORD, 0); 361 1.1 jtc t->str = yylval.cp; 362 1.4 hubertf nesting_push(&old_nesting, c); 363 1.1 jtc t->left = caselist(); 364 1.4 hubertf nesting_pop(&old_nesting); 365 1.1 jtc break; 366 1.1 jtc 367 1.1 jtc case IF: 368 1.4 hubertf nesting_push(&old_nesting, c); 369 1.1 jtc t = newtp(TIF); 370 1.10 kamil t->left = c_list(true); 371 1.1 jtc t->right = thenpart(); 372 1.1 jtc musthave(FI, KEYWORD|ALIAS); 373 1.4 hubertf nesting_pop(&old_nesting); 374 1.1 jtc break; 375 1.1 jtc 376 1.1 jtc case BANG: 377 1.1 jtc syniocf &= ~(KEYWORD|ALIAS); 378 1.1 jtc t = pipeline(0); 379 1.1 jtc if (t == (struct op *) 0) 380 1.1 jtc syntaxerr((char *) 0); 381 1.1 jtc t = block(TBANG, NOBLOCK, t, NOWORDS); 382 1.1 jtc break; 383 1.1 jtc 384 1.1 jtc case TIME: 385 1.1 jtc syniocf &= ~(KEYWORD|ALIAS); 386 1.1 jtc t = pipeline(0); 387 1.1 jtc t = block(TTIME, t, NOBLOCK, NOWORDS); 388 1.1 jtc break; 389 1.1 jtc 390 1.1 jtc case FUNCTION: 391 1.1 jtc musthave(LWORD, 0); 392 1.10 kamil t = function_body(yylval.cp, true); 393 1.1 jtc break; 394 1.1 jtc } 395 1.1 jtc 396 1.1 jtc while ((iop = synio(syniocf)) != NULL) { 397 1.1 jtc if (iopn >= NUFILE) 398 1.1 jtc yyerror("too many redirections\n"); 399 1.1 jtc iops[iopn++] = iop; 400 1.1 jtc } 401 1.1 jtc 402 1.1 jtc if (iopn == 0) { 403 1.1 jtc afree((void*) iops, ATEMP); 404 1.1 jtc t->ioact = NULL; 405 1.1 jtc } else { 406 1.1 jtc iops[iopn++] = NULL; 407 1.1 jtc iops = (struct ioword **) aresize((void*) iops, 408 1.1 jtc sizeofN(struct ioword *, iopn), ATEMP); 409 1.1 jtc t->ioact = iops; 410 1.1 jtc } 411 1.1 jtc 412 1.1 jtc if (t->type == TCOM || t->type == TDBRACKET) { 413 1.1 jtc XPput(args, NULL); 414 1.1 jtc t->args = (char **) XPclose(args); 415 1.1 jtc XPput(vars, NULL); 416 1.1 jtc t->vars = (char **) XPclose(vars); 417 1.1 jtc } else { 418 1.1 jtc XPfree(args); 419 1.1 jtc XPfree(vars); 420 1.1 jtc } 421 1.1 jtc 422 1.1 jtc return t; 423 1.1 jtc } 424 1.1 jtc 425 1.1 jtc static struct op * 426 1.1 jtc dogroup() 427 1.1 jtc { 428 1.11 kamil int c; 429 1.11 kamil struct op *list; 430 1.1 jtc 431 1.1 jtc c = token(CONTIN|KEYWORD|ALIAS); 432 1.1 jtc /* A {...} can be used instead of do...done for for/select loops 433 1.1 jtc * but not for while/until loops - we don't need to check if it 434 1.1 jtc * is a while loop because it would have been parsed as part of 435 1.1 jtc * the conditional command list... 436 1.1 jtc */ 437 1.1 jtc if (c == DO) 438 1.1 jtc c = DONE; 439 1.1 jtc else if (c == '{') 440 1.1 jtc c = '}'; 441 1.1 jtc else 442 1.1 jtc syntaxerr((char *) 0); 443 1.10 kamil list = c_list(true); 444 1.1 jtc musthave(c, KEYWORD|ALIAS); 445 1.1 jtc return list; 446 1.1 jtc } 447 1.1 jtc 448 1.1 jtc static struct op * 449 1.1 jtc thenpart() 450 1.1 jtc { 451 1.11 kamil struct op *t; 452 1.1 jtc 453 1.1 jtc musthave(THEN, KEYWORD|ALIAS); 454 1.1 jtc t = newtp(0); 455 1.10 kamil t->left = c_list(true); 456 1.1 jtc if (t->left == NULL) 457 1.1 jtc syntaxerr((char *) 0); 458 1.1 jtc t->right = elsepart(); 459 1.1 jtc return (t); 460 1.1 jtc } 461 1.1 jtc 462 1.1 jtc static struct op * 463 1.1 jtc elsepart() 464 1.1 jtc { 465 1.11 kamil struct op *t; 466 1.1 jtc 467 1.1 jtc switch (token(KEYWORD|ALIAS|VARASN)) { 468 1.1 jtc case ELSE: 469 1.10 kamil if ((t = c_list(true)) == NULL) 470 1.1 jtc syntaxerr((char *) 0); 471 1.1 jtc return (t); 472 1.1 jtc 473 1.1 jtc case ELIF: 474 1.1 jtc t = newtp(TELIF); 475 1.10 kamil t->left = c_list(true); 476 1.1 jtc t->right = thenpart(); 477 1.1 jtc return (t); 478 1.1 jtc 479 1.1 jtc default: 480 1.1 jtc REJECT; 481 1.1 jtc } 482 1.1 jtc return NULL; 483 1.1 jtc } 484 1.1 jtc 485 1.1 jtc static struct op * 486 1.1 jtc caselist() 487 1.1 jtc { 488 1.11 kamil struct op *t, *tl; 489 1.1 jtc int c; 490 1.1 jtc 491 1.1 jtc c = token(CONTIN|KEYWORD|ALIAS); 492 1.1 jtc /* A {...} can be used instead of in...esac for case statements */ 493 1.1 jtc if (c == IN) 494 1.1 jtc c = ESAC; 495 1.1 jtc else if (c == '{') 496 1.1 jtc c = '}'; 497 1.1 jtc else 498 1.1 jtc syntaxerr((char *) 0); 499 1.1 jtc t = tl = NULL; 500 1.1 jtc while ((tpeek(CONTIN|KEYWORD|ESACONLY)) != c) { /* no ALIAS here */ 501 1.1 jtc struct op *tc = casepart(c); 502 1.1 jtc if (tl == NULL) 503 1.1 jtc t = tl = tc, tl->right = NULL; 504 1.1 jtc else 505 1.1 jtc tl->right = tc, tl = tc; 506 1.1 jtc } 507 1.1 jtc musthave(c, KEYWORD|ALIAS); 508 1.1 jtc return (t); 509 1.1 jtc } 510 1.1 jtc 511 1.1 jtc static struct op * 512 1.1 jtc casepart(endtok) 513 1.1 jtc int endtok; 514 1.1 jtc { 515 1.11 kamil struct op *t; 516 1.11 kamil int c; 517 1.1 jtc XPtrV ptns; 518 1.1 jtc 519 1.1 jtc XPinit(ptns, 16); 520 1.1 jtc t = newtp(TPAT); 521 1.1 jtc c = token(CONTIN|KEYWORD); /* no ALIAS here */ 522 1.1 jtc if (c != '(') 523 1.1 jtc REJECT; 524 1.1 jtc do { 525 1.1 jtc musthave(LWORD, 0); 526 1.1 jtc XPput(ptns, yylval.cp); 527 1.1 jtc } while ((c = token(0)) == '|'); 528 1.1 jtc REJECT; 529 1.1 jtc XPput(ptns, NULL); 530 1.1 jtc t->vars = (char **) XPclose(ptns); 531 1.1 jtc musthave(')', 0); 532 1.1 jtc 533 1.10 kamil t->left = c_list(true); 534 1.4 hubertf /* Note: Posix requires the ;; */ 535 1.1 jtc if ((tpeek(CONTIN|KEYWORD|ALIAS)) != endtok) 536 1.1 jtc musthave(BREAK, CONTIN|KEYWORD|ALIAS); 537 1.1 jtc return (t); 538 1.1 jtc } 539 1.1 jtc 540 1.1 jtc static struct op * 541 1.1 jtc function_body(name, ksh_func) 542 1.1 jtc char *name; 543 1.1 jtc int ksh_func; /* function foo { ... } vs foo() { .. } */ 544 1.1 jtc { 545 1.4 hubertf char *sname, *p; 546 1.1 jtc struct op *t; 547 1.1 jtc int old_func_parse; 548 1.1 jtc 549 1.4 hubertf sname = wdstrip(name); 550 1.4 hubertf /* Check for valid characters in name. posix and ksh93 say only 551 1.4 hubertf * allow [a-zA-Z_0-9] but this allows more as old pdksh's have 552 1.4 hubertf * allowed more (the following were never allowed: 553 1.4 hubertf * nul space nl tab $ ' " \ ` ( ) & | ; = < > 554 1.4 hubertf * C_QUOTE covers all but = and adds # [ ? *) 555 1.4 hubertf */ 556 1.4 hubertf for (p = sname; *p; p++) 557 1.4 hubertf if (ctype(*p, C_QUOTE) || *p == '=') 558 1.4 hubertf yyerror("%s: invalid function name\n", sname); 559 1.4 hubertf 560 1.1 jtc t = newtp(TFUNCT); 561 1.4 hubertf t->str = sname; 562 1.1 jtc t->u.ksh_func = ksh_func; 563 1.4 hubertf t->lineno = source->line; 564 1.1 jtc 565 1.1 jtc /* Note that POSIX allows only compound statements after foo(), sh and 566 1.1 jtc * at&t ksh allow any command, go with the later since it shouldn't 567 1.1 jtc * break anything. However, for function foo, at&t ksh only accepts 568 1.1 jtc * an open-brace. 569 1.1 jtc */ 570 1.1 jtc if (ksh_func) { 571 1.1 jtc musthave('{', CONTIN|KEYWORD|ALIAS); /* } */ 572 1.1 jtc REJECT; 573 1.1 jtc } 574 1.1 jtc 575 1.1 jtc old_func_parse = e->flags & EF_FUNC_PARSE; 576 1.1 jtc e->flags |= EF_FUNC_PARSE; 577 1.1 jtc if ((t->left = get_command(CONTIN)) == (struct op *) 0) { 578 1.4 hubertf /* 579 1.4 hubertf * Probably something like foo() followed by eof or ;. 580 1.4 hubertf * This is accepted by sh and ksh88. 581 1.6 mycroft * To make "typeset -f foo" work reliably (so its output can 582 1.4 hubertf * be used as input), we pretend there is a colon here. 583 1.4 hubertf */ 584 1.1 jtc t->left = newtp(TCOM); 585 1.4 hubertf t->left->args = (char **) alloc(sizeof(char *) * 2, ATEMP); 586 1.4 hubertf t->left->args[0] = alloc(sizeof(char) * 3, ATEMP); 587 1.4 hubertf t->left->args[0][0] = CHAR; 588 1.4 hubertf t->left->args[0][1] = ':'; 589 1.4 hubertf t->left->args[0][2] = EOS; 590 1.4 hubertf t->left->args[1] = (char *) 0; 591 1.3 erh t->left->vars = (char **) alloc(sizeof(char *), ATEMP); 592 1.3 erh t->left->vars[0] = (char *) 0; 593 1.4 hubertf t->left->lineno = 1; 594 1.1 jtc } 595 1.1 jtc if (!old_func_parse) 596 1.1 jtc e->flags &= ~EF_FUNC_PARSE; 597 1.1 jtc 598 1.1 jtc return t; 599 1.1 jtc } 600 1.1 jtc 601 1.1 jtc static char ** 602 1.1 jtc wordlist() 603 1.1 jtc { 604 1.11 kamil int c; 605 1.1 jtc XPtrV args; 606 1.1 jtc 607 1.1 jtc XPinit(args, 16); 608 1.4 hubertf /* Posix does not do alias expansion here... */ 609 1.1 jtc if ((c = token(CONTIN|KEYWORD|ALIAS)) != IN) { 610 1.1 jtc if (c != ';') /* non-POSIX, but at&t ksh accepts a ; here */ 611 1.1 jtc REJECT; 612 1.1 jtc return NULL; 613 1.1 jtc } 614 1.1 jtc while ((c = token(0)) == LWORD) 615 1.1 jtc XPput(args, yylval.cp); 616 1.1 jtc if (c != '\n' && c != ';') 617 1.1 jtc syntaxerr((char *) 0); 618 1.1 jtc if (XPsize(args) == 0) { 619 1.1 jtc XPfree(args); 620 1.1 jtc return NULL; 621 1.1 jtc } else { 622 1.1 jtc XPput(args, NULL); 623 1.1 jtc return (char **) XPclose(args); 624 1.1 jtc } 625 1.1 jtc } 626 1.1 jtc 627 1.1 jtc /* 628 1.1 jtc * supporting functions 629 1.1 jtc */ 630 1.1 jtc 631 1.1 jtc static struct op * 632 1.1 jtc block(type, t1, t2, wp) 633 1.1 jtc int type; 634 1.1 jtc struct op *t1, *t2; 635 1.1 jtc char **wp; 636 1.1 jtc { 637 1.11 kamil struct op *t; 638 1.1 jtc 639 1.1 jtc t = newtp(type); 640 1.1 jtc t->left = t1; 641 1.1 jtc t->right = t2; 642 1.1 jtc t->vars = wp; 643 1.1 jtc return (t); 644 1.1 jtc } 645 1.1 jtc 646 1.1 jtc const struct tokeninfo { 647 1.1 jtc const char *name; 648 1.1 jtc short val; 649 1.1 jtc short reserved; 650 1.1 jtc } tokentab[] = { 651 1.1 jtc /* Reserved words */ 652 1.10 kamil { "if", IF, true }, 653 1.10 kamil { "then", THEN, true }, 654 1.10 kamil { "else", ELSE, true }, 655 1.10 kamil { "elif", ELIF, true }, 656 1.10 kamil { "fi", FI, true }, 657 1.10 kamil { "case", CASE, true }, 658 1.10 kamil { "esac", ESAC, true }, 659 1.10 kamil { "for", FOR, true }, 660 1.1 jtc #ifdef KSH 661 1.10 kamil { "select", SELECT, true }, 662 1.1 jtc #endif /* KSH */ 663 1.10 kamil { "while", WHILE, true }, 664 1.10 kamil { "until", UNTIL, true }, 665 1.10 kamil { "do", DO, true }, 666 1.10 kamil { "done", DONE, true }, 667 1.10 kamil { "in", IN, true }, 668 1.10 kamil { "function", FUNCTION, true }, 669 1.10 kamil { "time", TIME, true }, 670 1.10 kamil { "{", '{', true }, 671 1.10 kamil { "}", '}', true }, 672 1.10 kamil { "!", BANG, true }, 673 1.1 jtc #ifdef KSH 674 1.10 kamil { "[[", DBRACKET, true }, 675 1.1 jtc #endif /* KSH */ 676 1.1 jtc /* Lexical tokens (0[EOF], LWORD and REDIR handled specially) */ 677 1.10 kamil { "&&", LOGAND, false }, 678 1.10 kamil { "||", LOGOR, false }, 679 1.10 kamil { ";;", BREAK, false }, 680 1.2 tls #ifdef KSH 681 1.10 kamil { "((", MDPAREN, false }, 682 1.10 kamil { "|&", COPROC, false }, 683 1.1 jtc #endif /* KSH */ 684 1.1 jtc /* and some special cases... */ 685 1.10 kamil { "newline", '\n', false }, 686 1.9 christos { .name = NULL } 687 1.1 jtc }; 688 1.1 jtc 689 1.1 jtc void 690 1.1 jtc initkeywords() 691 1.1 jtc { 692 1.11 kamil struct tokeninfo const *tt; 693 1.11 kamil struct tbl *p; 694 1.1 jtc 695 1.1 jtc tinit(&keywords, APERM, 32); /* must be 2^n (currently 20 keywords) */ 696 1.1 jtc for (tt = tokentab; tt->name; tt++) { 697 1.1 jtc if (tt->reserved) { 698 1.1 jtc p = tenter(&keywords, tt->name, hash(tt->name)); 699 1.1 jtc p->flag |= DEFINED|ISSET; 700 1.1 jtc p->type = CKEYWD; 701 1.1 jtc p->val.i = tt->val; 702 1.1 jtc } 703 1.1 jtc } 704 1.1 jtc } 705 1.1 jtc 706 1.1 jtc static void 707 1.1 jtc syntaxerr(what) 708 1.1 jtc const char *what; 709 1.1 jtc { 710 1.1 jtc char redir[6]; /* 2<<- is the longest redirection, I think */ 711 1.1 jtc const char *s; 712 1.1 jtc struct tokeninfo const *tt; 713 1.1 jtc int c; 714 1.1 jtc 715 1.1 jtc if (!what) 716 1.1 jtc what = "unexpected"; 717 1.1 jtc REJECT; 718 1.1 jtc c = token(0); 719 1.1 jtc Again: 720 1.1 jtc switch (c) { 721 1.1 jtc case 0: 722 1.4 hubertf if (nesting.start_token) { 723 1.4 hubertf c = nesting.start_token; 724 1.4 hubertf source->errline = nesting.start_line; 725 1.1 jtc what = "unmatched"; 726 1.1 jtc goto Again; 727 1.1 jtc } 728 1.1 jtc /* don't quote the EOF */ 729 1.1 jtc yyerror("syntax error: unexpected EOF\n"); 730 1.1 jtc /*NOTREACHED*/ 731 1.1 jtc 732 1.1 jtc case LWORD: 733 1.1 jtc s = snptreef((char *) 0, 32, "%S", yylval.cp); 734 1.1 jtc break; 735 1.1 jtc 736 1.1 jtc case REDIR: 737 1.1 jtc s = snptreef(redir, sizeof(redir), "%R", yylval.iop); 738 1.1 jtc break; 739 1.1 jtc 740 1.1 jtc default: 741 1.1 jtc for (tt = tokentab; tt->name; tt++) 742 1.1 jtc if (tt->val == c) 743 1.1 jtc break; 744 1.1 jtc if (tt->name) 745 1.1 jtc s = tt->name; 746 1.1 jtc else { 747 1.1 jtc if (c > 0 && c < 256) { 748 1.1 jtc redir[0] = c; 749 1.1 jtc redir[1] = '\0'; 750 1.1 jtc } else 751 1.1 jtc shf_snprintf(redir, sizeof(redir), 752 1.1 jtc "?%d", c); 753 1.1 jtc s = redir; 754 1.1 jtc } 755 1.1 jtc } 756 1.1 jtc yyerror("syntax error: `%s' %s\n", s, what); 757 1.1 jtc } 758 1.1 jtc 759 1.1 jtc static void 760 1.4 hubertf nesting_push(save, tok) 761 1.4 hubertf struct nesting_state *save; 762 1.1 jtc int tok; 763 1.1 jtc { 764 1.4 hubertf *save = nesting; 765 1.4 hubertf nesting.start_token = tok; 766 1.4 hubertf nesting.start_line = source->line; 767 1.1 jtc } 768 1.1 jtc 769 1.1 jtc static void 770 1.4 hubertf nesting_pop(saved) 771 1.4 hubertf struct nesting_state *saved; 772 1.1 jtc { 773 1.4 hubertf nesting = *saved; 774 1.1 jtc } 775 1.1 jtc 776 1.1 jtc static struct op * 777 1.1 jtc newtp(type) 778 1.1 jtc int type; 779 1.1 jtc { 780 1.11 kamil struct op *t; 781 1.1 jtc 782 1.1 jtc t = (struct op *) alloc(sizeof(*t), ATEMP); 783 1.1 jtc t->type = type; 784 1.1 jtc t->u.evalflags = 0; 785 1.1 jtc t->args = t->vars = NULL; 786 1.1 jtc t->ioact = NULL; 787 1.1 jtc t->left = t->right = NULL; 788 1.1 jtc t->str = NULL; 789 1.1 jtc return (t); 790 1.1 jtc } 791 1.1 jtc 792 1.1 jtc struct op * 793 1.1 jtc compile(s) 794 1.1 jtc Source *s; 795 1.1 jtc { 796 1.4 hubertf nesting.start_token = 0; 797 1.4 hubertf nesting.start_line = 0; 798 1.1 jtc herep = heres; 799 1.1 jtc source = s; 800 1.1 jtc yyparse(); 801 1.1 jtc return outtree; 802 1.1 jtc } 803 1.1 jtc 804 1.1 jtc /* This kludge exists to take care of sh/at&t ksh oddity in which 805 1.1 jtc * the arguments of alias/export/readonly/typeset have no field 806 1.1 jtc * splitting, file globbing, or (normal) tilde expansion done. 807 1.1 jtc * at&t ksh seems to do something similar to this since 808 1.1 jtc * $ touch a=a; typeset a=[ab]; echo "$a" 809 1.1 jtc * a=[ab] 810 1.1 jtc * $ x=typeset; $x a=[ab]; echo "$a" 811 1.1 jtc * a=a 812 1.6 mycroft * $ 813 1.1 jtc */ 814 1.1 jtc static int 815 1.1 jtc assign_command(s) 816 1.1 jtc char *s; 817 1.1 jtc { 818 1.1 jtc char c = *s; 819 1.1 jtc 820 1.1 jtc if (Flag(FPOSIX) || !*s) 821 1.1 jtc return 0; 822 1.1 jtc return (c == 'a' && strcmp(s, "alias") == 0) 823 1.1 jtc || (c == 'e' && strcmp(s, "export") == 0) 824 1.1 jtc || (c == 'r' && strcmp(s, "readonly") == 0) 825 1.1 jtc || (c == 't' && strcmp(s, "typeset") == 0); 826 1.2 tls } 827 1.2 tls 828 1.2 tls /* Check if we are in the middle of reading an alias */ 829 1.2 tls static int 830 1.2 tls inalias(s) 831 1.2 tls struct source *s; 832 1.2 tls { 833 1.2 tls for (; s && s->type == SALIAS; s = s->next) 834 1.2 tls if (!(s->flags & SF_ALIASEND)) 835 1.2 tls return 1; 836 1.2 tls return 0; 837 1.1 jtc } 838 1.1 jtc 839 1.1 jtc 840 1.1 jtc #ifdef KSH 841 1.1 jtc /* Order important - indexed by Test_meta values 842 1.1 jtc * Note that ||, &&, ( and ) can't appear in as unquoted strings 843 1.1 jtc * in normal shell input, so these can be interpreted unambiguously 844 1.1 jtc * in the evaluation pass. 845 1.1 jtc */ 846 1.1 jtc static const char dbtest_or[] = { CHAR, '|', CHAR, '|', EOS }; 847 1.1 jtc static const char dbtest_and[] = { CHAR, '&', CHAR, '&', EOS }; 848 1.1 jtc static const char dbtest_not[] = { CHAR, '!', EOS }; 849 1.1 jtc static const char dbtest_oparen[] = { CHAR, '(', EOS }; 850 1.1 jtc static const char dbtest_cparen[] = { CHAR, ')', EOS }; 851 1.1 jtc const char *const dbtest_tokens[] = { 852 1.1 jtc dbtest_or, dbtest_and, dbtest_not, 853 1.1 jtc dbtest_oparen, dbtest_cparen 854 1.1 jtc }; 855 1.1 jtc const char db_close[] = { CHAR, ']', CHAR, ']', EOS }; 856 1.1 jtc const char db_lthan[] = { CHAR, '<', EOS }; 857 1.1 jtc const char db_gthan[] = { CHAR, '>', EOS }; 858 1.1 jtc 859 1.1 jtc /* Test if the current token is a whatever. Accepts the current token if 860 1.1 jtc * it is. Returns 0 if it is not, non-zero if it is (in the case of 861 1.1 jtc * TM_UNOP and TM_BINOP, the returned value is a Test_op). 862 1.1 jtc */ 863 1.1 jtc static int 864 1.1 jtc dbtestp_isa(te, meta) 865 1.1 jtc Test_env *te; 866 1.1 jtc Test_meta meta; 867 1.1 jtc { 868 1.1 jtc int c = tpeek(ARRAYVAR | (meta == TM_BINOP ? 0 : CONTIN)); 869 1.1 jtc int uqword = 0; 870 1.1 jtc char *save = (char *) 0; 871 1.1 jtc int ret = 0; 872 1.1 jtc 873 1.1 jtc /* unquoted word? */ 874 1.1 jtc uqword = c == LWORD && *ident; 875 1.1 jtc 876 1.1 jtc if (meta == TM_OR) 877 1.1 jtc ret = c == LOGOR; 878 1.1 jtc else if (meta == TM_AND) 879 1.1 jtc ret = c == LOGAND; 880 1.1 jtc else if (meta == TM_NOT) 881 1.1 jtc ret = uqword && strcmp(yylval.cp, dbtest_tokens[(int) TM_NOT]) == 0; 882 1.1 jtc else if (meta == TM_OPAREN) 883 1.1 jtc ret = c == '(' /*)*/; 884 1.1 jtc else if (meta == TM_CPAREN) 885 1.1 jtc ret = c == /*(*/ ')'; 886 1.1 jtc else if (meta == TM_UNOP || meta == TM_BINOP) { 887 1.1 jtc if (meta == TM_BINOP && c == REDIR 888 1.1 jtc && (yylval.iop->flag == IOREAD 889 1.1 jtc || yylval.iop->flag == IOWRITE)) 890 1.1 jtc { 891 1.1 jtc ret = 1; 892 1.1 jtc save = wdcopy(yylval.iop->flag == IOREAD ? 893 1.1 jtc db_lthan : db_gthan, ATEMP); 894 1.1 jtc } else if (uqword && (ret = (int) test_isop(te, meta, ident))) 895 1.1 jtc save = yylval.cp; 896 1.1 jtc } else /* meta == TM_END */ 897 1.1 jtc ret = uqword && strcmp(yylval.cp, db_close) == 0; 898 1.1 jtc if (ret) { 899 1.1 jtc ACCEPT; 900 1.8 christos if (meta != TM_END) { 901 1.8 christos if (!save) { 902 1.9 christos assert(/* meta >= 0 && */ 903 1.8 christos meta < sizeof(dbtest_tokens) / 904 1.8 christos sizeof(dbtest_tokens[0])); 905 1.1 jtc save = wdcopy(dbtest_tokens[(int) meta], ATEMP); 906 1.8 christos } 907 1.1 jtc XPput(*te->pos.av, save); 908 1.1 jtc } 909 1.1 jtc } 910 1.1 jtc return ret; 911 1.1 jtc } 912 1.1 jtc 913 1.1 jtc static const char * 914 1.1 jtc dbtestp_getopnd(te, op, do_eval) 915 1.1 jtc Test_env *te; 916 1.1 jtc Test_op op; 917 1.1 jtc int do_eval; 918 1.1 jtc { 919 1.1 jtc int c = tpeek(ARRAYVAR); 920 1.1 jtc 921 1.1 jtc if (c != LWORD) 922 1.1 jtc return (const char *) 0; 923 1.1 jtc 924 1.1 jtc ACCEPT; 925 1.1 jtc XPput(*te->pos.av, yylval.cp); 926 1.1 jtc 927 1.1 jtc return null; 928 1.1 jtc } 929 1.1 jtc 930 1.1 jtc static int 931 1.1 jtc dbtestp_eval(te, op, opnd1, opnd2, do_eval) 932 1.1 jtc Test_env *te; 933 1.1 jtc Test_op op; 934 1.1 jtc const char *opnd1; 935 1.1 jtc const char *opnd2; 936 1.1 jtc int do_eval; 937 1.1 jtc { 938 1.1 jtc return 1; 939 1.1 jtc } 940 1.1 jtc 941 1.1 jtc static void 942 1.1 jtc dbtestp_error(te, offset, msg) 943 1.1 jtc Test_env *te; 944 1.1 jtc int offset; 945 1.1 jtc const char *msg; 946 1.1 jtc { 947 1.1 jtc te->flags |= TEF_ERROR; 948 1.1 jtc 949 1.1 jtc if (offset < 0) { 950 1.1 jtc REJECT; 951 1.1 jtc /* Kludgy to say the least... */ 952 1.1 jtc symbol = LWORD; 953 1.1 jtc yylval.cp = *(XPptrv(*te->pos.av) + XPsize(*te->pos.av) 954 1.1 jtc + offset); 955 1.1 jtc } 956 1.1 jtc syntaxerr(msg); 957 1.1 jtc } 958 1.1 jtc #endif /* KSH */ 959