1 /*-
2 * Copyright (c) 1991, 1993
3 * The Regents of the University of California. All rights reserved.
4 * Copyright (c) 1997-2005
5 * Herbert Xu <herbert@gondor.apana.org.au>. All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Kenneth Almquist.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. 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 #if HAVE_ALLOCA_H
36 #include <alloca.h>
37 #endif
38
39 #include <stdlib.h>
40
41 #include "shell.h"
42 #include "parser.h"
43 #include "nodes.h"
44 #include "expand.h" /* defines rmescapes() */
45 #include "exec.h" /* defines find_builtin() */
46 #include "syntax.h"
47 #include "options.h"
48 #include "input.h"
49 #include "output.h"
50 #include "var.h"
51 #include "error.h"
52 #include "memalloc.h"
53 #include "mystring.h"
54 #include "alias.h"
55 #include "show.h"
56 #include "builtins.h"
57 #include "system.h"
58 #ifndef SMALL
59 #include "myhistedit.h"
60 #endif
61
62 /*
63 * Shell command parser.
64 */
65
66 /* values returned by readtoken */
67 #include "token_vars.h"
68
69
70
71 /* Used by expandstr to get here-doc like behaviour. */
72 #define FAKEEOFMARK (char *)1
73
74
75
76 struct heredoc {
77 struct heredoc *next; /* next here document in list */
78 union node *here; /* redirection node */
79 char *eofmark; /* string indicating end of input */
80 int striptabs; /* if set, strip leading tabs */
81 };
82
83 struct synstack {
84 const char *syntax;
85 struct synstack *prev;
86 struct synstack *next;
87 int innerdq;
88 int varpushed;
89 int dblquote;
90 int varnest; /* levels of variables expansion */
91 int parenlevel; /* levels of parens in arithmetic */
92 int dqvarnest; /* levels of variables expansion within double quotes */
93 };
94
95
96
97 struct heredoc *heredoclist; /* list of here documents to read */
98 int doprompt; /* if set, prompt the user */
99 int needprompt; /* true if interactive and at start of line */
100 int lasttoken; /* last token read */
101 int tokpushback; /* last token pushed back */
102 char *wordtext; /* text of last word returned by readtoken */
103 int checkkwd;
104 struct nodelist *backquotelist;
105 union node *redirnode;
106 struct heredoc *heredoc;
107 int quoteflag; /* set if (part of) last token was quoted */
108
109
110 STATIC union node *list(int);
111 STATIC union node *andor(void);
112 STATIC union node *pipeline(void);
113 STATIC union node *command(void);
114 STATIC union node *simplecmd(void);
115 STATIC union node *makename(void);
116 STATIC void parsefname(void);
117 STATIC void parseheredoc(void);
118 STATIC int readtoken(void);
119 STATIC int xxreadtoken(void);
120 STATIC int pgetc_eatbnl();
121 STATIC int readtoken1(int, char const *, char *, int);
122 STATIC void synexpect(int) __attribute__((__noreturn__));
123 STATIC void synerror(const char *) __attribute__((__noreturn__));
124 STATIC void setprompt(int);
125
126
isassignment(const char * p)127 int isassignment(const char *p)
128 {
129 const char *q = endofname(p);
130 if (p == q)
131 return 0;
132 return *q == '=';
133 }
134
realeofmark(const char * eofmark)135 static inline int realeofmark(const char *eofmark)
136 {
137 return eofmark && eofmark != FAKEEOFMARK;
138 }
139
140
141 /*
142 * Read and parse a command. Returns NEOF on end of file. (NULL is a
143 * valid parse tree indicating a blank line.)
144 */
145
146 union node *
parsecmd(int interact)147 parsecmd(int interact)
148 {
149 tokpushback = 0;
150 checkkwd = 0;
151 heredoclist = 0;
152 doprompt = interact;
153 if (doprompt)
154 setprompt(doprompt);
155 needprompt = 0;
156 return list(1);
157 }
158
159
160 STATIC union node *
list(int nlflag)161 list(int nlflag)
162 {
163 int chknl = nlflag & 1 ? 0 : CHKNL;
164 union node *n1, *n2, *n3;
165 int tok;
166
167 n1 = NULL;
168 for (;;) {
169 checkkwd = chknl | CHKKWD | CHKALIAS;
170 tok = readtoken();
171 switch (tok) {
172 case TNL:
173 parseheredoc();
174 return n1;
175
176 case TEOF:
177 if (!n1 && !chknl)
178 n1 = NEOF;
179 out_eof:
180 parseheredoc();
181 tokpushback++;
182 lasttoken = TEOF;
183 return n1;
184 }
185
186 tokpushback++;
187 if (nlflag == 2 && tokendlist[tok])
188 return n1;
189 nlflag |= 2;
190
191 n2 = andor();
192 tok = readtoken();
193 if (tok == TBACKGND) {
194 if (n2->type == NPIPE) {
195 n2->npipe.backgnd = 1;
196 } else {
197 if (n2->type != NREDIR) {
198 n3 = stalloc(sizeof(struct nredir));
199 n3->nredir.n = n2;
200 n3->nredir.redirect = NULL;
201 n2 = n3;
202 }
203 n2->type = NBACKGND;
204 }
205 }
206 if (n1 == NULL) {
207 n1 = n2;
208 }
209 else {
210 n3 = (union node *)stalloc(sizeof (struct nbinary));
211 n3->type = NSEMI;
212 n3->nbinary.ch1 = n1;
213 n3->nbinary.ch2 = n2;
214 n1 = n3;
215 }
216 switch (tok) {
217 case TEOF:
218 goto out_eof;
219 case TNL:
220 tokpushback++;
221 /* fall through */
222 case TBACKGND:
223 case TSEMI:
224 break;
225 default:
226 if (!chknl)
227 synexpect(-1);
228 tokpushback++;
229 return n1;
230 }
231 }
232 }
233
234
235
236 STATIC union node *
andor(void)237 andor(void)
238 {
239 union node *n1, *n2, *n3;
240 int t;
241
242 n1 = pipeline();
243 for (;;) {
244 if ((t = readtoken()) == TAND) {
245 t = NAND;
246 } else if (t == TOR) {
247 t = NOR;
248 } else {
249 tokpushback++;
250 return n1;
251 }
252 checkkwd = CHKNL | CHKKWD | CHKALIAS;
253 n2 = pipeline();
254 n3 = (union node *)stalloc(sizeof (struct nbinary));
255 n3->type = t;
256 n3->nbinary.ch1 = n1;
257 n3->nbinary.ch2 = n2;
258 n1 = n3;
259 }
260 }
261
262
263
264 STATIC union node *
pipeline(void)265 pipeline(void)
266 {
267 union node *n1, *n2, *pipenode;
268 struct nodelist *lp, *prev;
269 int negate;
270
271 negate = 0;
272 TRACE(("pipeline: entered\n"));
273 if (readtoken() == TNOT) {
274 negate = !negate;
275 checkkwd = CHKKWD | CHKALIAS;
276 } else
277 tokpushback++;
278 n1 = command();
279 if (readtoken() == TPIPE) {
280 pipenode = (union node *)stalloc(sizeof (struct npipe));
281 pipenode->type = NPIPE;
282 pipenode->npipe.backgnd = 0;
283 lp = (struct nodelist *)stalloc(sizeof (struct nodelist));
284 pipenode->npipe.cmdlist = lp;
285 lp->n = n1;
286 do {
287 prev = lp;
288 lp = (struct nodelist *)stalloc(sizeof (struct nodelist));
289 checkkwd = CHKNL | CHKKWD | CHKALIAS;
290 lp->n = command();
291 prev->next = lp;
292 } while (readtoken() == TPIPE);
293 lp->next = NULL;
294 n1 = pipenode;
295 }
296 tokpushback++;
297 if (negate) {
298 n2 = (union node *)stalloc(sizeof (struct nnot));
299 n2->type = NNOT;
300 n2->nnot.com = n1;
301 return n2;
302 } else
303 return n1;
304 }
305
306
307
308 STATIC union node *
command(void)309 command(void)
310 {
311 union node *n1, *n2;
312 union node *ap, **app;
313 union node *cp, **cpp;
314 union node *redir, **rpp;
315 union node **rpp2;
316 int t;
317 int savelinno;
318
319 redir = NULL;
320 rpp2 = &redir;
321
322 savelinno = plinno;
323
324 switch (readtoken()) {
325 default:
326 synexpect(-1);
327 /* NOTREACHED */
328 case TIF:
329 n1 = (union node *)stalloc(sizeof (struct nif));
330 n1->type = NIF;
331 n1->nif.test = list(0);
332 if (readtoken() != TTHEN)
333 synexpect(TTHEN);
334 n1->nif.ifpart = list(0);
335 n2 = n1;
336 while (readtoken() == TELIF) {
337 n2->nif.elsepart = (union node *)stalloc(sizeof (struct nif));
338 n2 = n2->nif.elsepart;
339 n2->type = NIF;
340 n2->nif.test = list(0);
341 if (readtoken() != TTHEN)
342 synexpect(TTHEN);
343 n2->nif.ifpart = list(0);
344 }
345 if (lasttoken == TELSE)
346 n2->nif.elsepart = list(0);
347 else {
348 n2->nif.elsepart = NULL;
349 tokpushback++;
350 }
351 t = TFI;
352 break;
353 case TWHILE:
354 case TUNTIL: {
355 int got;
356 n1 = (union node *)stalloc(sizeof (struct nbinary));
357 n1->type = (lasttoken == TWHILE)? NWHILE : NUNTIL;
358 n1->nbinary.ch1 = list(0);
359 if ((got=readtoken()) != TDO) {
360 TRACE(("expecting DO got %s %s\n", tokname[got], got == TWORD ? wordtext : ""));
361 synexpect(TDO);
362 }
363 n1->nbinary.ch2 = list(0);
364 t = TDONE;
365 break;
366 }
367 case TFOR:
368 if (readtoken() != TWORD || quoteflag || ! goodname(wordtext))
369 synerror("Bad for loop variable");
370 n1 = (union node *)stalloc(sizeof (struct nfor));
371 n1->type = NFOR;
372 n1->nfor.linno = savelinno;
373 n1->nfor.var = wordtext;
374 checkkwd = CHKNL | CHKKWD | CHKALIAS;
375 if (readtoken() == TIN) {
376 app = ≈
377 while (readtoken() == TWORD) {
378 n2 = (union node *)stalloc(sizeof (struct narg));
379 n2->type = NARG;
380 n2->narg.text = wordtext;
381 n2->narg.backquote = backquotelist;
382 *app = n2;
383 app = &n2->narg.next;
384 }
385 *app = NULL;
386 n1->nfor.args = ap;
387 if (lasttoken != TNL && lasttoken != TSEMI)
388 synexpect(-1);
389 } else {
390 n2 = (union node *)stalloc(sizeof (struct narg));
391 n2->type = NARG;
392 n2->narg.text = (char *)dolatstr;
393 n2->narg.backquote = NULL;
394 n2->narg.next = NULL;
395 n1->nfor.args = n2;
396 /*
397 * Newline or semicolon here is optional (but note
398 * that the original Bourne shell only allowed NL).
399 */
400 if (lasttoken != TSEMI)
401 tokpushback++;
402 }
403 checkkwd = CHKNL | CHKKWD | CHKALIAS;
404 if (readtoken() != TDO)
405 synexpect(TDO);
406 n1->nfor.body = list(0);
407 t = TDONE;
408 break;
409 case TCASE:
410 n1 = (union node *)stalloc(sizeof (struct ncase));
411 n1->type = NCASE;
412 n1->ncase.linno = savelinno;
413 if (readtoken() != TWORD)
414 synexpect(TWORD);
415 n1->ncase.expr = n2 = (union node *)stalloc(sizeof (struct narg));
416 n2->type = NARG;
417 n2->narg.text = wordtext;
418 n2->narg.backquote = backquotelist;
419 n2->narg.next = NULL;
420 checkkwd = CHKNL | CHKKWD | CHKALIAS;
421 if (readtoken() != TIN)
422 synexpect(TIN);
423 cpp = &n1->ncase.cases;
424 next_case:
425 checkkwd = CHKNL | CHKKWD;
426 t = readtoken();
427 while(t != TESAC) {
428 if (lasttoken == TLP)
429 readtoken();
430 *cpp = cp = (union node *)stalloc(sizeof (struct nclist));
431 cp->type = NCLIST;
432 app = &cp->nclist.pattern;
433 for (;;) {
434 *app = ap = (union node *)stalloc(sizeof (struct narg));
435 ap->type = NARG;
436 ap->narg.text = wordtext;
437 ap->narg.backquote = backquotelist;
438 if (readtoken() != TPIPE)
439 break;
440 app = &ap->narg.next;
441 readtoken();
442 }
443 ap->narg.next = NULL;
444 if (lasttoken != TRP)
445 synexpect(TRP);
446 cp->nclist.body = list(2);
447
448 cpp = &cp->nclist.next;
449
450 checkkwd = CHKNL | CHKKWD;
451 if ((t = readtoken()) != TESAC) {
452 if (t != TENDCASE)
453 synexpect(TENDCASE);
454 else
455 goto next_case;
456 }
457 }
458 *cpp = NULL;
459 goto redir;
460 case TLP:
461 n1 = (union node *)stalloc(sizeof (struct nredir));
462 n1->type = NSUBSHELL;
463 n1->nredir.linno = savelinno;
464 n1->nredir.n = list(0);
465 n1->nredir.redirect = NULL;
466 t = TRP;
467 break;
468 case TBEGIN:
469 n1 = list(0);
470 t = TEND;
471 break;
472 case TWORD:
473 case TREDIR:
474 tokpushback++;
475 return simplecmd();
476 }
477
478 if (readtoken() != t)
479 synexpect(t);
480
481 redir:
482 /* Now check for redirection which may follow command */
483 checkkwd = CHKKWD | CHKALIAS;
484 rpp = rpp2;
485 while (readtoken() == TREDIR) {
486 *rpp = n2 = redirnode;
487 rpp = &n2->nfile.next;
488 parsefname();
489 }
490 tokpushback++;
491 *rpp = NULL;
492 if (redir) {
493 if (n1->type != NSUBSHELL) {
494 n2 = (union node *)stalloc(sizeof (struct nredir));
495 n2->type = NREDIR;
496 n2->nredir.linno = savelinno;
497 n2->nredir.n = n1;
498 n1 = n2;
499 }
500 n1->nredir.redirect = redir;
501 }
502
503 return n1;
504 }
505
506
507 STATIC union node *
simplecmd(void)508 simplecmd(void) {
509 union node *args, **app;
510 union node *n = NULL;
511 union node *vars, **vpp;
512 union node **rpp, *redir;
513 int savecheckkwd;
514 int savelinno;
515
516 args = NULL;
517 app = &args;
518 vars = NULL;
519 vpp = &vars;
520 redir = NULL;
521 rpp = &redir;
522
523 savecheckkwd = CHKALIAS;
524 savelinno = plinno;
525 for (;;) {
526 checkkwd = savecheckkwd;
527 switch (readtoken()) {
528 case TWORD:
529 n = (union node *)stalloc(sizeof (struct narg));
530 n->type = NARG;
531 n->narg.text = wordtext;
532 n->narg.backquote = backquotelist;
533 if (savecheckkwd && isassignment(wordtext)) {
534 *vpp = n;
535 vpp = &n->narg.next;
536 } else {
537 *app = n;
538 app = &n->narg.next;
539 savecheckkwd = 0;
540 }
541 break;
542 case TREDIR:
543 *rpp = n = redirnode;
544 rpp = &n->nfile.next;
545 parsefname(); /* read name of redirection file */
546 break;
547 case TLP:
548 if (
549 args && app == &args->narg.next &&
550 !vars && !redir
551 ) {
552 struct builtincmd *bcmd;
553 const char *name;
554
555 /* We have a function */
556 if (readtoken() != TRP)
557 synexpect(TRP);
558 name = n->narg.text;
559 if (
560 !goodname(name) || (
561 (bcmd = find_builtin(name)) &&
562 bcmd->flags & BUILTIN_SPECIAL
563 )
564 )
565 synerror("Bad function name");
566 n->type = NDEFUN;
567 checkkwd = CHKNL | CHKKWD | CHKALIAS;
568 n->ndefun.text = n->narg.text;
569 n->ndefun.linno = plinno;
570 n->ndefun.body = command();
571 return n;
572 }
573 /* fall through */
574 default:
575 tokpushback++;
576 goto out;
577 }
578 }
579 out:
580 *app = NULL;
581 *vpp = NULL;
582 *rpp = NULL;
583 n = (union node *)stalloc(sizeof (struct ncmd));
584 n->type = NCMD;
585 n->ncmd.linno = savelinno;
586 n->ncmd.args = args;
587 n->ncmd.assign = vars;
588 n->ncmd.redirect = redir;
589 return n;
590 }
591
592 STATIC union node *
makename(void)593 makename(void)
594 {
595 union node *n;
596
597 n = (union node *)stalloc(sizeof (struct narg));
598 n->type = NARG;
599 n->narg.next = NULL;
600 n->narg.text = wordtext;
601 n->narg.backquote = backquotelist;
602 return n;
603 }
604
fixredir(union node * n,const char * text,int err)605 void fixredir(union node *n, const char *text, int err)
606 {
607 TRACE(("Fix redir %s %d\n", text, err));
608 if (!err)
609 n->ndup.vname = NULL;
610
611 if (is_digit(text[0]) && text[1] == '\0')
612 n->ndup.dupfd = digit_val(text[0]);
613 else if (text[0] == '-' && text[1] == '\0')
614 n->ndup.dupfd = -1;
615 else {
616
617 if (err)
618 synerror("Bad fd number");
619 else
620 n->ndup.vname = makename();
621 }
622 }
623
624
625 STATIC void
parsefname(void)626 parsefname(void)
627 {
628 union node *n = redirnode;
629
630 if (n->type == NHERE)
631 checkkwd = CHKEOFMARK;
632 if (readtoken() != TWORD)
633 synexpect(-1);
634 if (n->type == NHERE) {
635 struct heredoc *here = heredoc;
636 struct heredoc *p;
637
638 if (quoteflag == 0)
639 n->type = NXHERE;
640 TRACE(("Here document %d\n", n->type));
641 rmescapes(wordtext);
642 here->eofmark = wordtext;
643 here->next = NULL;
644 if (heredoclist == NULL)
645 heredoclist = here;
646 else {
647 for (p = heredoclist ; p->next ; p = p->next);
648 p->next = here;
649 }
650 } else if (n->type == NTOFD || n->type == NFROMFD) {
651 fixredir(n, wordtext, 0);
652 } else {
653 n->nfile.fname = makename();
654 }
655 }
656
657
658 /*
659 * Input any here documents.
660 */
661
662 STATIC void
parseheredoc(void)663 parseheredoc(void)
664 {
665 struct heredoc *here;
666 union node *n;
667
668 here = heredoclist;
669 heredoclist = 0;
670
671 while (here) {
672 if (needprompt) {
673 setprompt(2);
674 }
675 if (here->here->type == NHERE)
676 readtoken1(pgetc(), SQSYNTAX, here->eofmark, here->striptabs);
677 else
678 readtoken1(pgetc_eatbnl(), DQSYNTAX, here->eofmark, here->striptabs);
679 n = (union node *)stalloc(sizeof (struct narg));
680 n->narg.type = NARG;
681 n->narg.next = NULL;
682 n->narg.text = wordtext;
683 n->narg.backquote = backquotelist;
684 here->here->nhere.doc = n;
685 here = here->next;
686 }
687 }
688
689 STATIC int
readtoken(void)690 readtoken(void)
691 {
692 int t;
693 int kwd = checkkwd;
694 #ifdef DEBUG
695 int alreadyseen = tokpushback;
696 #endif
697
698 top:
699 t = xxreadtoken();
700
701 /*
702 * eat newlines
703 */
704 if (kwd & CHKNL) {
705 while (t == TNL) {
706 parseheredoc();
707 checkkwd = 0;
708 t = xxreadtoken();
709 }
710 }
711
712 kwd |= checkkwd;
713 checkkwd = 0;
714
715 if (t != TWORD || quoteflag) {
716 goto out;
717 }
718
719 /*
720 * check for keywords
721 */
722 if (kwd & CHKKWD) {
723 const char *const *pp;
724
725 if ((pp = findkwd(wordtext))) {
726 lasttoken = t = pp - parsekwd + KWDOFFSET;
727 TRACE(("keyword %s recognized\n", tokname[t]));
728 goto out;
729 }
730 }
731
732 if (kwd & CHKALIAS) {
733 struct alias *ap;
734 if ((ap = lookupalias(wordtext, 1)) != NULL) {
735 if (*ap->val) {
736 pushstring(ap->val, ap);
737 }
738 goto top;
739 }
740 }
741 out:
742 #ifdef DEBUG
743 if (!alreadyseen)
744 TRACE(("token %s %s\n", tokname[t], t == TWORD ? wordtext : ""));
745 else
746 TRACE(("reread token %s %s\n", tokname[t], t == TWORD ? wordtext : ""));
747 #endif
748 return (t);
749 }
750
nlprompt(void)751 static void nlprompt(void)
752 {
753 plinno++;
754 if (doprompt)
755 setprompt(2);
756 }
757
nlnoprompt(void)758 static void nlnoprompt(void)
759 {
760 plinno++;
761 needprompt = doprompt;
762 }
763
764
765 /*
766 * Read the next input token.
767 * If the token is a word, we set backquotelist to the list of cmds in
768 * backquotes. We set quoteflag to true if any part of the word was
769 * quoted.
770 * If the token is TREDIR, then we set redirnode to a structure containing
771 * the redirection.
772 *
773 * [Change comment: here documents and internal procedures]
774 * [Readtoken shouldn't have any arguments. Perhaps we should make the
775 * word parsing code into a separate routine. In this case, readtoken
776 * doesn't need to have any internal procedures, but parseword does.
777 * We could also make parseoperator in essence the main routine, and
778 * have parseword (readtoken1?) handle both words and redirection.]
779 */
780
781 #define RETURN(token) return lasttoken = token
782
783 STATIC int
xxreadtoken(void)784 xxreadtoken(void)
785 {
786 int c;
787
788 if (tokpushback) {
789 tokpushback = 0;
790 return lasttoken;
791 }
792 if (needprompt) {
793 setprompt(2);
794 }
795 for (;;) { /* until token or start of word found */
796 c = pgetc_eatbnl();
797 switch (c) {
798 case ' ': case '\t':
799 case PEOA:
800 continue;
801 case '#':
802 while ((c = pgetc()) != '\n' && c != PEOF);
803 pungetc();
804 continue;
805 case '\n':
806 nlnoprompt();
807 RETURN(TNL);
808 case PEOF:
809 RETURN(TEOF);
810 case '&':
811 if (pgetc_eatbnl() == '&')
812 RETURN(TAND);
813 pungetc();
814 RETURN(TBACKGND);
815 case '|':
816 if (pgetc_eatbnl() == '|')
817 RETURN(TOR);
818 pungetc();
819 RETURN(TPIPE);
820 case ';':
821 if (pgetc_eatbnl() == ';')
822 RETURN(TENDCASE);
823 pungetc();
824 RETURN(TSEMI);
825 case '(':
826 RETURN(TLP);
827 case ')':
828 RETURN(TRP);
829 }
830 break;
831 }
832 return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
833 #undef RETURN
834 }
835
pgetc_eatbnl(void)836 static int pgetc_eatbnl(void)
837 {
838 int c;
839
840 while ((c = pgetc()) == '\\') {
841 if (pgetc2() != '\n') {
842 pungetc();
843 break;
844 }
845
846 nlprompt();
847 }
848
849 return c;
850 }
851
pgetc_top(struct synstack * stack)852 static int pgetc_top(struct synstack *stack)
853 {
854 return stack->syntax == SQSYNTAX ? pgetc() : pgetc_eatbnl();
855 }
856
synstack_push(struct synstack ** stack,struct synstack * next,const char * syntax)857 static void synstack_push(struct synstack **stack, struct synstack *next,
858 const char *syntax)
859 {
860 memset(next, 0, sizeof(*next));
861 next->syntax = syntax;
862 next->next = *stack;
863 (*stack)->prev = next;
864 *stack = next;
865 }
866
synstack_pop(struct synstack ** stack)867 static void synstack_pop(struct synstack **stack)
868 {
869 *stack = (*stack)->next;
870 }
871
872
873
874 /*
875 * If eofmark is NULL, read a word or a redirection symbol. If eofmark
876 * is not NULL, read a here document. In the latter case, eofmark is the
877 * word which marks the end of the document and striptabs is true if
878 * leading tabs should be stripped from the document. The argument firstc
879 * is the first character of the input token or document.
880 *
881 * Because C does not have internal subroutines, I have simulated them
882 * using goto's to implement the subroutine linkage. The following macros
883 * will run code that appears at the end of readtoken1.
884 */
885
886 #define CHECKEND() {goto checkend; checkend_return:;}
887 #define PARSEREDIR() {goto parseredir; parseredir_return:;}
888 #define PARSESUB() {goto parsesub; parsesub_return:;}
889 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
890 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
891 #define PARSEARITH() {goto parsearith; parsearith_return:;}
892
893 STATIC int
readtoken1(int firstc,char const * syntax,char * eofmark,int striptabs)894 readtoken1(int firstc, char const *syntax, char *eofmark, int striptabs)
895 {
896 int c = firstc;
897 char *out;
898 size_t len;
899 struct nodelist *bqlist;
900 int quotef;
901 int oldstyle;
902 /* syntax stack */
903 struct synstack synbase = { .syntax = syntax };
904 struct synstack *synstack = &synbase;
905
906 if (syntax == DQSYNTAX)
907 synstack->dblquote = 1;
908 quotef = 0;
909 bqlist = NULL;
910
911 STARTSTACKSTR(out);
912 loop: { /* for each line, until end of word */
913 #if ATTY
914 if (c == '\034' && doprompt
915 && attyset() && ! equal(termval(), "emacs")) {
916 attyline();
917 if (synstack->syntax == BASESYNTAX)
918 return readtoken();
919 c = pgetc_top(synstack);
920 goto loop;
921 }
922 #endif
923 CHECKEND(); /* set c to PEOF if at end of here document */
924 for (;;) { /* until end of line or end of word */
925 CHECKSTRSPACE(4, out); /* permit 4 calls to USTPUTC */
926 switch(synstack->syntax[c]) {
927 case CNL: /* '\n' */
928 if (synstack->syntax == BASESYNTAX &&
929 !synstack->varnest)
930 goto endword; /* exit outer loop */
931 USTPUTC(c, out);
932 nlprompt();
933 c = pgetc_top(synstack);
934 goto loop; /* continue outer loop */
935 case CWORD:
936 USTPUTC(c, out);
937 break;
938 case CCTL:
939 if ((!eofmark) | synstack->dblquote |
940 synstack->varnest)
941 USTPUTC(CTLESC, out);
942 USTPUTC(c, out);
943 break;
944 /* backslash */
945 case CBACK:
946 c = pgetc2();
947 if (c == PEOF) {
948 USTPUTC(CTLESC, out);
949 USTPUTC('\\', out);
950 pungetc();
951 } else {
952 if (
953 synstack->dblquote &&
954 c != '\\' && c != '`' &&
955 c != '$' && (
956 c != '"' ||
957 (eofmark != NULL &&
958 !synstack->varnest)
959 ) && (
960 c != '}' ||
961 !synstack->varnest
962 )
963 ) {
964 USTPUTC(CTLESC, out);
965 USTPUTC('\\', out);
966 }
967 USTPUTC(CTLESC, out);
968 USTPUTC(c, out);
969 quotef++;
970 }
971 break;
972 case CSQUOTE:
973 synstack->syntax = SQSYNTAX;
974 quotemark:
975 if (eofmark == NULL) {
976 USTPUTC(CTLQUOTEMARK, out);
977 }
978 break;
979 case CDQUOTE:
980 synstack->syntax = DQSYNTAX;
981 synstack->dblquote = 1;
982 toggledq:
983 if (synstack->varnest)
984 synstack->innerdq ^= 1;
985 goto quotemark;
986 case CENDQUOTE:
987 if (eofmark && !synstack->varnest) {
988 USTPUTC(c, out);
989 break;
990 }
991
992 if (synstack->dqvarnest == 0) {
993 synstack->syntax = BASESYNTAX;
994 synstack->dblquote = 0;
995 }
996
997 quotef++;
998
999 if (c == '"')
1000 goto toggledq;
1001
1002 goto quotemark;
1003 case CVAR: /* '$' */
1004 PARSESUB(); /* parse substitution */
1005 break;
1006 case CENDVAR: /* '}' */
1007 if (!synstack->innerdq &&
1008 synstack->varnest > 0) {
1009 if (!--synstack->varnest &&
1010 synstack->varpushed)
1011 synstack_pop(&synstack);
1012 else if (synstack->dqvarnest > 0)
1013 synstack->dqvarnest--;
1014 USTPUTC(CTLENDVAR, out);
1015 } else {
1016 USTPUTC(c, out);
1017 }
1018 break;
1019 case CLP: /* '(' in arithmetic */
1020 synstack->parenlevel++;
1021 USTPUTC(c, out);
1022 break;
1023 case CRP: /* ')' in arithmetic */
1024 if (synstack->parenlevel > 0) {
1025 USTPUTC(c, out);
1026 --synstack->parenlevel;
1027 } else {
1028 if (pgetc_eatbnl() == ')') {
1029 USTPUTC(CTLENDARI, out);
1030 synstack_pop(&synstack);
1031 } else {
1032 /*
1033 * unbalanced parens
1034 * (don't 2nd guess - no error)
1035 */
1036 pungetc();
1037 USTPUTC(')', out);
1038 }
1039 }
1040 break;
1041 case CBQUOTE: /* '`' */
1042 if (checkkwd & CHKEOFMARK) {
1043 USTPUTC('`', out);
1044 break;
1045 }
1046
1047 PARSEBACKQOLD();
1048 break;
1049 case CEOF:
1050 goto endword; /* exit outer loop */
1051 case CIGN:
1052 break;
1053 default:
1054 if (synstack->varnest == 0)
1055 goto endword; /* exit outer loop */
1056 if (c != PEOA) {
1057 USTPUTC(c, out);
1058 }
1059 }
1060 c = pgetc_top(synstack);
1061 }
1062 }
1063 endword:
1064 if (synstack->syntax == ARISYNTAX)
1065 synerror("Missing '))'");
1066 if (synstack->syntax != BASESYNTAX && eofmark == NULL)
1067 synerror("Unterminated quoted string");
1068 if (synstack->varnest != 0) {
1069 /* { */
1070 synerror("Missing '}'");
1071 }
1072 USTPUTC('\0', out);
1073 len = out - (char *)stackblock();
1074 out = stackblock();
1075 if (eofmark == NULL) {
1076 if ((c == '>' || c == '<')
1077 && quotef == 0
1078 && len <= 2
1079 && (*out == '\0' || is_digit(*out))) {
1080 PARSEREDIR();
1081 return lasttoken = TREDIR;
1082 } else {
1083 pungetc();
1084 }
1085 }
1086 quoteflag = quotef;
1087 backquotelist = bqlist;
1088 grabstackblock(len);
1089 wordtext = out;
1090 return lasttoken = TWORD;
1091 /* end of readtoken routine */
1092
1093
1094
1095 /*
1096 * Check to see whether we are at the end of the here document. When this
1097 * is called, c is set to the first character of the next input line. If
1098 * we are at the end of the here document, this routine sets the c to PEOF.
1099 */
1100
1101 checkend: {
1102 if (realeofmark(eofmark)) {
1103 int markloc;
1104 char *p;
1105
1106 if (c == PEOA) {
1107 c = pgetc2();
1108 }
1109 if (striptabs) {
1110 while (c == '\t') {
1111 c = pgetc2();
1112 }
1113 }
1114
1115 markloc = out - (char *)stackblock();
1116 for (p = eofmark; STPUTC(c, out), *p; p++) {
1117 if (c != *p)
1118 goto more_heredoc;
1119
1120 c = pgetc2();
1121 }
1122
1123 if (c == '\n' || c == PEOF) {
1124 c = PEOF;
1125 nlnoprompt();
1126 } else {
1127 int len;
1128
1129 more_heredoc:
1130 p = (char *)stackblock() + markloc + 1;
1131 len = out - p;
1132
1133 if (len) {
1134 len -= c < 0;
1135 c = p[-1];
1136
1137 if (len) {
1138 char *str;
1139
1140 str = alloca(len + 1);
1141 *(char *)mempcpy(str, p, len) = 0;
1142
1143 pushstring(str, NULL);
1144 }
1145 }
1146 }
1147
1148 STADJUST((char *)stackblock() + markloc - out, out);
1149 }
1150 goto checkend_return;
1151 }
1152
1153
1154 /*
1155 * Parse a redirection operator. The variable "out" points to a string
1156 * specifying the fd to be redirected. The variable "c" contains the
1157 * first character of the redirection operator.
1158 */
1159
1160 parseredir: {
1161 char fd = *out;
1162 union node *np;
1163
1164 np = (union node *)stalloc(sizeof (struct nfile));
1165 if (c == '>') {
1166 np->nfile.fd = 1;
1167 c = pgetc_eatbnl();
1168 if (c == '>')
1169 np->type = NAPPEND;
1170 else if (c == '|')
1171 np->type = NCLOBBER;
1172 else if (c == '&')
1173 np->type = NTOFD;
1174 else {
1175 np->type = NTO;
1176 pungetc();
1177 }
1178 } else { /* c == '<' */
1179 np->nfile.fd = 0;
1180 switch (c = pgetc_eatbnl()) {
1181 case '<':
1182 if (sizeof (struct nfile) != sizeof (struct nhere)) {
1183 np = (union node *)stalloc(sizeof (struct nhere));
1184 np->nfile.fd = 0;
1185 }
1186 np->type = NHERE;
1187 heredoc = (struct heredoc *)stalloc(sizeof (struct heredoc));
1188 heredoc->here = np;
1189 if ((c = pgetc_eatbnl()) == '-') {
1190 heredoc->striptabs = 1;
1191 } else {
1192 heredoc->striptabs = 0;
1193 pungetc();
1194 }
1195 break;
1196
1197 case '&':
1198 np->type = NFROMFD;
1199 break;
1200
1201 case '>':
1202 np->type = NFROMTO;
1203 break;
1204
1205 default:
1206 np->type = NFROM;
1207 pungetc();
1208 break;
1209 }
1210 }
1211 if (fd != '\0')
1212 np->nfile.fd = digit_val(fd);
1213 redirnode = np;
1214 goto parseredir_return;
1215 }
1216
1217
1218 /*
1219 * Parse a substitution. At this point, we have read the dollar sign
1220 * and nothing else.
1221 */
1222
1223 parsesub: {
1224 int subtype;
1225 int typeloc;
1226 char *p;
1227 static const char types[] = "}-+?=";
1228
1229 c = pgetc_eatbnl();
1230 if (
1231 (checkkwd & CHKEOFMARK) ||
1232 c <= PEOA ||
1233 (c != '(' && c != '{' && !is_name(c) && !is_special(c))
1234 ) {
1235 USTPUTC('$', out);
1236 pungetc();
1237 } else if (c == '(') { /* $(command) or $((arith)) */
1238 if (pgetc_eatbnl() == '(') {
1239 PARSEARITH();
1240 } else {
1241 pungetc();
1242 PARSEBACKQNEW();
1243 }
1244 } else {
1245 const char *newsyn = synstack->syntax;
1246
1247 USTPUTC(CTLVAR, out);
1248 typeloc = out - (char *)stackblock();
1249 STADJUST(1, out);
1250 subtype = VSNORMAL;
1251 if (likely(c == '{')) {
1252 c = pgetc_eatbnl();
1253 subtype = 0;
1254 }
1255 varname:
1256 if (is_name(c)) {
1257 do {
1258 STPUTC(c, out);
1259 c = pgetc_eatbnl();
1260 } while (is_in_name(c));
1261 } else if (is_digit(c)) {
1262 do {
1263 STPUTC(c, out);
1264 c = pgetc_eatbnl();
1265 } while ((subtype <= 0 || subtype >= VSLENGTH) &&
1266 is_digit(c));
1267 } else if (c != '}') {
1268 int cc = c;
1269
1270 c = pgetc_eatbnl();
1271
1272 if (!subtype && cc == '#') {
1273 subtype = VSLENGTH;
1274
1275 if (c == '_' || isalnum(c))
1276 goto varname;
1277
1278 cc = c;
1279 c = pgetc_eatbnl();
1280 if (cc == '}' || c != '}') {
1281 pungetc();
1282 subtype = 0;
1283 c = cc;
1284 cc = '#';
1285 }
1286 }
1287
1288 if (!is_special(cc)) {
1289 if (subtype == VSLENGTH)
1290 subtype = 0;
1291 goto badsub;
1292 }
1293
1294 USTPUTC(cc, out);
1295 } else
1296 goto badsub;
1297
1298 if (subtype == 0) {
1299 int cc = c;
1300
1301 switch (c) {
1302 case ':':
1303 subtype = VSNUL;
1304 c = pgetc_eatbnl();
1305 /*FALLTHROUGH*/
1306 default:
1307 p = strchr(types, c);
1308 if (p == NULL)
1309 break;
1310 subtype |= p - types + VSNORMAL;
1311 break;
1312 case '%':
1313 case '#':
1314 subtype = c == '#' ? VSTRIMLEFT :
1315 VSTRIMRIGHT;
1316 c = pgetc_eatbnl();
1317 if (c == cc)
1318 subtype++;
1319 else
1320 pungetc();
1321
1322 newsyn = BASESYNTAX;
1323 break;
1324 }
1325 } else {
1326 if (subtype == VSLENGTH && c != '}')
1327 subtype = 0;
1328 badsub:
1329 pungetc();
1330 }
1331
1332 if (newsyn == ARISYNTAX)
1333 newsyn = DQSYNTAX;
1334
1335 if ((newsyn != synstack->syntax || synstack->innerdq) &&
1336 subtype != VSNORMAL) {
1337 synstack_push(&synstack,
1338 synstack->prev ?:
1339 alloca(sizeof(*synstack)),
1340 newsyn);
1341
1342 synstack->varpushed++;
1343 synstack->dblquote = newsyn != BASESYNTAX;
1344 }
1345
1346 *((char *)stackblock() + typeloc) = subtype;
1347 if (subtype != VSNORMAL) {
1348 synstack->varnest++;
1349 if (synstack->dblquote)
1350 synstack->dqvarnest++;
1351 }
1352 STPUTC('=', out);
1353 }
1354 goto parsesub_return;
1355 }
1356
1357
1358 /*
1359 * Called to parse command substitutions. Newstyle is set if the command
1360 * is enclosed inside $(...); nlpp is a pointer to the head of the linked
1361 * list of commands (passed by reference), and savelen is the number of
1362 * characters on the top of the stack which must be preserved.
1363 */
1364
1365 parsebackq: {
1366 struct nodelist **nlpp;
1367 union node *n;
1368 char *str;
1369 size_t savelen;
1370 struct heredoc *saveheredoclist;
1371 int uninitialized_var(saveprompt);
1372
1373 str = NULL;
1374 savelen = out - (char *)stackblock();
1375 if (savelen > 0) {
1376 str = alloca(savelen);
1377 memcpy(str, stackblock(), savelen);
1378 }
1379 if (oldstyle) {
1380 /* We must read until the closing backquote, giving special
1381 treatment to some slashes, and then push the string and
1382 reread it as input, interpreting it normally. */
1383 char *pout;
1384 int pc;
1385 size_t psavelen;
1386 char *pstr;
1387
1388
1389 STARTSTACKSTR(pout);
1390 for (;;) {
1391 if (needprompt) {
1392 setprompt(2);
1393 }
1394 switch (pc = pgetc_eatbnl()) {
1395 case '`':
1396 goto done;
1397
1398 case '\\':
1399 pc = pgetc();
1400 if (pc != '\\' && pc != '`' && pc != '$'
1401 && (!synstack->dblquote || pc != '"'))
1402 STPUTC('\\', pout);
1403 if (pc > PEOA) {
1404 break;
1405 }
1406 /* fall through */
1407
1408 case PEOF:
1409 case PEOA:
1410 synerror("EOF in backquote substitution");
1411
1412 case '\n':
1413 nlnoprompt();
1414 break;
1415
1416 default:
1417 break;
1418 }
1419 STPUTC(pc, pout);
1420 }
1421 done:
1422 STPUTC('\0', pout);
1423 psavelen = pout - (char *)stackblock();
1424 if (psavelen > 0) {
1425 pstr = grabstackstr(pout);
1426 setinputstring(pstr);
1427 }
1428 }
1429 nlpp = &bqlist;
1430 while (*nlpp)
1431 nlpp = &(*nlpp)->next;
1432 *nlpp = (struct nodelist *)stalloc(sizeof (struct nodelist));
1433 (*nlpp)->next = NULL;
1434
1435 saveheredoclist = heredoclist;
1436 heredoclist = NULL;
1437
1438 if (oldstyle) {
1439 saveprompt = doprompt;
1440 doprompt = 0;
1441 }
1442
1443 n = list(2);
1444
1445 if (oldstyle)
1446 doprompt = saveprompt;
1447 else {
1448 if (readtoken() != TRP)
1449 synexpect(TRP);
1450 setinputstring(nullstr);
1451 }
1452
1453 parseheredoc();
1454 heredoclist = saveheredoclist;
1455
1456 (*nlpp)->n = n;
1457 /* Start reading from old file again. */
1458 popfile();
1459 /* Ignore any pushed back tokens left from the backquote parsing. */
1460 if (oldstyle)
1461 tokpushback = 0;
1462 out = growstackto(savelen + 1);
1463 if (str) {
1464 memcpy(out, str, savelen);
1465 STADJUST(savelen, out);
1466 }
1467 USTPUTC(CTLBACKQ, out);
1468 if (oldstyle)
1469 goto parsebackq_oldreturn;
1470 else
1471 goto parsebackq_newreturn;
1472 }
1473
1474 /*
1475 * Parse an arithmetic expansion (indicate start of one and set state)
1476 */
1477 parsearith: {
1478
1479 synstack_push(&synstack,
1480 synstack->prev ?: alloca(sizeof(*synstack)),
1481 ARISYNTAX);
1482 synstack->dblquote = 1;
1483 USTPUTC(CTLARI, out);
1484 goto parsearith_return;
1485 }
1486
1487 } /* end of readtoken */
1488
1489
1490
1491 #ifdef mkinit
1492 INCLUDE "parser.h"
1493 #endif
1494
1495
1496 /*
1497 * Return of a legal variable name (a letter or underscore followed by zero or
1498 * more letters, underscores, and digits).
1499 */
1500
1501 char *
1502 endofname(const char *name)
1503 {
1504 char *p;
1505
1506 p = (char *) name;
1507 if (! is_name(*p))
1508 return p;
1509 while (*++p) {
1510 if (! is_in_name(*p))
1511 break;
1512 }
1513 return p;
1514 }
1515
1516
1517 /*
1518 * Called when an unexpected token is read during the parse. The argument
1519 * is the token that is expected, or -1 if more than one type of token can
1520 * occur at this point.
1521 */
1522
1523 STATIC void
synexpect(int token)1524 synexpect(int token)
1525 {
1526 char msg[64];
1527
1528 if (token >= 0) {
1529 fmtstr(msg, 64, "%s unexpected (expecting %s)",
1530 tokname[lasttoken], tokname[token]);
1531 } else {
1532 fmtstr(msg, 64, "%s unexpected", tokname[lasttoken]);
1533 }
1534 synerror(msg);
1535 /* NOTREACHED */
1536 }
1537
1538
1539 STATIC void
synerror(const char * msg)1540 synerror(const char *msg)
1541 {
1542 errlinno = plinno;
1543 sh_error("Syntax error: %s", msg);
1544 /* NOTREACHED */
1545 }
1546
1547 STATIC void
setprompt(int which)1548 setprompt(int which)
1549 {
1550 struct stackmark smark;
1551 int show;
1552
1553 needprompt = 0;
1554 whichprompt = which;
1555
1556 #ifdef SMALL
1557 show = 1;
1558 #else
1559 show = !el;
1560 #endif
1561 if (show) {
1562 pushstackmark(&smark, stackblocksize());
1563 out2str(getprompt(NULL));
1564 popstackmark(&smark);
1565 }
1566 }
1567
1568 const char *
expandstr(const char * ps)1569 expandstr(const char *ps)
1570 {
1571 struct parsefile *file_stop;
1572 struct jmploc *volatile savehandler;
1573 struct heredoc *saveheredoclist;
1574 const char *result;
1575 int saveprompt;
1576 struct jmploc jmploc;
1577 union node n;
1578 int err;
1579
1580 file_stop = parsefile;
1581
1582 /* XXX Fix (char *) cast. */
1583 setinputstring((char *)ps);
1584
1585 saveheredoclist = heredoclist;
1586 heredoclist = NULL;
1587 saveprompt = doprompt;
1588 doprompt = 0;
1589 result = ps;
1590 savehandler = handler;
1591 if (unlikely(err = setjmp(jmploc.loc)))
1592 goto out;
1593 handler = &jmploc;
1594
1595 readtoken1(pgetc_eatbnl(), DQSYNTAX, FAKEEOFMARK, 0);
1596
1597 n.narg.type = NARG;
1598 n.narg.next = NULL;
1599 n.narg.text = wordtext;
1600 n.narg.backquote = backquotelist;
1601
1602 expandarg(&n, NULL, EXP_QUOTED);
1603 result = stackblock();
1604
1605 out:
1606 handler = savehandler;
1607 if (err && exception != EXERROR)
1608 longjmp(handler->loc, 1);
1609
1610 doprompt = saveprompt;
1611 unwindfiles(file_stop);
1612 heredoclist = saveheredoclist;
1613
1614 return result;
1615 }
1616
1617 /*
1618 * called by editline -- any expansions to the prompt
1619 * should be added here.
1620 */
1621 const char *
getprompt(void * unused)1622 getprompt(void *unused)
1623 {
1624 const char *prompt;
1625
1626 switch (whichprompt) {
1627 default:
1628 #ifdef DEBUG
1629 return "<internal prompt error>";
1630 #endif
1631 case 0:
1632 return nullstr;
1633 case 1:
1634 prompt = ps1val();
1635 break;
1636 case 2:
1637 prompt = ps2val();
1638 break;
1639 }
1640
1641 return expandstr(prompt);
1642 }
1643
1644 const char *const *
findkwd(const char * s)1645 findkwd(const char *s)
1646 {
1647 return findstring(
1648 s, parsekwd, sizeof(parsekwd) / sizeof(const char *)
1649 );
1650 }
1651