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.
7 * This code is derived from software contributed to Berkeley by
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
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.
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
44 #include "expand.h" /* defines rmescapes() */
45 #include "exec.h" /* defines find_builtin() */
59 #include "myhistedit.h"
63 * Shell command parser.
66 /* values returned by readtoken */
67 #include "token_vars.h"
71 /* Used by expandstr to get here-doc like behaviour. */
72 #define FAKEEOFMARK (char *)1
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 */
85 struct synstack
*prev
;
86 struct synstack
*next
;
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 */
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 */
104 struct nodelist
*backquotelist
;
105 union node
*redirnode
;
106 struct heredoc
*heredoc
;
107 int quoteflag
; /* set if (part of) last token was quoted */
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);
127 int isassignment(const char *p
)
129 const char *q
= endofname(p
);
135 static inline int realeofmark(const char *eofmark
)
137 return eofmark
&& eofmark
!= FAKEEOFMARK
;
142 * Read and parse a command. Returns NEOF on end of file. (NULL is a
143 * valid parse tree indicating a blank line.)
147 parsecmd(int interact
)
163 int chknl
= nlflag
& 1 ? 0 : CHKNL
;
164 union node
*n1
, *n2
, *n3
;
169 checkkwd
= chknl
| CHKKWD
| CHKALIAS
;
187 if (nlflag
== 2 && tokendlist
[tok
])
193 if (tok
== TBACKGND
) {
194 if (n2
->type
== NPIPE
) {
195 n2
->npipe
.backgnd
= 1;
197 if (n2
->type
!= NREDIR
) {
198 n3
= stalloc(sizeof(struct nredir
));
200 n3
->nredir
.redirect
= NULL
;
210 n3
= (union node
*)stalloc(sizeof (struct nbinary
));
212 n3
->nbinary
.ch1
= n1
;
213 n3
->nbinary
.ch2
= n2
;
239 union node
*n1
, *n2
, *n3
;
244 if ((t
= readtoken()) == TAND
) {
246 } else if (t
== TOR
) {
252 checkkwd
= CHKNL
| CHKKWD
| CHKALIAS
;
254 n3
= (union node
*)stalloc(sizeof (struct nbinary
));
256 n3
->nbinary
.ch1
= n1
;
257 n3
->nbinary
.ch2
= n2
;
267 union node
*n1
, *n2
, *pipenode
;
268 struct nodelist
*lp
, *prev
;
272 TRACE(("pipeline: entered\n"));
273 if (readtoken() == TNOT
) {
275 checkkwd
= CHKKWD
| CHKALIAS
;
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
;
288 lp
= (struct nodelist
*)stalloc(sizeof (struct nodelist
));
289 checkkwd
= CHKNL
| CHKKWD
| CHKALIAS
;
292 } while (readtoken() == TPIPE
);
298 n2
= (union node
*)stalloc(sizeof (struct nnot
));
312 union node
*ap
, **app
;
313 union node
*cp
, **cpp
;
314 union node
*redir
, **rpp
;
324 switch (readtoken()) {
329 n1
= (union node
*)stalloc(sizeof (struct nif
));
331 n1
->nif
.test
= list(0);
332 if (readtoken() != TTHEN
)
334 n1
->nif
.ifpart
= list(0);
336 while (readtoken() == TELIF
) {
337 n2
->nif
.elsepart
= (union node
*)stalloc(sizeof (struct nif
));
338 n2
= n2
->nif
.elsepart
;
340 n2
->nif
.test
= list(0);
341 if (readtoken() != TTHEN
)
343 n2
->nif
.ifpart
= list(0);
345 if (lasttoken
== TELSE
)
346 n2
->nif
.elsepart
= list(0);
348 n2
->nif
.elsepart
= NULL
;
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
: ""));
363 n1
->nbinary
.ch2
= list(0);
368 if (readtoken() != TWORD
|| quoteflag
|| ! goodname(wordtext
))
369 synerror("Bad for loop variable");
370 n1
= (union node
*)stalloc(sizeof (struct nfor
));
372 n1
->nfor
.linno
= savelinno
;
373 n1
->nfor
.var
= wordtext
;
374 checkkwd
= CHKNL
| CHKKWD
| CHKALIAS
;
375 if (readtoken() == TIN
) {
377 while (readtoken() == TWORD
) {
378 n2
= (union node
*)stalloc(sizeof (struct narg
));
380 n2
->narg
.text
= wordtext
;
381 n2
->narg
.backquote
= backquotelist
;
383 app
= &n2
->narg
.next
;
387 if (lasttoken
!= TNL
&& lasttoken
!= TSEMI
)
390 n2
= (union node
*)stalloc(sizeof (struct narg
));
392 n2
->narg
.text
= (char *)dolatstr
;
393 n2
->narg
.backquote
= NULL
;
394 n2
->narg
.next
= NULL
;
397 * Newline or semicolon here is optional (but note
398 * that the original Bourne shell only allowed NL).
400 if (lasttoken
!= TSEMI
)
403 checkkwd
= CHKNL
| CHKKWD
| CHKALIAS
;
404 if (readtoken() != TDO
)
406 n1
->nfor
.body
= list(0);
410 n1
= (union node
*)stalloc(sizeof (struct ncase
));
412 n1
->ncase
.linno
= savelinno
;
413 if (readtoken() != TWORD
)
415 n1
->ncase
.expr
= n2
= (union node
*)stalloc(sizeof (struct 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
)
423 cpp
= &n1
->ncase
.cases
;
425 checkkwd
= CHKNL
| CHKKWD
;
428 if (lasttoken
== TLP
)
430 *cpp
= cp
= (union node
*)stalloc(sizeof (struct nclist
));
432 app
= &cp
->nclist
.pattern
;
434 *app
= ap
= (union node
*)stalloc(sizeof (struct narg
));
436 ap
->narg
.text
= wordtext
;
437 ap
->narg
.backquote
= backquotelist
;
438 if (readtoken() != TPIPE
)
440 app
= &ap
->narg
.next
;
443 ap
->narg
.next
= NULL
;
444 if (lasttoken
!= TRP
)
446 cp
->nclist
.body
= list(2);
448 cpp
= &cp
->nclist
.next
;
450 checkkwd
= CHKNL
| CHKKWD
;
451 if ((t
= readtoken()) != TESAC
) {
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
;
478 if (readtoken() != t
)
482 /* Now check for redirection which may follow command */
483 checkkwd
= CHKKWD
| CHKALIAS
;
485 while (readtoken() == TREDIR
) {
486 *rpp
= n2
= redirnode
;
487 rpp
= &n2
->nfile
.next
;
493 if (n1
->type
!= NSUBSHELL
) {
494 n2
= (union node
*)stalloc(sizeof (struct nredir
));
496 n2
->nredir
.linno
= savelinno
;
500 n1
->nredir
.redirect
= redir
;
509 union node
*args
, **app
;
510 union node
*n
= NULL
;
511 union node
*vars
, **vpp
;
512 union node
**rpp
, *redir
;
523 savecheckkwd
= CHKALIAS
;
526 checkkwd
= savecheckkwd
;
527 switch (readtoken()) {
529 n
= (union node
*)stalloc(sizeof (struct narg
));
531 n
->narg
.text
= wordtext
;
532 n
->narg
.backquote
= backquotelist
;
533 if (savecheckkwd
&& isassignment(wordtext
)) {
543 *rpp
= n
= redirnode
;
544 rpp
= &n
->nfile
.next
;
545 parsefname(); /* read name of redirection file */
549 args
&& app
== &args
->narg
.next
&&
552 struct builtincmd
*bcmd
;
555 /* We have a function */
556 if (readtoken() != TRP
)
561 (bcmd
= find_builtin(name
)) &&
562 bcmd
->flags
& BUILTIN_SPECIAL
565 synerror("Bad function name");
567 checkkwd
= CHKNL
| CHKKWD
| CHKALIAS
;
568 n
->ndefun
.text
= n
->narg
.text
;
569 n
->ndefun
.linno
= plinno
;
570 n
->ndefun
.body
= command();
583 n
= (union node
*)stalloc(sizeof (struct ncmd
));
585 n
->ncmd
.linno
= savelinno
;
587 n
->ncmd
.assign
= vars
;
588 n
->ncmd
.redirect
= redir
;
597 n
= (union node
*)stalloc(sizeof (struct narg
));
600 n
->narg
.text
= wordtext
;
601 n
->narg
.backquote
= backquotelist
;
605 void fixredir(union node
*n
, const char *text
, int err
)
607 TRACE(("Fix redir %s %d\n", text
, err
));
609 n
->ndup
.vname
= NULL
;
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')
618 synerror("Bad fd number");
620 n
->ndup
.vname
= makename();
628 union node
*n
= redirnode
;
630 if (n
->type
== NHERE
)
631 checkkwd
= CHKEOFMARK
;
632 if (readtoken() != TWORD
)
634 if (n
->type
== NHERE
) {
635 struct heredoc
*here
= heredoc
;
640 TRACE(("Here document %d\n", n
->type
));
642 here
->eofmark
= wordtext
;
644 if (heredoclist
== NULL
)
647 for (p
= heredoclist
; p
->next
; p
= p
->next
);
650 } else if (n
->type
== NTOFD
|| n
->type
== NFROMFD
) {
651 fixredir(n
, wordtext
, 0);
653 n
->nfile
.fname
= makename();
659 * Input any here documents.
665 struct heredoc
*here
;
675 if (here
->here
->type
== NHERE
)
676 readtoken1(pgetc(), SQSYNTAX
, here
->eofmark
, here
->striptabs
);
678 readtoken1(pgetc_eatbnl(), DQSYNTAX
, here
->eofmark
, here
->striptabs
);
679 n
= (union node
*)stalloc(sizeof (struct narg
));
682 n
->narg
.text
= wordtext
;
683 n
->narg
.backquote
= backquotelist
;
684 here
->here
->nhere
.doc
= n
;
695 int alreadyseen
= tokpushback
;
715 if (t
!= TWORD
|| quoteflag
) {
723 const char *const *pp
;
725 if ((pp
= findkwd(wordtext
))) {
726 lasttoken
= t
= pp
- parsekwd
+ KWDOFFSET
;
727 TRACE(("keyword %s recognized\n", tokname
[t
]));
732 if (kwd
& CHKALIAS
) {
734 if ((ap
= lookupalias(wordtext
, 1)) != NULL
) {
736 pushstring(ap
->val
, ap
);
744 TRACE(("token %s %s\n", tokname
[t
], t
== TWORD
? wordtext
: ""));
746 TRACE(("reread token %s %s\n", tokname
[t
], t
== TWORD
? wordtext
: ""));
751 static void nlprompt(void)
758 static void nlnoprompt(void)
761 needprompt
= doprompt
;
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
770 * If the token is TREDIR, then we set redirnode to a structure containing
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.]
781 #define RETURN(token) return lasttoken = token
795 for (;;) { /* until token or start of word found */
801 while ((c
= pgetc()) != '\n' && c
!= PEOF
);
810 if (pgetc_eatbnl() == '&')
815 if (pgetc_eatbnl() == '|')
820 if (pgetc_eatbnl() == ';')
831 return readtoken1(c
, BASESYNTAX
, (char *)NULL
, 0);
835 static int pgetc_eatbnl(void)
839 while ((c
= pgetc()) == '\\') {
840 if (pgetc() != '\n') {
851 static int pgetc_top(struct synstack
*stack
)
853 return stack
->syntax
== SQSYNTAX
? pgetc() : pgetc_eatbnl();
856 static void synstack_push(struct synstack
**stack
, struct synstack
*next
,
859 memset(next
, 0, sizeof(*next
));
860 next
->syntax
= syntax
;
862 (*stack
)->prev
= next
;
866 static void synstack_pop(struct synstack
**stack
)
868 *stack
= (*stack
)->next
;
874 * If eofmark is NULL, read a word or a redirection symbol. If eofmark
875 * is not NULL, read a here document. In the latter case, eofmark is the
876 * word which marks the end of the document and striptabs is true if
877 * leading tabs should be stripped from the document. The argument firstc
878 * is the first character of the input token or document.
880 * Because C does not have internal subroutines, I have simulated them
881 * using goto's to implement the subroutine linkage. The following macros
882 * will run code that appears at the end of readtoken1.
885 #define CHECKEND() {goto checkend; checkend_return:;}
886 #define PARSEREDIR() {goto parseredir; parseredir_return:;}
887 #define PARSESUB() {goto parsesub; parsesub_return:;}
888 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
889 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
890 #define PARSEARITH() {goto parsearith; parsearith_return:;}
893 readtoken1(int firstc
, char const *syntax
, char *eofmark
, int striptabs
)
898 struct nodelist
*bqlist
;
902 struct synstack synbase
= { .syntax
= syntax
};
903 struct synstack
*synstack
= &synbase
;
905 if (syntax
== DQSYNTAX
)
906 synstack
->dblquote
= 1;
911 loop
: { /* for each line, until end of word */
913 if (c
== '\034' && doprompt
914 && attyset() && ! equal(termval(), "emacs")) {
916 if (synstack
->syntax
== BASESYNTAX
)
918 c
= pgetc_top(synstack
);
922 CHECKEND(); /* set c to PEOF if at end of here document */
923 for (;;) { /* until end of line or end of word */
924 CHECKSTRSPACE(4, out
); /* permit 4 calls to USTPUTC */
925 switch(synstack
->syntax
[c
]) {
927 if (synstack
->syntax
== BASESYNTAX
&&
929 goto endword
; /* exit outer loop */
932 c
= pgetc_top(synstack
);
933 goto loop
; /* continue outer loop */
938 if ((!eofmark
) | synstack
->dblquote
|
940 USTPUTC(CTLESC
, out
);
947 USTPUTC(CTLESC
, out
);
952 synstack
->dblquote
&&
953 c
!= '\\' && c
!= '`' &&
963 USTPUTC(CTLESC
, out
);
966 USTPUTC(CTLESC
, out
);
972 synstack
->syntax
= SQSYNTAX
;
974 if (eofmark
== NULL
) {
975 USTPUTC(CTLQUOTEMARK
, out
);
979 synstack
->syntax
= DQSYNTAX
;
980 synstack
->dblquote
= 1;
982 if (synstack
->varnest
)
983 synstack
->innerdq
^= 1;
986 if (eofmark
&& !synstack
->varnest
) {
991 if (synstack
->dqvarnest
== 0) {
992 synstack
->syntax
= BASESYNTAX
;
993 synstack
->dblquote
= 0;
1002 case CVAR
: /* '$' */
1003 PARSESUB(); /* parse substitution */
1005 case CENDVAR
: /* '}' */
1006 if (!synstack
->innerdq
&&
1007 synstack
->varnest
> 0) {
1008 if (!--synstack
->varnest
&&
1009 synstack
->varpushed
)
1010 synstack_pop(&synstack
);
1011 else if (synstack
->dqvarnest
> 0)
1012 synstack
->dqvarnest
--;
1013 USTPUTC(CTLENDVAR
, out
);
1018 case CLP
: /* '(' in arithmetic */
1019 synstack
->parenlevel
++;
1022 case CRP
: /* ')' in arithmetic */
1023 if (synstack
->parenlevel
> 0) {
1025 --synstack
->parenlevel
;
1027 if (pgetc_eatbnl() == ')') {
1028 USTPUTC(CTLENDARI
, out
);
1029 synstack_pop(&synstack
);
1033 * (don't 2nd guess - no error)
1040 case CBQUOTE
: /* '`' */
1041 if (checkkwd
& CHKEOFMARK
) {
1049 goto endword
; /* exit outer loop */
1051 if (synstack
->varnest
== 0)
1052 goto endword
; /* exit outer loop */
1055 c
= pgetc_top(synstack
);
1059 if (synstack
->syntax
== ARISYNTAX
)
1060 synerror("Missing '))'");
1061 if (synstack
->syntax
!= BASESYNTAX
&& eofmark
== NULL
)
1062 synerror("Unterminated quoted string");
1063 if (synstack
->varnest
!= 0) {
1065 synerror("Missing '}'");
1068 len
= out
- (char *)stackblock();
1070 if (eofmark
== NULL
) {
1071 if ((c
== '>' || c
== '<')
1074 && (*out
== '\0' || is_digit(*out
))) {
1076 return lasttoken
= TREDIR
;
1082 backquotelist
= bqlist
;
1083 grabstackblock(len
);
1085 return lasttoken
= TWORD
;
1086 /* end of readtoken routine */
1091 * Check to see whether we are at the end of the here document. When this
1092 * is called, c is set to the first character of the next input line. If
1093 * we are at the end of the here document, this routine sets the c to PEOF.
1097 if (realeofmark(eofmark
)) {
1106 markloc
= out
- (char *)stackblock();
1107 for (p
= eofmark
; STPUTC(c
, out
), *p
; p
++) {
1114 if (c
== '\n' || c
== PEOF
) {
1121 p
= (char *)stackblock() + markloc
+ 1;
1131 str
= alloca(len
+ 1);
1132 *(char *)mempcpy(str
, p
, len
) = 0;
1134 pushstring(str
, NULL
);
1139 STADJUST((char *)stackblock() + markloc
- out
, out
);
1141 goto checkend_return
;
1146 * Parse a redirection operator. The variable "out" points to a string
1147 * specifying the fd to be redirected. The variable "c" contains the
1148 * first character of the redirection operator.
1155 np
= (union node
*)stalloc(sizeof (struct nfile
));
1162 np
->type
= NCLOBBER
;
1169 } else { /* c == '<' */
1171 switch (c
= pgetc_eatbnl()) {
1173 if (sizeof (struct nfile
) != sizeof (struct nhere
)) {
1174 np
= (union node
*)stalloc(sizeof (struct nhere
));
1178 heredoc
= (struct heredoc
*)stalloc(sizeof (struct heredoc
));
1180 if ((c
= pgetc_eatbnl()) == '-') {
1181 heredoc
->striptabs
= 1;
1183 heredoc
->striptabs
= 0;
1203 np
->nfile
.fd
= digit_val(fd
);
1205 goto parseredir_return
;
1210 * Parse a substitution. At this point, we have read the dollar sign
1218 static const char types
[] = "}-+?=";
1222 (checkkwd
& CHKEOFMARK
) ||
1223 (c
!= '(' && c
!= '{' && !is_name(c
) && !is_special(c
))
1227 } else if (c
== '(') { /* $(command) or $((arith)) */
1228 if (pgetc_eatbnl() == '(') {
1235 const char *newsyn
= synstack
->syntax
;
1237 USTPUTC(CTLVAR
, out
);
1238 typeloc
= out
- (char *)stackblock();
1241 if (likely(c
== '{')) {
1250 } while (is_in_name(c
));
1251 } else if (is_digit(c
)) {
1255 } while ((subtype
<= 0 || subtype
>= VSLENGTH
) &&
1257 } else if (c
!= '}') {
1262 if (!subtype
&& cc
== '#') {
1265 if (c
== '_' || isalnum(c
))
1270 if (cc
== '}' || c
!= '}') {
1278 if (!is_special(cc
)) {
1279 if (subtype
== VSLENGTH
)
1297 p
= strchr(types
, c
);
1300 subtype
|= p
- types
+ VSNORMAL
;
1304 subtype
= c
== '#' ? VSTRIMLEFT
:
1312 newsyn
= BASESYNTAX
;
1316 if (subtype
== VSLENGTH
&& c
!= '}')
1322 if (newsyn
== ARISYNTAX
)
1325 if ((newsyn
!= synstack
->syntax
|| synstack
->innerdq
) &&
1326 subtype
!= VSNORMAL
) {
1327 synstack_push(&synstack
,
1329 alloca(sizeof(*synstack
)),
1332 synstack
->varpushed
++;
1333 synstack
->dblquote
= newsyn
!= BASESYNTAX
;
1336 *((char *)stackblock() + typeloc
) = subtype
| VSBIT
;
1337 if (subtype
!= VSNORMAL
) {
1338 synstack
->varnest
++;
1339 if (synstack
->dblquote
)
1340 synstack
->dqvarnest
++;
1344 goto parsesub_return
;
1349 * Called to parse command substitutions. Newstyle is set if the command
1350 * is enclosed inside $(...); nlpp is a pointer to the head of the linked
1351 * list of commands (passed by reference), and savelen is the number of
1352 * characters on the top of the stack which must be preserved.
1356 struct nodelist
**nlpp
;
1360 struct heredoc
*saveheredoclist
;
1361 int uninitialized_var(saveprompt
);
1364 savelen
= out
- (char *)stackblock();
1366 str
= alloca(savelen
);
1367 memcpy(str
, stackblock(), savelen
);
1370 /* We must read until the closing backquote, giving special
1371 treatment to some slashes, and then push the string and
1372 reread it as input, interpreting it normally. */
1379 STARTSTACKSTR(pout
);
1384 switch (pc
= pgetc_eatbnl()) {
1390 if (pc
!= '\\' && pc
!= '`' && pc
!= '$'
1391 && (!synstack
->dblquote
|| pc
!= '"'))
1396 synerror("EOF in backquote substitution");
1409 psavelen
= pout
- (char *)stackblock();
1411 pstr
= grabstackstr(pout
);
1412 setinputstring(pstr
);
1417 nlpp
= &(*nlpp
)->next
;
1418 *nlpp
= (struct nodelist
*)stalloc(sizeof (struct nodelist
));
1419 (*nlpp
)->next
= NULL
;
1421 saveheredoclist
= heredoclist
;
1425 saveprompt
= doprompt
;
1432 doprompt
= saveprompt
;
1434 if (readtoken() != TRP
)
1436 setinputstring(nullstr
);
1440 heredoclist
= saveheredoclist
;
1443 /* Start reading from old file again. */
1445 /* Ignore any pushed back tokens left from the backquote parsing. */
1448 out
= growstackto(savelen
+ 1);
1450 memcpy(out
, str
, savelen
);
1451 STADJUST(savelen
, out
);
1453 USTPUTC(CTLBACKQ
, out
);
1455 goto parsebackq_oldreturn
;
1457 goto parsebackq_newreturn
;
1461 * Parse an arithmetic expansion (indicate start of one and set state)
1465 synstack_push(&synstack
,
1466 synstack
->prev
?: alloca(sizeof(*synstack
)),
1468 synstack
->dblquote
= 1;
1469 USTPUTC(CTLARI
, out
);
1470 goto parsearith_return
;
1473 } /* end of readtoken */
1483 * Return of a legal variable name (a letter or underscore followed by zero or
1484 * more letters, underscores, and digits).
1488 endofname(const char *name
)
1496 if (! is_in_name(*p
))
1504 * Called when an unexpected token is read during the parse. The argument
1505 * is the token that is expected, or -1 if more than one type of token can
1506 * occur at this point.
1510 synexpect(int token
)
1515 fmtstr(msg
, 64, "%s unexpected (expecting %s)",
1516 tokname
[lasttoken
], tokname
[token
]);
1518 fmtstr(msg
, 64, "%s unexpected", tokname
[lasttoken
]);
1526 synerror(const char *msg
)
1529 sh_error("Syntax error: %s", msg
);
1534 setprompt(int which
)
1536 struct stackmark smark
;
1540 whichprompt
= which
;
1548 pushstackmark(&smark
, stackblocksize());
1549 out2str(getprompt(NULL
));
1550 popstackmark(&smark
);
1555 expandstr(const char *ps
)
1557 struct parsefile
*file_stop
;
1558 struct jmploc
*volatile savehandler
;
1559 struct heredoc
*saveheredoclist
;
1562 struct jmploc jmploc
;
1566 file_stop
= parsefile
;
1568 /* XXX Fix (char *) cast. */
1569 setinputstring((char *)ps
);
1571 saveheredoclist
= heredoclist
;
1573 saveprompt
= doprompt
;
1576 savehandler
= handler
;
1577 if (unlikely(err
= setjmp(jmploc
.loc
)))
1581 readtoken1(pgetc_eatbnl(), DQSYNTAX
, FAKEEOFMARK
, 0);
1585 n
.narg
.text
= wordtext
;
1586 n
.narg
.backquote
= backquotelist
;
1588 expandarg(&n
, NULL
, EXP_QUOTED
);
1589 result
= stackblock();
1592 restore_handler_expandarg(savehandler
, err
);
1594 doprompt
= saveprompt
;
1595 unwindfiles(file_stop
);
1596 heredoclist
= saveheredoclist
;
1602 * called by editline -- any expansions to the prompt
1603 * should be added here.
1606 getprompt(void *unused
)
1610 switch (whichprompt
) {
1613 return "<internal prompt error>";
1625 return expandstr(prompt
);
1629 findkwd(const char *s
)
1632 s
, parsekwd
, sizeof(parsekwd
) / sizeof(const char *)