sh: Sync with FreeBSD:
[dragonfly.git] / bin / sh / parser.c
blobd4031abb8c1c03e86d6059c79d6140714e3844c1
1 /*-
2 * Copyright (c) 1991, 1993
3 * The Regents of the University of California. All rights reserved.
5 * This code is derived from software contributed to Berkeley by
6 * Kenneth Almquist.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
36 * @(#)parser.c 8.7 (Berkeley) 5/16/95
37 * $FreeBSD: head/bin/sh/parser.c 245382 2013-01-13 19:26:33Z jilles $
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <unistd.h>
44 #include "shell.h"
45 #include "parser.h"
46 #include "nodes.h"
47 #include "expand.h" /* defines rmescapes() */
48 #include "syntax.h"
49 #include "options.h"
50 #include "input.h"
51 #include "output.h"
52 #include "var.h"
53 #include "error.h"
54 #include "memalloc.h"
55 #include "mystring.h"
56 #include "alias.h"
57 #include "show.h"
58 #include "eval.h"
59 #include "exec.h" /* to check for special builtins */
60 #ifndef NO_HISTORY
61 #include "myhistedit.h"
62 #endif
65 * Shell command parser.
68 #define EOFMARKLEN 79
69 #define PROMPTLEN 128
71 /* values of checkkwd variable */
72 #define CHKALIAS 0x1
73 #define CHKKWD 0x2
74 #define CHKNL 0x4
76 /* values returned by readtoken */
77 #include "token.h"
81 struct heredoc {
82 struct heredoc *next; /* next here document in list */
83 union node *here; /* redirection node */
84 char *eofmark; /* string indicating end of input */
85 int striptabs; /* if set, strip leading tabs */
88 struct parser_temp {
89 struct parser_temp *next;
90 void *data;
94 static struct heredoc *heredoclist; /* list of here documents to read */
95 static int doprompt; /* if set, prompt the user */
96 static int needprompt; /* true if interactive and at start of line */
97 static int lasttoken; /* last token read */
98 MKINIT int tokpushback; /* last token pushed back */
99 static char *wordtext; /* text of last word returned by readtoken */
100 MKINIT int checkkwd; /* 1 == check for kwds, 2 == also eat newlines */
101 static struct nodelist *backquotelist;
102 static union node *redirnode;
103 static struct heredoc *heredoc;
104 static int quoteflag; /* set if (part of) last token was quoted */
105 static int startlinno; /* line # where last token started */
106 static int funclinno; /* line # where the current function started */
107 static struct parser_temp *parser_temp;
110 static union node *list(int, int);
111 static union node *andor(void);
112 static union node *pipeline(void);
113 static union node *command(void);
114 static union node *simplecmd(union node **, union node *);
115 static union node *makename(void);
116 static void parsefname(void);
117 static void parseheredoc(void);
118 static int peektoken(void);
119 static int readtoken(void);
120 static int xxreadtoken(void);
121 static int readtoken1(int, char const *, char *, int);
122 static int noexpand(char *);
123 static void synexpect(int) __dead2;
124 static void synerror(const char *) __dead2;
125 static void setprompt(int);
128 static void *
129 parser_temp_alloc(size_t len)
131 struct parser_temp *t;
133 INTOFF;
134 t = ckmalloc(sizeof(*t));
135 t->data = NULL;
136 t->next = parser_temp;
137 parser_temp = t;
138 t->data = ckmalloc(len);
139 INTON;
140 return t->data;
144 static void *
145 parser_temp_realloc(void *ptr, size_t len)
147 struct parser_temp *t;
149 INTOFF;
150 t = parser_temp;
151 if (ptr != t->data)
152 error("bug: parser_temp_realloc misused");
153 t->data = ckrealloc(t->data, len);
154 INTON;
155 return t->data;
159 static void
160 parser_temp_free_upto(void *ptr)
162 struct parser_temp *t;
163 int done = 0;
165 INTOFF;
166 while (parser_temp != NULL && !done) {
167 t = parser_temp;
168 parser_temp = t->next;
169 done = t->data == ptr;
170 ckfree(t->data);
171 ckfree(t);
173 INTON;
174 if (!done)
175 error("bug: parser_temp_free_upto misused");
179 static void
180 parser_temp_free_all(void)
182 struct parser_temp *t;
184 INTOFF;
185 while (parser_temp != NULL) {
186 t = parser_temp;
187 parser_temp = t->next;
188 ckfree(t->data);
189 ckfree(t);
191 INTON;
196 * Read and parse a command. Returns NEOF on end of file. (NULL is a
197 * valid parse tree indicating a blank line.)
200 union node *
201 parsecmd(int interact)
203 int t;
205 /* This assumes the parser is not re-entered,
206 * which could happen if we add command substitution on PS1/PS2.
208 parser_temp_free_all();
209 heredoclist = NULL;
211 tokpushback = 0;
212 doprompt = interact;
213 if (doprompt)
214 setprompt(1);
215 else
216 setprompt(0);
217 needprompt = 0;
218 t = readtoken();
219 if (t == TEOF)
220 return NEOF;
221 if (t == TNL)
222 return NULL;
223 tokpushback++;
224 return list(1, 1);
228 static union node *
229 list(int nlflag, int erflag)
231 union node *ntop, *n1, *n2, *n3;
232 int tok;
234 checkkwd = CHKNL | CHKKWD | CHKALIAS;
235 if (!nlflag && !erflag && tokendlist[peektoken()])
236 return NULL;
237 ntop = n1 = NULL;
238 for (;;) {
239 n2 = andor();
240 tok = readtoken();
241 if (tok == TBACKGND) {
242 if (n2 != NULL && n2->type == NPIPE) {
243 n2->npipe.backgnd = 1;
244 } else if (n2 != NULL && n2->type == NREDIR) {
245 n2->type = NBACKGND;
246 } else {
247 n3 = (union node *)stalloc(sizeof (struct nredir));
248 n3->type = NBACKGND;
249 n3->nredir.n = n2;
250 n3->nredir.redirect = NULL;
251 n2 = n3;
254 if (ntop == NULL)
255 ntop = n2;
256 else if (n1 == NULL) {
257 n1 = (union node *)stalloc(sizeof (struct nbinary));
258 n1->type = NSEMI;
259 n1->nbinary.ch1 = ntop;
260 n1->nbinary.ch2 = n2;
261 ntop = n1;
263 else {
264 n3 = (union node *)stalloc(sizeof (struct nbinary));
265 n3->type = NSEMI;
266 n3->nbinary.ch1 = n1->nbinary.ch2;
267 n3->nbinary.ch2 = n2;
268 n1->nbinary.ch2 = n3;
269 n1 = n3;
271 switch (tok) {
272 case TBACKGND:
273 case TSEMI:
274 tok = readtoken();
275 /* FALLTHROUGH */
276 case TNL:
277 if (tok == TNL) {
278 parseheredoc();
279 if (nlflag)
280 return ntop;
281 } else if (tok == TEOF && nlflag) {
282 parseheredoc();
283 return ntop;
284 } else {
285 tokpushback++;
287 checkkwd = CHKNL | CHKKWD | CHKALIAS;
288 if (!nlflag && (erflag ? peektoken() == TEOF :
289 tokendlist[peektoken()]))
290 return ntop;
291 break;
292 case TEOF:
293 if (heredoclist)
294 parseheredoc();
295 else
296 pungetc(); /* push back EOF on input */
297 return ntop;
298 default:
299 if (nlflag || erflag)
300 synexpect(-1);
301 tokpushback++;
302 return ntop;
309 static union node *
310 andor(void)
312 union node *n1, *n2, *n3;
313 int t;
315 n1 = pipeline();
316 for (;;) {
317 if ((t = readtoken()) == TAND) {
318 t = NAND;
319 } else if (t == TOR) {
320 t = NOR;
321 } else {
322 tokpushback++;
323 return n1;
325 n2 = pipeline();
326 n3 = (union node *)stalloc(sizeof (struct nbinary));
327 n3->type = t;
328 n3->nbinary.ch1 = n1;
329 n3->nbinary.ch2 = n2;
330 n1 = n3;
336 static union node *
337 pipeline(void)
339 union node *n1, *n2, *pipenode;
340 struct nodelist *lp, *prev;
341 int negate, t;
343 negate = 0;
344 checkkwd = CHKNL | CHKKWD | CHKALIAS;
345 TRACE(("pipeline: entered\n"));
346 while (readtoken() == TNOT)
347 negate = !negate;
348 tokpushback++;
349 n1 = command();
350 if (readtoken() == TPIPE) {
351 pipenode = (union node *)stalloc(sizeof (struct npipe));
352 pipenode->type = NPIPE;
353 pipenode->npipe.backgnd = 0;
354 lp = (struct nodelist *)stalloc(sizeof (struct nodelist));
355 pipenode->npipe.cmdlist = lp;
356 lp->n = n1;
357 do {
358 prev = lp;
359 lp = (struct nodelist *)stalloc(sizeof (struct nodelist));
360 checkkwd = CHKNL | CHKKWD | CHKALIAS;
361 t = readtoken();
362 tokpushback++;
363 if (t == TNOT)
364 lp->n = pipeline();
365 else
366 lp->n = command();
367 prev->next = lp;
368 } while (readtoken() == TPIPE);
369 lp->next = NULL;
370 n1 = pipenode;
372 tokpushback++;
373 if (negate) {
374 n2 = (union node *)stalloc(sizeof (struct nnot));
375 n2->type = NNOT;
376 n2->nnot.com = n1;
377 return n2;
378 } else
379 return n1;
384 static union node *
385 command(void)
387 union node *n1, *n2;
388 union node *ap, **app;
389 union node *cp, **cpp;
390 union node *redir, **rpp;
391 int t;
392 int is_subshell;
394 checkkwd = CHKNL | CHKKWD | CHKALIAS;
395 is_subshell = 0;
396 redir = NULL;
397 n1 = NULL;
398 rpp = &redir;
400 /* Check for redirection which may precede command */
401 while (readtoken() == TREDIR) {
402 *rpp = n2 = redirnode;
403 rpp = &n2->nfile.next;
404 parsefname();
406 tokpushback++;
408 switch (readtoken()) {
409 case TIF:
410 n1 = (union node *)stalloc(sizeof (struct nif));
411 n1->type = NIF;
412 if ((n1->nif.test = list(0, 0)) == NULL)
413 synexpect(-1);
414 if (readtoken() != TTHEN)
415 synexpect(TTHEN);
416 n1->nif.ifpart = list(0, 0);
417 n2 = n1;
418 while (readtoken() == TELIF) {
419 n2->nif.elsepart = (union node *)stalloc(sizeof (struct nif));
420 n2 = n2->nif.elsepart;
421 n2->type = NIF;
422 if ((n2->nif.test = list(0, 0)) == NULL)
423 synexpect(-1);
424 if (readtoken() != TTHEN)
425 synexpect(TTHEN);
426 n2->nif.ifpart = list(0, 0);
428 if (lasttoken == TELSE)
429 n2->nif.elsepart = list(0, 0);
430 else {
431 n2->nif.elsepart = NULL;
432 tokpushback++;
434 if (readtoken() != TFI)
435 synexpect(TFI);
436 checkkwd = CHKKWD | CHKALIAS;
437 break;
438 case TWHILE:
439 case TUNTIL: {
440 int got;
441 n1 = (union node *)stalloc(sizeof (struct nbinary));
442 n1->type = (lasttoken == TWHILE)? NWHILE : NUNTIL;
443 if ((n1->nbinary.ch1 = list(0, 0)) == NULL)
444 synexpect(-1);
445 if ((got=readtoken()) != TDO) {
446 TRACE(("expecting DO got %s %s\n", tokname[got], got == TWORD ? wordtext : ""));
447 synexpect(TDO);
449 n1->nbinary.ch2 = list(0, 0);
450 if (readtoken() != TDONE)
451 synexpect(TDONE);
452 checkkwd = CHKKWD | CHKALIAS;
453 break;
455 case TFOR:
456 if (readtoken() != TWORD || quoteflag || ! goodname(wordtext))
457 synerror("Bad for loop variable");
458 n1 = (union node *)stalloc(sizeof (struct nfor));
459 n1->type = NFOR;
460 n1->nfor.var = wordtext;
461 while (readtoken() == TNL)
463 if (lasttoken == TWORD && ! quoteflag && equal(wordtext, "in")) {
464 app = &ap;
465 while (readtoken() == TWORD) {
466 n2 = (union node *)stalloc(sizeof (struct narg));
467 n2->type = NARG;
468 n2->narg.text = wordtext;
469 n2->narg.backquote = backquotelist;
470 *app = n2;
471 app = &n2->narg.next;
473 *app = NULL;
474 n1->nfor.args = ap;
475 if (lasttoken != TNL && lasttoken != TSEMI)
476 synexpect(-1);
477 } else {
478 static char argvars[5] = {
479 CTLVAR, VSNORMAL|VSQUOTE, '@', '=', '\0'
481 n2 = (union node *)stalloc(sizeof (struct narg));
482 n2->type = NARG;
483 n2->narg.text = argvars;
484 n2->narg.backquote = NULL;
485 n2->narg.next = NULL;
486 n1->nfor.args = n2;
488 * Newline or semicolon here is optional (but note
489 * that the original Bourne shell only allowed NL).
491 if (lasttoken != TNL && lasttoken != TSEMI)
492 tokpushback++;
494 checkkwd = CHKNL | CHKKWD | CHKALIAS;
495 if ((t = readtoken()) == TDO)
496 t = TDONE;
497 else if (t == TBEGIN)
498 t = TEND;
499 else
500 synexpect(-1);
501 n1->nfor.body = list(0, 0);
502 if (readtoken() != t)
503 synexpect(t);
504 checkkwd = CHKKWD | CHKALIAS;
505 break;
506 case TCASE:
507 n1 = (union node *)stalloc(sizeof (struct ncase));
508 n1->type = NCASE;
509 if (readtoken() != TWORD)
510 synexpect(TWORD);
511 n1->ncase.expr = n2 = (union node *)stalloc(sizeof (struct narg));
512 n2->type = NARG;
513 n2->narg.text = wordtext;
514 n2->narg.backquote = backquotelist;
515 n2->narg.next = NULL;
516 while (readtoken() == TNL);
517 if (lasttoken != TWORD || ! equal(wordtext, "in"))
518 synerror("expecting \"in\"");
519 cpp = &n1->ncase.cases;
520 checkkwd = CHKNL | CHKKWD, readtoken();
521 while (lasttoken != TESAC) {
522 *cpp = cp = (union node *)stalloc(sizeof (struct nclist));
523 cp->type = NCLIST;
524 app = &cp->nclist.pattern;
525 if (lasttoken == TLP)
526 readtoken();
527 for (;;) {
528 *app = ap = (union node *)stalloc(sizeof (struct narg));
529 ap->type = NARG;
530 ap->narg.text = wordtext;
531 ap->narg.backquote = backquotelist;
532 checkkwd = CHKNL | CHKKWD;
533 if (readtoken() != TPIPE)
534 break;
535 app = &ap->narg.next;
536 readtoken();
538 ap->narg.next = NULL;
539 if (lasttoken != TRP)
540 synexpect(TRP);
541 cp->nclist.body = list(0, 0);
543 checkkwd = CHKNL | CHKKWD | CHKALIAS;
544 if ((t = readtoken()) != TESAC) {
545 if (t == TENDCASE)
547 else if (t == TFALLTHRU)
548 cp->type = NCLISTFALLTHRU;
549 else
550 synexpect(TENDCASE);
551 checkkwd = CHKNL | CHKKWD, readtoken();
553 cpp = &cp->nclist.next;
555 *cpp = NULL;
556 checkkwd = CHKKWD | CHKALIAS;
557 break;
558 case TLP:
559 n1 = (union node *)stalloc(sizeof (struct nredir));
560 n1->type = NSUBSHELL;
561 n1->nredir.n = list(0, 0);
562 n1->nredir.redirect = NULL;
563 if (readtoken() != TRP)
564 synexpect(TRP);
565 checkkwd = CHKKWD | CHKALIAS;
566 is_subshell = 1;
567 break;
568 case TBEGIN:
569 n1 = list(0, 0);
570 if (readtoken() != TEND)
571 synexpect(TEND);
572 checkkwd = CHKKWD | CHKALIAS;
573 break;
574 /* Handle an empty command like other simple commands. */
575 case TBACKGND:
576 case TSEMI:
577 case TAND:
578 case TOR:
580 * An empty command before a ; doesn't make much sense, and
581 * should certainly be disallowed in the case of `if ;'.
583 if (!redir)
584 synexpect(-1);
585 case TNL:
586 case TEOF:
587 case TWORD:
588 case TRP:
589 tokpushback++;
590 n1 = simplecmd(rpp, redir);
591 return n1;
592 default:
593 synexpect(-1);
596 /* Now check for redirection which may follow command */
597 while (readtoken() == TREDIR) {
598 *rpp = n2 = redirnode;
599 rpp = &n2->nfile.next;
600 parsefname();
602 tokpushback++;
603 *rpp = NULL;
604 if (redir) {
605 if (!is_subshell) {
606 n2 = (union node *)stalloc(sizeof (struct nredir));
607 n2->type = NREDIR;
608 n2->nredir.n = n1;
609 n1 = n2;
611 n1->nredir.redirect = redir;
614 return n1;
618 static union node *
619 simplecmd(union node **rpp, union node *redir)
621 union node *args, **app;
622 union node **orig_rpp = rpp;
623 union node *n = NULL;
624 int special;
625 int savecheckkwd;
627 /* If we don't have any redirections already, then we must reset */
628 /* rpp to be the address of the local redir variable. */
629 if (redir == NULL)
630 rpp = &redir;
632 args = NULL;
633 app = &args;
635 * We save the incoming value, because we need this for shell
636 * functions. There can not be a redirect or an argument between
637 * the function name and the open parenthesis.
639 orig_rpp = rpp;
641 savecheckkwd = CHKALIAS;
643 for (;;) {
644 checkkwd = savecheckkwd;
645 if (readtoken() == TWORD) {
646 n = (union node *)stalloc(sizeof (struct narg));
647 n->type = NARG;
648 n->narg.text = wordtext;
649 n->narg.backquote = backquotelist;
650 *app = n;
651 app = &n->narg.next;
652 if (savecheckkwd != 0 && !isassignment(wordtext))
653 savecheckkwd = 0;
654 } else if (lasttoken == TREDIR) {
655 *rpp = n = redirnode;
656 rpp = &n->nfile.next;
657 parsefname(); /* read name of redirection file */
658 } else if (lasttoken == TLP && app == &args->narg.next
659 && rpp == orig_rpp) {
660 /* We have a function */
661 if (readtoken() != TRP)
662 synexpect(TRP);
663 funclinno = plinno;
665 * - Require plain text.
666 * - Functions with '/' cannot be called.
667 * - Reject name=().
668 * - Reject ksh extended glob patterns.
670 if (!noexpand(n->narg.text) || quoteflag ||
671 strchr(n->narg.text, '/') ||
672 strchr("!%*+-=?@}~",
673 n->narg.text[strlen(n->narg.text) - 1]))
674 synerror("Bad function name");
675 rmescapes(n->narg.text);
676 if (find_builtin(n->narg.text, &special) >= 0 &&
677 special)
678 synerror("Cannot override a special builtin with a function");
679 n->type = NDEFUN;
680 n->narg.next = command();
681 funclinno = 0;
682 return n;
683 } else {
684 tokpushback++;
685 break;
688 *app = NULL;
689 *rpp = NULL;
690 n = (union node *)stalloc(sizeof (struct ncmd));
691 n->type = NCMD;
692 n->ncmd.args = args;
693 n->ncmd.redirect = redir;
694 return n;
697 static union node *
698 makename(void)
700 union node *n;
702 n = (union node *)stalloc(sizeof (struct narg));
703 n->type = NARG;
704 n->narg.next = NULL;
705 n->narg.text = wordtext;
706 n->narg.backquote = backquotelist;
707 return n;
710 void
711 fixredir(union node *n, const char *text, int err)
713 TRACE(("Fix redir %s %d\n", text, err));
714 if (!err)
715 n->ndup.vname = NULL;
717 if (is_digit(text[0]) && text[1] == '\0')
718 n->ndup.dupfd = digit_val(text[0]);
719 else if (text[0] == '-' && text[1] == '\0')
720 n->ndup.dupfd = -1;
721 else {
723 if (err)
724 synerror("Bad fd number");
725 else
726 n->ndup.vname = makename();
731 static void
732 parsefname(void)
734 union node *n = redirnode;
736 if (readtoken() != TWORD)
737 synexpect(-1);
738 if (n->type == NHERE) {
739 struct heredoc *here = heredoc;
740 struct heredoc *p;
741 int i;
743 if (quoteflag == 0)
744 n->type = NXHERE;
745 TRACE(("Here document %d\n", n->type));
746 if (here->striptabs) {
747 while (*wordtext == '\t')
748 wordtext++;
750 if (! noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)
751 synerror("Illegal eof marker for << redirection");
752 rmescapes(wordtext);
753 here->eofmark = wordtext;
754 here->next = NULL;
755 if (heredoclist == NULL)
756 heredoclist = here;
757 else {
758 for (p = heredoclist ; p->next ; p = p->next);
759 p->next = here;
761 } else if (n->type == NTOFD || n->type == NFROMFD) {
762 fixredir(n, wordtext, 0);
763 } else {
764 n->nfile.fname = makename();
770 * Input any here documents.
773 static void
774 parseheredoc(void)
776 struct heredoc *here;
777 union node *n;
779 while (heredoclist) {
780 here = heredoclist;
781 heredoclist = here->next;
782 if (needprompt) {
783 setprompt(2);
784 needprompt = 0;
786 readtoken1(pgetc(), here->here->type == NHERE? SQSYNTAX : DQSYNTAX,
787 here->eofmark, here->striptabs);
788 n = (union node *)stalloc(sizeof (struct narg));
789 n->narg.type = NARG;
790 n->narg.next = NULL;
791 n->narg.text = wordtext;
792 n->narg.backquote = backquotelist;
793 here->here->nhere.doc = n;
797 static int
798 peektoken(void)
800 int t;
802 t = readtoken();
803 tokpushback++;
804 return (t);
807 static int
808 readtoken(void)
810 int t;
811 struct alias *ap;
812 #ifdef DEBUG
813 int alreadyseen = tokpushback;
814 #endif
816 top:
817 t = xxreadtoken();
820 * eat newlines
822 if (checkkwd & CHKNL) {
823 while (t == TNL) {
824 parseheredoc();
825 t = xxreadtoken();
830 * check for keywords and aliases
832 if (t == TWORD && !quoteflag)
834 const char * const *pp;
836 if (checkkwd & CHKKWD)
837 for (pp = parsekwd; *pp; pp++) {
838 if (**pp == *wordtext && equal(*pp, wordtext))
840 lasttoken = t = pp - parsekwd + KWDOFFSET;
841 TRACE(("keyword %s recognized\n", tokname[t]));
842 goto out;
845 if (checkkwd & CHKALIAS &&
846 (ap = lookupalias(wordtext, 1)) != NULL) {
847 pushstring(ap->val, strlen(ap->val), ap);
848 goto top;
851 out:
852 if (t != TNOT)
853 checkkwd = 0;
855 #ifdef DEBUG
856 if (!alreadyseen)
857 TRACE(("token %s %s\n", tokname[t], t == TWORD ? wordtext : ""));
858 else
859 TRACE(("reread token %s %s\n", tokname[t], t == TWORD ? wordtext : ""));
860 #endif
861 return (t);
866 * Read the next input token.
867 * If the token is a word, we set backquotelist to the list of cmds in
868 * backquotes. We set quoteflag to true if any part of the word was
869 * quoted.
870 * If the token is TREDIR, then we set redirnode to a structure containing
871 * the redirection.
872 * In all cases, the variable startlinno is set to the number of the line
873 * on which the token starts.
875 * [Change comment: here documents and internal procedures]
876 * [Readtoken shouldn't have any arguments. Perhaps we should make the
877 * word parsing code into a separate routine. In this case, readtoken
878 * doesn't need to have any internal procedures, but parseword does.
879 * We could also make parseoperator in essence the main routine, and
880 * have parseword (readtoken1?) handle both words and redirection.]
883 #define RETURN(token) return lasttoken = token
885 static int
886 xxreadtoken(void)
888 int c;
890 if (tokpushback) {
891 tokpushback = 0;
892 return lasttoken;
894 if (needprompt) {
895 setprompt(2);
896 needprompt = 0;
898 startlinno = plinno;
899 for (;;) { /* until token or start of word found */
900 c = pgetc_macro();
901 switch (c) {
902 case ' ': case '\t':
903 continue;
904 case '#':
905 while ((c = pgetc()) != '\n' && c != PEOF);
906 pungetc();
907 continue;
908 case '\\':
909 if (pgetc() == '\n') {
910 startlinno = ++plinno;
911 if (doprompt)
912 setprompt(2);
913 else
914 setprompt(0);
915 continue;
917 pungetc();
918 goto breakloop;
919 case '\n':
920 plinno++;
921 needprompt = doprompt;
922 RETURN(TNL);
923 case PEOF:
924 RETURN(TEOF);
925 case '&':
926 if (pgetc() == '&')
927 RETURN(TAND);
928 pungetc();
929 RETURN(TBACKGND);
930 case '|':
931 if (pgetc() == '|')
932 RETURN(TOR);
933 pungetc();
934 RETURN(TPIPE);
935 case ';':
936 c = pgetc();
937 if (c == ';')
938 RETURN(TENDCASE);
939 else if (c == '&')
940 RETURN(TFALLTHRU);
941 pungetc();
942 RETURN(TSEMI);
943 case '(':
944 RETURN(TLP);
945 case ')':
946 RETURN(TRP);
947 default:
948 goto breakloop;
951 breakloop:
952 return readtoken1(c, BASESYNTAX, NULL, 0);
953 #undef RETURN
957 #define MAXNEST_STATIC 8
958 struct tokenstate
960 const char *syntax; /* *SYNTAX */
961 int parenlevel; /* levels of parentheses in arithmetic */
962 enum tokenstate_category
964 TSTATE_TOP,
965 TSTATE_VAR_OLD, /* ${var+-=?}, inherits dquotes */
966 TSTATE_VAR_NEW, /* other ${var...}, own dquote state */
967 TSTATE_ARITH
968 } category;
973 * Called to parse command substitutions.
976 static char *
977 parsebackq(char *out, struct nodelist **pbqlist,
978 int oldstyle, int dblquote, int quoted)
980 struct nodelist **nlpp;
981 union node *n;
982 char *volatile str;
983 struct jmploc jmploc;
984 struct jmploc *const savehandler = handler;
985 int savelen;
986 int saveprompt;
987 const int bq_startlinno = plinno;
988 char *volatile ostr = NULL;
989 struct parsefile *const savetopfile = getcurrentfile();
990 struct heredoc *const saveheredoclist = heredoclist;
991 struct heredoc *here;
993 str = NULL;
994 if (setjmp(jmploc.loc)) {
995 popfilesupto(savetopfile);
996 if (str)
997 ckfree(str);
998 if (ostr)
999 ckfree(ostr);
1000 heredoclist = saveheredoclist;
1001 handler = savehandler;
1002 if (exception == EXERROR) {
1003 startlinno = bq_startlinno;
1004 synerror("Error in command substitution");
1006 longjmp(handler->loc, 1);
1008 INTOFF;
1009 savelen = out - stackblock();
1010 if (savelen > 0) {
1011 str = ckmalloc(savelen);
1012 memcpy(str, stackblock(), savelen);
1014 handler = &jmploc;
1015 heredoclist = NULL;
1016 INTON;
1017 if (oldstyle) {
1019 * We must read until the closing backquote, giving special
1020 * treatment to some slashes, and then push the string and
1021 * reread it as input, interpreting it normally.
1023 char *oout;
1024 int c, olen;
1026 STARTSTACKSTR(oout);
1027 for (;;) {
1028 if (needprompt) {
1029 setprompt(2);
1030 needprompt = 0;
1032 CHECKSTRSPACE(2, oout);
1033 switch (c = pgetc()) {
1034 case '`':
1035 goto done;
1037 case '\\':
1038 if ((c = pgetc()) == '\n') {
1039 plinno++;
1040 if (doprompt)
1041 setprompt(2);
1042 else
1043 setprompt(0);
1045 * If eating a newline, avoid putting
1046 * the newline into the new character
1047 * stream (via the USTPUTC after the
1048 * switch).
1050 continue;
1052 if (c != '\\' && c != '`' && c != '$'
1053 && (!dblquote || c != '"'))
1054 USTPUTC('\\', oout);
1055 break;
1057 case '\n':
1058 plinno++;
1059 needprompt = doprompt;
1060 break;
1062 case PEOF:
1063 startlinno = plinno;
1064 synerror("EOF in backquote substitution");
1065 break;
1067 default:
1068 break;
1070 USTPUTC(c, oout);
1072 done:
1073 USTPUTC('\0', oout);
1074 olen = oout - stackblock();
1075 INTOFF;
1076 ostr = ckmalloc(olen);
1077 memcpy(ostr, stackblock(), olen);
1078 setinputstring(ostr, 1);
1079 INTON;
1081 nlpp = pbqlist;
1082 while (*nlpp)
1083 nlpp = &(*nlpp)->next;
1084 *nlpp = (struct nodelist *)stalloc(sizeof (struct nodelist));
1085 (*nlpp)->next = NULL;
1087 if (oldstyle) {
1088 saveprompt = doprompt;
1089 doprompt = 0;
1092 n = list(0, oldstyle);
1094 if (oldstyle)
1095 doprompt = saveprompt;
1096 else {
1097 if (readtoken() != TRP)
1098 synexpect(TRP);
1101 (*nlpp)->n = n;
1102 if (oldstyle) {
1104 * Start reading from old file again, ignoring any pushed back
1105 * tokens left from the backquote parsing
1107 popfile();
1108 tokpushback = 0;
1110 STARTSTACKSTR(out);
1111 CHECKSTRSPACE(savelen + 1, out);
1112 INTOFF;
1113 if (str) {
1114 memcpy(out, str, savelen);
1115 STADJUST(savelen, out);
1116 ckfree(str);
1117 str = NULL;
1119 if (ostr) {
1120 ckfree(ostr);
1121 ostr = NULL;
1123 here = saveheredoclist;
1124 if (here != NULL) {
1125 while (here->next != NULL)
1126 here = here->next;
1127 here->next = heredoclist;
1128 heredoclist = saveheredoclist;
1130 handler = savehandler;
1131 INTON;
1132 if (quoted)
1133 USTPUTC(CTLBACKQ | CTLQUOTE, out);
1134 else
1135 USTPUTC(CTLBACKQ, out);
1136 return out;
1141 * Called to parse a backslash escape sequence inside $'...'.
1142 * The backslash has already been read.
1144 static char *
1145 readcstyleesc(char *out)
1147 int c, v, i, n;
1149 c = pgetc();
1150 switch (c) {
1151 case '\0':
1152 synerror("Unterminated quoted string");
1153 case '\n':
1154 plinno++;
1155 if (doprompt)
1156 setprompt(2);
1157 else
1158 setprompt(0);
1159 return out;
1160 case '\\':
1161 case '\'':
1162 case '"':
1163 v = c;
1164 break;
1165 case 'a': v = '\a'; break;
1166 case 'b': v = '\b'; break;
1167 case 'e': v = '\033'; break;
1168 case 'f': v = '\f'; break;
1169 case 'n': v = '\n'; break;
1170 case 'r': v = '\r'; break;
1171 case 't': v = '\t'; break;
1172 case 'v': v = '\v'; break;
1173 case 'x':
1174 v = 0;
1175 for (;;) {
1176 c = pgetc();
1177 if (c >= '0' && c <= '9')
1178 v = (v << 4) + c - '0';
1179 else if (c >= 'A' && c <= 'F')
1180 v = (v << 4) + c - 'A' + 10;
1181 else if (c >= 'a' && c <= 'f')
1182 v = (v << 4) + c - 'a' + 10;
1183 else
1184 break;
1186 pungetc();
1187 break;
1188 case '0': case '1': case '2': case '3':
1189 case '4': case '5': case '6': case '7':
1190 v = c - '0';
1191 c = pgetc();
1192 if (c >= '0' && c <= '7') {
1193 v <<= 3;
1194 v += c - '0';
1195 c = pgetc();
1196 if (c >= '0' && c <= '7') {
1197 v <<= 3;
1198 v += c - '0';
1199 } else
1200 pungetc();
1201 } else
1202 pungetc();
1203 break;
1204 case 'c':
1205 c = pgetc();
1206 if (c < 0x3f || c > 0x7a || c == 0x60)
1207 synerror("Bad escape sequence");
1208 if (c == '\\' && pgetc() != '\\')
1209 synerror("Bad escape sequence");
1210 if (c == '?')
1211 v = 127;
1212 else
1213 v = c & 0x1f;
1214 break;
1215 case 'u':
1216 case 'U':
1217 n = c == 'U' ? 8 : 4;
1218 v = 0;
1219 for (i = 0; i < n; i++) {
1220 c = pgetc();
1221 if (c >= '0' && c <= '9')
1222 v = (v << 4) + c - '0';
1223 else if (c >= 'A' && c <= 'F')
1224 v = (v << 4) + c - 'A' + 10;
1225 else if (c >= 'a' && c <= 'f')
1226 v = (v << 4) + c - 'a' + 10;
1227 else
1228 synerror("Bad escape sequence");
1230 if (v == 0 || (v >= 0xd800 && v <= 0xdfff))
1231 synerror("Bad escape sequence");
1232 /* We really need iconv here. */
1233 if (initial_localeisutf8 && v > 127) {
1234 CHECKSTRSPACE(4, out);
1236 * We cannot use wctomb() as the locale may have
1237 * changed.
1239 if (v <= 0x7ff) {
1240 USTPUTC(0xc0 | v >> 6, out);
1241 USTPUTC(0x80 | (v & 0x3f), out);
1242 return out;
1243 } else if (v <= 0xffff) {
1244 USTPUTC(0xe0 | v >> 12, out);
1245 USTPUTC(0x80 | ((v >> 6) & 0x3f), out);
1246 USTPUTC(0x80 | (v & 0x3f), out);
1247 return out;
1248 } else if (v <= 0x10ffff) {
1249 USTPUTC(0xf0 | v >> 18, out);
1250 USTPUTC(0x80 | ((v >> 12) & 0x3f), out);
1251 USTPUTC(0x80 | ((v >> 6) & 0x3f), out);
1252 USTPUTC(0x80 | (v & 0x3f), out);
1253 return out;
1256 if (v > 127)
1257 v = '?';
1258 break;
1259 default:
1260 synerror("Bad escape sequence");
1262 v = (char)v;
1264 * We can't handle NUL bytes.
1265 * POSIX says we should skip till the closing quote.
1267 if (v == '\0') {
1268 while ((c = pgetc()) != '\'') {
1269 if (c == '\\')
1270 c = pgetc();
1271 if (c == PEOF)
1272 synerror("Unterminated quoted string");
1274 pungetc();
1275 return out;
1277 if (SQSYNTAX[v] == CCTL)
1278 USTPUTC(CTLESC, out);
1279 USTPUTC(v, out);
1280 return out;
1285 * If eofmark is NULL, read a word or a redirection symbol. If eofmark
1286 * is not NULL, read a here document. In the latter case, eofmark is the
1287 * word which marks the end of the document and striptabs is true if
1288 * leading tabs should be stripped from the document. The argument firstc
1289 * is the first character of the input token or document.
1291 * Because C does not have internal subroutines, I have simulated them
1292 * using goto's to implement the subroutine linkage. The following macros
1293 * will run code that appears at the end of readtoken1.
1296 #define CHECKEND() {goto checkend; checkend_return:;}
1297 #define PARSEREDIR() {goto parseredir; parseredir_return:;}
1298 #define PARSESUB() {goto parsesub; parsesub_return:;}
1299 #define PARSEARITH() {goto parsearith; parsearith_return:;}
1301 static int
1302 readtoken1(int firstc, char const *initialsyntax, char *eofmark, int striptabs)
1304 int c = firstc;
1305 char * volatile out;
1306 int len;
1307 char line[EOFMARKLEN + 1];
1308 struct nodelist *bqlist;
1309 volatile int quotef;
1310 int newvarnest;
1311 int level;
1312 int synentry;
1313 struct tokenstate state_static[MAXNEST_STATIC];
1314 int maxnest = MAXNEST_STATIC;
1315 struct tokenstate *state = state_static;
1316 int sqiscstyle = 0;
1318 startlinno = plinno;
1319 quotef = 0;
1320 bqlist = NULL;
1321 newvarnest = 0;
1322 level = 0;
1323 state[level].syntax = initialsyntax;
1324 state[level].parenlevel = 0;
1325 state[level].category = TSTATE_TOP;
1327 STARTSTACKSTR(out);
1328 loop: { /* for each line, until end of word */
1329 CHECKEND(); /* set c to PEOF if at end of here document */
1330 for (;;) { /* until end of line or end of word */
1331 CHECKSTRSPACE(4, out); /* permit 4 calls to USTPUTC */
1333 synentry = state[level].syntax[c];
1335 switch(synentry) {
1336 case CNL: /* '\n' */
1337 if (state[level].syntax == BASESYNTAX)
1338 goto endword; /* exit outer loop */
1339 USTPUTC(c, out);
1340 plinno++;
1341 if (doprompt)
1342 setprompt(2);
1343 else
1344 setprompt(0);
1345 c = pgetc();
1346 goto loop; /* continue outer loop */
1347 case CSBACK:
1348 if (sqiscstyle) {
1349 out = readcstyleesc(out);
1350 break;
1352 /* FALLTHROUGH */
1353 case CWORD:
1354 USTPUTC(c, out);
1355 break;
1356 case CCTL:
1357 if (eofmark == NULL || initialsyntax != SQSYNTAX)
1358 USTPUTC(CTLESC, out);
1359 USTPUTC(c, out);
1360 break;
1361 case CBACK: /* backslash */
1362 c = pgetc();
1363 if (c == PEOF) {
1364 USTPUTC('\\', out);
1365 pungetc();
1366 } else if (c == '\n') {
1367 plinno++;
1368 if (doprompt)
1369 setprompt(2);
1370 else
1371 setprompt(0);
1372 } else {
1373 if (state[level].syntax == DQSYNTAX &&
1374 c != '\\' && c != '`' && c != '$' &&
1375 (c != '"' || (eofmark != NULL &&
1376 newvarnest == 0)) &&
1377 (c != '}' || state[level].category != TSTATE_VAR_OLD))
1378 USTPUTC('\\', out);
1379 if ((eofmark == NULL ||
1380 newvarnest > 0) &&
1381 state[level].syntax == BASESYNTAX)
1382 USTPUTC(CTLQUOTEMARK, out);
1383 if (SQSYNTAX[c] == CCTL)
1384 USTPUTC(CTLESC, out);
1385 USTPUTC(c, out);
1386 if ((eofmark == NULL ||
1387 newvarnest > 0) &&
1388 state[level].syntax == BASESYNTAX &&
1389 state[level].category == TSTATE_VAR_OLD)
1390 USTPUTC(CTLQUOTEEND, out);
1391 quotef++;
1393 break;
1394 case CSQUOTE:
1395 USTPUTC(CTLQUOTEMARK, out);
1396 state[level].syntax = SQSYNTAX;
1397 sqiscstyle = 0;
1398 break;
1399 case CDQUOTE:
1400 USTPUTC(CTLQUOTEMARK, out);
1401 state[level].syntax = DQSYNTAX;
1402 break;
1403 case CENDQUOTE:
1404 if (eofmark != NULL && newvarnest == 0)
1405 USTPUTC(c, out);
1406 else {
1407 if (state[level].category == TSTATE_VAR_OLD)
1408 USTPUTC(CTLQUOTEEND, out);
1409 state[level].syntax = BASESYNTAX;
1410 quotef++;
1412 break;
1413 case CVAR: /* '$' */
1414 PARSESUB(); /* parse substitution */
1415 break;
1416 case CENDVAR: /* '}' */
1417 if (level > 0 &&
1418 ((state[level].category == TSTATE_VAR_OLD &&
1419 state[level].syntax ==
1420 state[level - 1].syntax) ||
1421 (state[level].category == TSTATE_VAR_NEW &&
1422 state[level].syntax == BASESYNTAX))) {
1423 if (state[level].category == TSTATE_VAR_NEW)
1424 newvarnest--;
1425 level--;
1426 USTPUTC(CTLENDVAR, out);
1427 } else {
1428 USTPUTC(c, out);
1430 break;
1431 case CLP: /* '(' in arithmetic */
1432 state[level].parenlevel++;
1433 USTPUTC(c, out);
1434 break;
1435 case CRP: /* ')' in arithmetic */
1436 if (state[level].parenlevel > 0) {
1437 USTPUTC(c, out);
1438 --state[level].parenlevel;
1439 } else {
1440 if (pgetc() == ')') {
1441 if (level > 0 &&
1442 state[level].category == TSTATE_ARITH) {
1443 level--;
1444 USTPUTC(CTLENDARI, out);
1445 } else
1446 USTPUTC(')', out);
1447 } else {
1449 * unbalanced parens
1450 * (don't 2nd guess - no error)
1452 pungetc();
1453 USTPUTC(')', out);
1456 break;
1457 case CBQUOTE: /* '`' */
1458 out = parsebackq(out, &bqlist, 1,
1459 state[level].syntax == DQSYNTAX &&
1460 (eofmark == NULL || newvarnest > 0),
1461 state[level].syntax == DQSYNTAX || state[level].syntax == ARISYNTAX);
1462 break;
1463 case CEOF:
1464 goto endword; /* exit outer loop */
1465 case CIGN:
1466 break;
1467 default:
1468 if (level == 0)
1469 goto endword; /* exit outer loop */
1470 USTPUTC(c, out);
1472 c = pgetc_macro();
1475 endword:
1476 if (state[level].syntax == ARISYNTAX)
1477 synerror("Missing '))'");
1478 if (state[level].syntax != BASESYNTAX && eofmark == NULL)
1479 synerror("Unterminated quoted string");
1480 if (state[level].category == TSTATE_VAR_OLD ||
1481 state[level].category == TSTATE_VAR_NEW) {
1482 startlinno = plinno;
1483 synerror("Missing '}'");
1485 if (state != state_static)
1486 parser_temp_free_upto(state);
1487 USTPUTC('\0', out);
1488 len = out - stackblock();
1489 out = stackblock();
1490 if (eofmark == NULL) {
1491 if ((c == '>' || c == '<')
1492 && quotef == 0
1493 && len <= 2
1494 && (*out == '\0' || is_digit(*out))) {
1495 PARSEREDIR();
1496 return lasttoken = TREDIR;
1497 } else {
1498 pungetc();
1501 quoteflag = quotef;
1502 backquotelist = bqlist;
1503 grabstackblock(len);
1504 wordtext = out;
1505 return lasttoken = TWORD;
1506 /* end of readtoken routine */
1510 * Check to see whether we are at the end of the here document. When this
1511 * is called, c is set to the first character of the next input line. If
1512 * we are at the end of the here document, this routine sets the c to PEOF.
1515 checkend: {
1516 if (eofmark) {
1517 if (striptabs) {
1518 while (c == '\t')
1519 c = pgetc();
1521 if (c == *eofmark) {
1522 if (pfgets(line, sizeof line) != NULL) {
1523 char *p, *q;
1525 p = line;
1526 for (q = eofmark + 1 ; *q && *p == *q ; p++, q++);
1527 if ((*p == '\0' || *p == '\n') && *q == '\0') {
1528 c = PEOF;
1529 if (*p == '\n') {
1530 plinno++;
1531 needprompt = doprompt;
1533 } else {
1534 pushstring(line, strlen(line), NULL);
1539 goto checkend_return;
1544 * Parse a redirection operator. The variable "out" points to a string
1545 * specifying the fd to be redirected. The variable "c" contains the
1546 * first character of the redirection operator.
1549 parseredir: {
1550 char fd = *out;
1551 union node *np;
1553 np = (union node *)stalloc(sizeof (struct nfile));
1554 if (c == '>') {
1555 np->nfile.fd = 1;
1556 c = pgetc();
1557 if (c == '>')
1558 np->type = NAPPEND;
1559 else if (c == '&')
1560 np->type = NTOFD;
1561 else if (c == '|')
1562 np->type = NCLOBBER;
1563 else {
1564 np->type = NTO;
1565 pungetc();
1567 } else { /* c == '<' */
1568 np->nfile.fd = 0;
1569 c = pgetc();
1570 if (c == '<') {
1571 if (sizeof (struct nfile) != sizeof (struct nhere)) {
1572 np = (union node *)stalloc(sizeof (struct nhere));
1573 np->nfile.fd = 0;
1575 np->type = NHERE;
1576 heredoc = (struct heredoc *)stalloc(sizeof (struct heredoc));
1577 heredoc->here = np;
1578 if ((c = pgetc()) == '-') {
1579 heredoc->striptabs = 1;
1580 } else {
1581 heredoc->striptabs = 0;
1582 pungetc();
1584 } else if (c == '&')
1585 np->type = NFROMFD;
1586 else if (c == '>')
1587 np->type = NFROMTO;
1588 else {
1589 np->type = NFROM;
1590 pungetc();
1593 if (fd != '\0')
1594 np->nfile.fd = digit_val(fd);
1595 redirnode = np;
1596 goto parseredir_return;
1601 * Parse a substitution. At this point, we have read the dollar sign
1602 * and nothing else.
1605 parsesub: {
1606 char buf[10];
1607 int subtype;
1608 int typeloc;
1609 int flags;
1610 char *p;
1611 static const char types[] = "}-+?=";
1612 int bracketed_name = 0; /* used to handle ${[0-9]*} variables */
1613 int linno;
1614 int length;
1615 int c1;
1617 c = pgetc();
1618 if (c == '(') { /* $(command) or $((arith)) */
1619 if (pgetc() == '(') {
1620 PARSEARITH();
1621 } else {
1622 pungetc();
1623 out = parsebackq(out, &bqlist, 0,
1624 state[level].syntax == DQSYNTAX &&
1625 (eofmark == NULL || newvarnest > 0),
1626 state[level].syntax == DQSYNTAX ||
1627 state[level].syntax == ARISYNTAX);
1629 } else if (c == '{' || is_name(c) || is_special(c)) {
1630 USTPUTC(CTLVAR, out);
1631 typeloc = out - stackblock();
1632 USTPUTC(VSNORMAL, out);
1633 subtype = VSNORMAL;
1634 flags = 0;
1635 if (c == '{') {
1636 bracketed_name = 1;
1637 c = pgetc();
1638 subtype = 0;
1640 varname:
1641 if (!is_eof(c) && is_name(c)) {
1642 length = 0;
1643 do {
1644 STPUTC(c, out);
1645 c = pgetc();
1646 length++;
1647 } while (!is_eof(c) && is_in_name(c));
1648 if (length == 6 &&
1649 strncmp(out - length, "LINENO", length) == 0) {
1650 /* Replace the variable name with the
1651 * current line number. */
1652 linno = plinno;
1653 if (funclinno != 0)
1654 linno -= funclinno - 1;
1655 snprintf(buf, sizeof(buf), "%d", linno);
1656 STADJUST(-6, out);
1657 STPUTS(buf, out);
1658 flags |= VSLINENO;
1660 } else if (is_digit(c)) {
1661 if (bracketed_name) {
1662 do {
1663 STPUTC(c, out);
1664 c = pgetc();
1665 } while (is_digit(c));
1666 } else {
1667 STPUTC(c, out);
1668 c = pgetc();
1670 } else if (is_special(c)) {
1671 c1 = c;
1672 c = pgetc();
1673 if (subtype == 0 && c1 == '#') {
1674 subtype = VSLENGTH;
1675 if (strchr(types, c) == NULL && c != ':' &&
1676 c != '#' && c != '%')
1677 goto varname;
1678 c1 = c;
1679 c = pgetc();
1680 if (c1 != '}' && c == '}') {
1681 pungetc();
1682 c = c1;
1683 goto varname;
1685 pungetc();
1686 c = c1;
1687 c1 = '#';
1688 subtype = 0;
1690 USTPUTC(c1, out);
1691 } else {
1692 subtype = VSERROR;
1693 if (c == '}')
1694 pungetc();
1695 else if (c == '\n' || c == PEOF)
1696 synerror("Unexpected end of line in substitution");
1697 else
1698 USTPUTC(c, out);
1700 if (subtype == 0) {
1701 switch (c) {
1702 case ':':
1703 flags |= VSNUL;
1704 c = pgetc();
1705 /*FALLTHROUGH*/
1706 default:
1707 p = strchr(types, c);
1708 if (p == NULL) {
1709 if (c == '\n' || c == PEOF)
1710 synerror("Unexpected end of line in substitution");
1711 if (flags == VSNUL)
1712 STPUTC(':', out);
1713 STPUTC(c, out);
1714 subtype = VSERROR;
1715 } else
1716 subtype = p - types + VSNORMAL;
1717 break;
1718 case '%':
1719 case '#':
1721 int cc = c;
1722 subtype = c == '#' ? VSTRIMLEFT :
1723 VSTRIMRIGHT;
1724 c = pgetc();
1725 if (c == cc)
1726 subtype++;
1727 else
1728 pungetc();
1729 break;
1732 } else if (subtype != VSERROR) {
1733 if (subtype == VSLENGTH && c != '}')
1734 subtype = VSERROR;
1735 pungetc();
1737 STPUTC('=', out);
1738 if (state[level].syntax == DQSYNTAX ||
1739 state[level].syntax == ARISYNTAX)
1740 flags |= VSQUOTE;
1741 *(stackblock() + typeloc) = subtype | flags;
1742 if (subtype != VSNORMAL) {
1743 if (level + 1 >= maxnest) {
1744 maxnest *= 2;
1745 if (state == state_static) {
1746 state = parser_temp_alloc(
1747 maxnest * sizeof(*state));
1748 memcpy(state, state_static,
1749 MAXNEST_STATIC * sizeof(*state));
1750 } else
1751 state = parser_temp_realloc(state,
1752 maxnest * sizeof(*state));
1754 level++;
1755 state[level].parenlevel = 0;
1756 if (subtype == VSMINUS || subtype == VSPLUS ||
1757 subtype == VSQUESTION || subtype == VSASSIGN) {
1759 * For operators that were in the Bourne shell,
1760 * inherit the double-quote state.
1762 state[level].syntax = state[level - 1].syntax;
1763 state[level].category = TSTATE_VAR_OLD;
1764 } else {
1766 * The other operators take a pattern,
1767 * so go to BASESYNTAX.
1768 * Also, ' and " are now special, even
1769 * in here documents.
1771 state[level].syntax = BASESYNTAX;
1772 state[level].category = TSTATE_VAR_NEW;
1773 newvarnest++;
1776 } else if (c == '\'' && state[level].syntax == BASESYNTAX) {
1777 /* $'cstylequotes' */
1778 USTPUTC(CTLQUOTEMARK, out);
1779 state[level].syntax = SQSYNTAX;
1780 sqiscstyle = 1;
1781 } else {
1782 USTPUTC('$', out);
1783 pungetc();
1785 goto parsesub_return;
1790 * Parse an arithmetic expansion (indicate start of one and set state)
1792 parsearith: {
1794 if (level + 1 >= maxnest) {
1795 maxnest *= 2;
1796 if (state == state_static) {
1797 state = parser_temp_alloc(
1798 maxnest * sizeof(*state));
1799 memcpy(state, state_static,
1800 MAXNEST_STATIC * sizeof(*state));
1801 } else
1802 state = parser_temp_realloc(state,
1803 maxnest * sizeof(*state));
1805 level++;
1806 state[level].syntax = ARISYNTAX;
1807 state[level].parenlevel = 0;
1808 state[level].category = TSTATE_ARITH;
1809 USTPUTC(CTLARI, out);
1810 if (state[level - 1].syntax == DQSYNTAX)
1811 USTPUTC('"',out);
1812 else
1813 USTPUTC(' ',out);
1814 goto parsearith_return;
1817 } /* end of readtoken */
1821 #ifdef mkinit
1822 RESET {
1823 tokpushback = 0;
1824 checkkwd = 0;
1826 #endif
1829 * Returns true if the text contains nothing to expand (no dollar signs
1830 * or backquotes).
1833 static int
1834 noexpand(char *text)
1836 char *p;
1837 char c;
1839 p = text;
1840 while ((c = *p++) != '\0') {
1841 if ( c == CTLQUOTEMARK)
1842 continue;
1843 if (c == CTLESC)
1844 p++;
1845 else if (BASESYNTAX[(int)c] == CCTL)
1846 return 0;
1848 return 1;
1853 * Return true if the argument is a legal variable name (a letter or
1854 * underscore followed by zero or more letters, underscores, and digits).
1858 goodname(const char *name)
1860 const char *p;
1862 p = name;
1863 if (! is_name(*p))
1864 return 0;
1865 while (*++p) {
1866 if (! is_in_name(*p))
1867 return 0;
1869 return 1;
1874 isassignment(const char *p)
1876 if (!is_name(*p))
1877 return 0;
1878 p++;
1879 for (;;) {
1880 if (*p == '=')
1881 return 1;
1882 else if (!is_in_name(*p))
1883 return 0;
1884 p++;
1890 * Called when an unexpected token is read during the parse. The argument
1891 * is the token that is expected, or -1 if more than one type of token can
1892 * occur at this point.
1895 static void
1896 synexpect(int token)
1898 char msg[64];
1900 if (token >= 0) {
1901 fmtstr(msg, 64, "%s unexpected (expecting %s)",
1902 tokname[lasttoken], tokname[token]);
1903 } else {
1904 fmtstr(msg, 64, "%s unexpected", tokname[lasttoken]);
1906 synerror(msg);
1910 static void
1911 synerror(const char *msg)
1913 if (commandname)
1914 outfmt(out2, "%s: %d: ", commandname, startlinno);
1915 outfmt(out2, "Syntax error: %s\n", msg);
1916 error(NULL);
1919 static void
1920 setprompt(int which)
1922 whichprompt = which;
1924 #ifndef NO_HISTORY
1925 if (!el)
1926 #endif
1928 out2str(getprompt(NULL));
1929 flushout(out2);
1934 * called by editline -- any expansions to the prompt
1935 * should be added here.
1937 const char *
1938 getprompt(void *unused __unused)
1940 static char ps[PROMPTLEN];
1941 const char *fmt;
1942 const char *pwd;
1943 int i, trim;
1946 * Select prompt format.
1948 switch (whichprompt) {
1949 case 0:
1950 fmt = "";
1951 break;
1952 case 1:
1953 fmt = ps1val();
1954 break;
1955 case 2:
1956 fmt = ps2val();
1957 break;
1958 default:
1959 return "??";
1963 * Format prompt string.
1965 for (i = 0; (i < 127) && (*fmt != '\0'); i++, fmt++)
1966 if (*fmt == '\\')
1967 switch (*++fmt) {
1970 * Hostname.
1972 * \h specifies just the local hostname,
1973 * \H specifies fully-qualified hostname.
1975 case 'h':
1976 case 'H':
1977 ps[i] = '\0';
1978 gethostname(&ps[i], PROMPTLEN - i);
1979 /* Skip to end of hostname. */
1980 trim = (*fmt == 'h') ? '.' : '\0';
1981 while ((ps[i+1] != '\0') && (ps[i+1] != trim))
1982 i++;
1983 break;
1986 * Working directory.
1988 * \W specifies just the final component,
1989 * \w specifies the entire path.
1991 case 'W':
1992 case 'w':
1993 pwd = lookupvar("PWD");
1994 if (pwd == NULL)
1995 pwd = "?";
1996 if (*fmt == 'W' &&
1997 *pwd == '/' && pwd[1] != '\0')
1998 strlcpy(&ps[i], strrchr(pwd, '/') + 1,
1999 PROMPTLEN - i);
2000 else
2001 strlcpy(&ps[i], pwd, PROMPTLEN - i);
2002 /* Skip to end of path. */
2003 while (ps[i + 1] != '\0')
2004 i++;
2005 break;
2008 * Superuser status.
2010 * '$' for normal users, '#' for root.
2012 case '$':
2013 ps[i] = (geteuid() != 0) ? '$' : '#';
2014 break;
2017 * A literal \.
2019 case '\\':
2020 ps[i] = '\\';
2021 break;
2024 * Emit unrecognized formats verbatim.
2026 default:
2027 ps[i++] = '\\';
2028 ps[i] = *fmt;
2029 break;
2031 else
2032 ps[i] = *fmt;
2033 ps[i] = '\0';
2034 return (ps);
2038 const char *
2039 expandstr(char *ps)
2041 union node n;
2042 struct jmploc jmploc;
2043 struct jmploc *const savehandler = handler;
2044 const int saveprompt = doprompt;
2045 struct parsefile *const savetopfile = getcurrentfile();
2046 struct parser_temp *const saveparser_temp = parser_temp;
2047 const char *result = NULL;
2049 if (!setjmp(jmploc.loc)) {
2050 handler = &jmploc;
2051 parser_temp = NULL;
2052 setinputstring(ps, 1);
2053 doprompt = 0;
2054 readtoken1(pgetc(), DQSYNTAX, __DECONST(char *, "\n\n"), 0);
2055 if (backquotelist != NULL)
2056 error("Command substitution not allowed here");
2058 n.narg.type = NARG;
2059 n.narg.next = NULL;
2060 n.narg.text = wordtext;
2061 n.narg.backquote = backquotelist;
2063 expandarg(&n, NULL, 0);
2064 result = stackblock();
2065 INTOFF;
2067 handler = savehandler;
2068 doprompt = saveprompt;
2069 popfilesupto(savetopfile);
2070 if (parser_temp != saveparser_temp) {
2071 parser_temp_free_all();
2072 parser_temp = saveparser_temp;
2074 if (result != NULL) {
2075 INTON;
2076 } else if (exception == EXINT)
2077 raise(SIGINT);
2078 return result;