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() */
60 #include "myhistedit.h"
64 * Shell command parser.
67 /* values returned by readtoken */
68 #include "token_vars.h"
72 /* Used by expandstr to get here-doc like behaviour. */
73 #define FAKEEOFMARK (char *)1
78 struct heredoc
*next
; /* next here document in list */
79 union node
*here
; /* redirection node */
80 char *eofmark
; /* string indicating end of input */
81 int striptabs
; /* if set, strip leading tabs */
86 struct synstack
*prev
;
87 struct synstack
*next
;
91 int varnest
; /* levels of variables expansion */
92 int parenlevel
; /* levels of parens in arithmetic */
93 int dqvarnest
; /* levels of variables expansion within double quotes */
98 struct heredoc
*heredoclist
; /* list of here documents to read */
99 int doprompt
; /* if set, prompt the user */
100 int needprompt
; /* true if interactive and at start of line */
101 int lasttoken
; /* last token read */
102 int tokpushback
; /* last token pushed back */
103 char *wordtext
; /* text of last word returned by readtoken */
105 struct nodelist
*backquotelist
;
106 union node
*redirnode
;
107 struct heredoc
*heredoc
;
108 int quoteflag
; /* set if (part of) last token was quoted */
111 STATIC
union node
*list(int);
112 STATIC
union node
*andor(void);
113 STATIC
union node
*pipeline(void);
114 STATIC
union node
*command(void);
115 STATIC
union node
*simplecmd(void);
116 STATIC
union node
*makename(void);
117 STATIC
void parsefname(void);
118 STATIC
void parseheredoc(void);
119 STATIC
int readtoken(void);
120 STATIC
int xxreadtoken(void);
121 STATIC
int pgetc_eatbnl();
122 STATIC
int readtoken1(int, char const *, char *, int);
123 STATIC
void synexpect(int) __attribute__((__noreturn__
));
124 STATIC
void synerror(const char *) __attribute__((__noreturn__
));
125 STATIC
void setprompt(int);
128 int isassignment(const char *p
)
130 const char *q
= endofname(p
);
136 int issimplecmd(union node
*n
, const char *name
)
138 return n
&& n
->type
== NCMD
&& n
->ncmd
.args
&&
139 equal(n
->ncmd
.args
->narg
.text
, name
);
142 static inline int realeofmark(const char *eofmark
)
144 return eofmark
&& eofmark
!= FAKEEOFMARK
;
149 * Read and parse a command. Returns NEOF on end of file. (NULL is a
150 * valid parse tree indicating a blank line.)
154 parsecmd(int interact
)
170 int chknl
= nlflag
& 1 ? 0 : CHKNL
;
171 union node
*n1
, *n2
, *n3
;
176 checkkwd
= chknl
| CHKKWD
| CHKALIAS
;
194 if (nlflag
== 2 && tokendlist
[tok
])
200 if (tok
== TBACKGND
) {
201 if (n2
->type
== NPIPE
) {
202 n2
->npipe
.backgnd
= 1;
204 if (n2
->type
!= NREDIR
) {
205 n3
= stalloc(sizeof(struct nredir
));
207 n3
->nredir
.redirect
= NULL
;
217 n3
= (union node
*)stalloc(sizeof (struct nbinary
));
219 n3
->nbinary
.ch1
= n1
;
220 n3
->nbinary
.ch2
= n2
;
246 union node
*n1
, *n2
, *n3
;
251 if ((t
= readtoken()) == TAND
) {
253 } else if (t
== TOR
) {
259 checkkwd
= CHKNL
| CHKKWD
| CHKALIAS
;
261 n3
= (union node
*)stalloc(sizeof (struct nbinary
));
263 n3
->nbinary
.ch1
= n1
;
264 n3
->nbinary
.ch2
= n2
;
274 union node
*n1
, *n2
, *pipenode
;
275 struct nodelist
*lp
, *prev
;
279 TRACE(("pipeline: entered\n"));
280 if (readtoken() == TNOT
) {
282 checkkwd
= CHKKWD
| CHKALIAS
;
286 if (readtoken() == TPIPE
) {
287 pipenode
= (union node
*)stalloc(sizeof (struct npipe
));
288 pipenode
->type
= NPIPE
;
289 pipenode
->npipe
.backgnd
= 0;
290 lp
= (struct nodelist
*)stalloc(sizeof (struct nodelist
));
291 pipenode
->npipe
.cmdlist
= lp
;
295 lp
= (struct nodelist
*)stalloc(sizeof (struct nodelist
));
296 checkkwd
= CHKNL
| CHKKWD
| CHKALIAS
;
299 } while (readtoken() == TPIPE
);
305 n2
= (union node
*)stalloc(sizeof (struct nnot
));
319 union node
*ap
, **app
;
320 union node
*cp
, **cpp
;
321 union node
*redir
, **rpp
;
331 switch (readtoken()) {
336 n1
= (union node
*)stalloc(sizeof (struct nif
));
338 n1
->nif
.test
= list(0);
339 if (readtoken() != TTHEN
)
341 n1
->nif
.ifpart
= list(0);
343 while (readtoken() == TELIF
) {
344 n2
->nif
.elsepart
= (union node
*)stalloc(sizeof (struct nif
));
345 n2
= n2
->nif
.elsepart
;
347 n2
->nif
.test
= list(0);
348 if (readtoken() != TTHEN
)
350 n2
->nif
.ifpart
= list(0);
352 if (lasttoken
== TELSE
)
353 n2
->nif
.elsepart
= list(0);
355 n2
->nif
.elsepart
= NULL
;
363 n1
= (union node
*)stalloc(sizeof (struct nbinary
));
364 n1
->type
= (lasttoken
== TWHILE
)? NWHILE
: NUNTIL
;
365 n1
->nbinary
.ch1
= list(0);
366 if ((got
=readtoken()) != TDO
) {
367 TRACE(("expecting DO got %s %s\n", tokname
[got
], got
== TWORD
? wordtext
: ""));
370 n1
->nbinary
.ch2
= list(0);
375 if (readtoken() != TWORD
|| quoteflag
|| ! goodname(wordtext
))
376 synerror("Bad for loop variable");
377 n1
= (union node
*)stalloc(sizeof (struct nfor
));
379 n1
->nfor
.linno
= savelinno
;
380 n1
->nfor
.var
= wordtext
;
381 checkkwd
= CHKNL
| CHKKWD
| CHKALIAS
;
382 if (readtoken() == TIN
) {
384 while (readtoken() == TWORD
) {
385 n2
= (union node
*)stalloc(sizeof (struct narg
));
387 n2
->narg
.text
= wordtext
;
388 n2
->narg
.backquote
= backquotelist
;
390 app
= &n2
->narg
.next
;
394 if (lasttoken
!= TNL
&& lasttoken
!= TSEMI
)
397 n2
= (union node
*)stalloc(sizeof (struct narg
));
399 n2
->narg
.text
= (char *)dolatstr
;
400 n2
->narg
.backquote
= NULL
;
401 n2
->narg
.next
= NULL
;
404 * Newline or semicolon here is optional (but note
405 * that the original Bourne shell only allowed NL).
407 if (lasttoken
!= TSEMI
)
410 checkkwd
= CHKNL
| CHKKWD
| CHKALIAS
;
411 if (readtoken() != TDO
)
413 n1
->nfor
.body
= list(0);
417 n1
= (union node
*)stalloc(sizeof (struct ncase
));
419 n1
->ncase
.linno
= savelinno
;
420 if (readtoken() != TWORD
)
422 n1
->ncase
.expr
= n2
= (union node
*)stalloc(sizeof (struct narg
));
424 n2
->narg
.text
= wordtext
;
425 n2
->narg
.backquote
= backquotelist
;
426 n2
->narg
.next
= NULL
;
427 checkkwd
= CHKNL
| CHKKWD
| CHKALIAS
;
428 if (readtoken() != TIN
)
430 cpp
= &n1
->ncase
.cases
;
432 checkkwd
= CHKNL
| CHKKWD
;
435 if (lasttoken
== TLP
)
437 *cpp
= cp
= (union node
*)stalloc(sizeof (struct nclist
));
439 app
= &cp
->nclist
.pattern
;
441 *app
= ap
= (union node
*)stalloc(sizeof (struct narg
));
443 ap
->narg
.text
= wordtext
;
444 ap
->narg
.backquote
= backquotelist
;
445 if (readtoken() != TPIPE
)
447 app
= &ap
->narg
.next
;
450 ap
->narg
.next
= NULL
;
451 if (lasttoken
!= TRP
)
453 cp
->nclist
.body
= list(2);
455 cpp
= &cp
->nclist
.next
;
457 checkkwd
= CHKNL
| CHKKWD
;
458 if ((t
= readtoken()) != TESAC
) {
468 n1
= (union node
*)stalloc(sizeof (struct nredir
));
469 n1
->type
= NSUBSHELL
;
470 n1
->nredir
.linno
= savelinno
;
471 n1
->nredir
.n
= list(0);
472 n1
->nredir
.redirect
= NULL
;
485 if (readtoken() != t
)
489 /* Now check for redirection which may follow command */
490 checkkwd
= CHKKWD
| CHKALIAS
;
492 while (readtoken() == TREDIR
) {
493 *rpp
= n2
= redirnode
;
494 rpp
= &n2
->nfile
.next
;
500 if (n1
->type
!= NSUBSHELL
) {
501 n2
= (union node
*)stalloc(sizeof (struct nredir
));
503 n2
->nredir
.linno
= savelinno
;
507 n1
->nredir
.redirect
= redir
;
516 union node
*args
, **app
;
517 union node
*n
= NULL
;
518 union node
*vars
, **vpp
;
519 union node
**rpp
, *redir
;
530 savecheckkwd
= CHKALIAS
;
533 checkkwd
= savecheckkwd
;
534 switch (readtoken()) {
536 n
= (union node
*)stalloc(sizeof (struct narg
));
538 n
->narg
.text
= wordtext
;
539 n
->narg
.backquote
= backquotelist
;
540 if (savecheckkwd
&& isassignment(wordtext
)) {
550 *rpp
= n
= redirnode
;
551 rpp
= &n
->nfile
.next
;
552 parsefname(); /* read name of redirection file */
556 args
&& app
== &args
->narg
.next
&&
559 struct builtincmd
*bcmd
;
562 /* We have a function */
563 if (readtoken() != TRP
)
568 (bcmd
= find_builtin(name
)) &&
569 bcmd
->flags
& BUILTIN_SPECIAL
572 synerror("Bad function name");
574 checkkwd
= CHKNL
| CHKKWD
| CHKALIAS
;
575 n
->ndefun
.text
= n
->narg
.text
;
576 n
->ndefun
.linno
= plinno
;
577 n
->ndefun
.body
= command();
590 n
= (union node
*)stalloc(sizeof (struct ncmd
));
592 n
->ncmd
.linno
= savelinno
;
594 n
->ncmd
.assign
= vars
;
595 n
->ncmd
.redirect
= redir
;
604 n
= (union node
*)stalloc(sizeof (struct narg
));
607 n
->narg
.text
= wordtext
;
608 n
->narg
.backquote
= backquotelist
;
612 void fixredir(union node
*n
, const char *text
, int err
)
614 TRACE(("Fix redir %s %d\n", text
, err
));
616 n
->ndup
.vname
= NULL
;
618 if (is_digit(text
[0]) && text
[1] == '\0')
619 n
->ndup
.dupfd
= digit_val(text
[0]);
620 else if (text
[0] == '-' && text
[1] == '\0')
625 sh_error("Bad fd number: %s", text
);
627 n
->ndup
.vname
= makename();
635 union node
*n
= redirnode
;
637 if (n
->type
== NHERE
)
638 checkkwd
|= CHKEOFMARK
;
639 if (readtoken() != TWORD
)
641 checkkwd
&= ~CHKEOFMARK
;
642 if (n
->type
== NHERE
) {
643 struct heredoc
*here
= heredoc
;
648 TRACE(("Here document %d\n", n
->type
));
650 here
->eofmark
= wordtext
;
652 if (heredoclist
== NULL
)
655 for (p
= heredoclist
; p
->next
; p
= p
->next
);
658 } else if (n
->type
== NTOFD
|| n
->type
== NFROMFD
) {
659 fixredir(n
, wordtext
, 0);
661 n
->nfile
.fname
= makename();
667 * Input any here documents.
673 struct heredoc
*here
;
683 if (here
->here
->type
== NHERE
)
684 readtoken1(pgetc(), SQSYNTAX
, here
->eofmark
, here
->striptabs
);
686 readtoken1(pgetc_eatbnl(), DQSYNTAX
, here
->eofmark
, here
->striptabs
);
687 n
= (union node
*)stalloc(sizeof (struct narg
));
690 n
->narg
.text
= wordtext
;
691 n
->narg
.backquote
= backquotelist
;
692 here
->here
->nhere
.doc
= n
;
703 int alreadyseen
= tokpushback
;
723 if (t
!= TWORD
|| quoteflag
) {
731 const char *const *pp
;
733 if ((pp
= findkwd(wordtext
))) {
734 lasttoken
= t
= pp
- parsekwd
+ KWDOFFSET
;
735 TRACE(("keyword %s recognized\n", tokname
[t
]));
740 if (kwd
& CHKALIAS
) {
742 if ((ap
= lookupalias(wordtext
, 1)) != NULL
) {
744 pushstring(ap
->val
, ap
);
752 TRACE(("token %s %s\n", tokname
[t
], t
== TWORD
? wordtext
: ""));
754 TRACE(("reread token %s %s\n", tokname
[t
], t
== TWORD
? wordtext
: ""));
759 static void nlprompt(void)
766 static void nlnoprompt(void)
769 needprompt
= doprompt
;
774 * Read the next input token.
775 * If the token is a word, we set backquotelist to the list of cmds in
776 * backquotes. We set quoteflag to true if any part of the word was
778 * If the token is TREDIR, then we set redirnode to a structure containing
781 * [Change comment: here documents and internal procedures]
782 * [Readtoken shouldn't have any arguments. Perhaps we should make the
783 * word parsing code into a separate routine. In this case, readtoken
784 * doesn't need to have any internal procedures, but parseword does.
785 * We could also make parseoperator in essence the main routine, and
786 * have parseword (readtoken1?) handle both words and redirection.]
789 #define RETURN(token) return lasttoken = token
803 for (;;) { /* until token or start of word found */
809 while ((c
= pgetc()) != '\n' && c
!= PEOF
);
818 if (pgetc_eatbnl() == '&')
823 if (pgetc_eatbnl() == '|')
828 if (pgetc_eatbnl() == ';')
839 return readtoken1(c
, BASESYNTAX
, (char *)NULL
, 0);
843 static int pgetc_eatbnl(void)
847 while ((c
= pgetc()) == '\\') {
848 if (pgetc() != '\n') {
859 static int pgetc_top(struct synstack
*stack
)
861 return stack
->syntax
== SQSYNTAX
? pgetc() : pgetc_eatbnl();
864 static void synstack_push(struct synstack
**stack
, struct synstack
*next
,
867 memset(next
, 0, sizeof(*next
));
868 next
->syntax
= syntax
;
870 (*stack
)->prev
= next
;
874 static void synstack_pop(struct synstack
**stack
)
876 *stack
= (*stack
)->next
;
882 * If eofmark is NULL, read a word or a redirection symbol. If eofmark
883 * is not NULL, read a here document. In the latter case, eofmark is the
884 * word which marks the end of the document and striptabs is true if
885 * leading tabs should be stripped from the document. The argument firstc
886 * is the first character of the input token or document.
888 * Because C does not have internal subroutines, I have simulated them
889 * using goto's to implement the subroutine linkage. The following macros
890 * will run code that appears at the end of readtoken1.
893 #define CHECKEND() {goto checkend; checkend_return:;}
894 #define PARSEREDIR() {goto parseredir; parseredir_return:;}
895 #define PARSESUB() {goto parsesub; parsesub_return:;}
896 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
897 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
898 #define PARSEARITH() {goto parsearith; parsearith_return:;}
901 readtoken1(int firstc
, char const *syntax
, char *eofmark
, int striptabs
)
906 struct nodelist
*bqlist
;
910 struct synstack synbase
= { .syntax
= syntax
};
911 struct synstack
*synstack
= &synbase
;
912 int chkeofmark
= checkkwd
& CHKEOFMARK
;
914 if (syntax
== DQSYNTAX
)
915 synstack
->dblquote
= 1;
920 loop
: { /* for each line, until end of word */
922 if (c
== '\034' && doprompt
923 && attyset() && ! equal(termval(), "emacs")) {
925 if (synstack
->syntax
== BASESYNTAX
)
927 c
= pgetc_top(synstack
);
931 CHECKEND(); /* set c to PEOF if at end of here document */
932 for (;;) { /* until end of line or end of word */
933 CHECKSTRSPACE(4, out
); /* permit 4 calls to USTPUTC */
934 switch(synstack
->syntax
[c
]) {
936 if (synstack
->syntax
== BASESYNTAX
&&
938 goto endword
; /* exit outer loop */
941 c
= pgetc_top(synstack
);
942 goto loop
; /* continue outer loop */
947 if ((!eofmark
) | synstack
->dblquote
|
949 USTPUTC(CTLESC
, out
);
956 USTPUTC(CTLESC
, out
);
961 synstack
->dblquote
&&
962 c
!= '\\' && c
!= '`' &&
972 USTPUTC(CTLESC
, out
);
975 USTPUTC(CTLESC
, out
);
981 synstack
->syntax
= SQSYNTAX
;
983 if (eofmark
== NULL
) {
984 USTPUTC(CTLQUOTEMARK
, out
);
988 synstack
->syntax
= DQSYNTAX
;
989 synstack
->dblquote
= 1;
991 if (synstack
->varnest
)
992 synstack
->innerdq
^= 1;
995 if (eofmark
&& !synstack
->varnest
) {
1000 if (synstack
->dqvarnest
== 0) {
1001 synstack
->syntax
= BASESYNTAX
;
1002 synstack
->dblquote
= 0;
1011 case CVAR
: /* '$' */
1012 PARSESUB(); /* parse substitution */
1014 case CENDVAR
: /* '}' */
1015 if (!synstack
->innerdq
&&
1016 synstack
->varnest
> 0) {
1017 if (!--synstack
->varnest
&&
1018 synstack
->varpushed
)
1019 synstack_pop(&synstack
);
1020 else if (synstack
->dqvarnest
> 0)
1021 synstack
->dqvarnest
--;
1027 case CLP
: /* '(' in arithmetic */
1028 synstack
->parenlevel
++;
1031 case CRP
: /* ')' in arithmetic */
1032 if (synstack
->parenlevel
> 0)
1033 --synstack
->parenlevel
;
1034 else if (pgetc_eatbnl() == ')') {
1035 synstack_pop(&synstack
);
1043 * (don't 2nd guess - no error)
1049 case CBQUOTE
: /* '`' */
1054 goto endword
; /* exit outer loop */
1056 if (synstack
->varnest
== 0)
1057 goto endword
; /* exit outer loop */
1060 c
= pgetc_top(synstack
);
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) {
1070 synerror("Missing '}'");
1073 len
= out
- (char *)stackblock();
1075 if (eofmark
== NULL
) {
1076 if ((c
== '>' || c
== '<')
1079 && (*out
== '\0' || is_digit(*out
))) {
1081 return lasttoken
= TREDIR
;
1087 backquotelist
= bqlist
;
1088 grabstackblock(len
);
1090 return lasttoken
= TWORD
;
1091 /* end of readtoken routine */
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.
1102 if (realeofmark(eofmark
)) {
1111 markloc
= out
- (char *)stackblock();
1112 for (p
= eofmark
; STPUTC(c
, out
), *p
; p
++) {
1119 if (c
== '\n' || c
== PEOF
) {
1126 p
= (char *)stackblock() + markloc
+ 1;
1136 str
= alloca(len
+ 1);
1137 *(char *)mempcpy(str
, p
, len
) = 0;
1139 pushstring(str
, NULL
);
1144 STADJUST((char *)stackblock() + markloc
- out
, out
);
1146 goto checkend_return
;
1151 * Parse a redirection operator. The variable "out" points to a string
1152 * specifying the fd to be redirected. The variable "c" contains the
1153 * first character of the redirection operator.
1160 np
= (union node
*)stalloc(sizeof (struct nfile
));
1167 np
->type
= NCLOBBER
;
1174 } else { /* c == '<' */
1176 switch (c
= pgetc_eatbnl()) {
1178 if (sizeof (struct nfile
) != sizeof (struct nhere
)) {
1179 np
= (union node
*)stalloc(sizeof (struct nhere
));
1183 heredoc
= (struct heredoc
*)stalloc(sizeof (struct heredoc
));
1185 if ((c
= pgetc_eatbnl()) == '-') {
1186 heredoc
->striptabs
= 1;
1188 heredoc
->striptabs
= 0;
1208 np
->nfile
.fd
= digit_val(fd
);
1210 goto parseredir_return
;
1215 * Parse a substitution. At this point, we have read the dollar sign
1223 static const char types
[] = "}-+?=";
1226 if (c
!= '(' && c
!= '{' && !is_name(c
) && !is_special(c
)) {
1229 goto parsesub_return
;
1234 if (c
== '(') { /* $(command) or $((arith)) */
1236 if (pgetc_eatbnl() == '(') {
1243 const char *newsyn
= synstack
->syntax
;
1245 typeloc
= out
- (char *)stackblock();
1251 if (likely(c
== '{')) {
1262 } while (is_in_name(c
));
1263 } else if (is_digit(c
)) {
1267 } while ((subtype
<= 0 || subtype
>= VSLENGTH
) &&
1269 } else if (c
!= '}') {
1274 if (!subtype
&& cc
== '#') {
1277 if (c
== '_' || isalnum(c
)) {
1285 if (cc
== '}' || c
!= '}') {
1290 } else if (chkeofmark
)
1294 if (!is_special(cc
)) {
1295 if (subtype
== VSLENGTH
)
1318 p
= strchr(types
, c
);
1321 subtype
|= p
- types
+ VSNORMAL
;
1325 subtype
= c
== '#' ? VSTRIMLEFT
:
1335 newsyn
= BASESYNTAX
;
1339 if (subtype
== VSLENGTH
&& c
!= '}')
1345 if (newsyn
== ARISYNTAX
)
1348 if ((newsyn
!= synstack
->syntax
|| synstack
->innerdq
) &&
1349 subtype
!= VSNORMAL
) {
1350 synstack_push(&synstack
,
1352 alloca(sizeof(*synstack
)),
1355 synstack
->varpushed
++;
1356 synstack
->dblquote
= newsyn
!= BASESYNTAX
;
1359 if (subtype
!= VSNORMAL
) {
1360 synstack
->varnest
++;
1361 if (synstack
->dblquote
)
1362 synstack
->dqvarnest
++;
1365 *((char *)stackblock() + typeloc
) = subtype
| VSBIT
;
1369 goto parsesub_return
;
1374 * Called to parse command substitutions. Newstyle is set if the command
1375 * is enclosed inside $(...); nlpp is a pointer to the head of the linked
1376 * list of commands (passed by reference), and savelen is the number of
1377 * characters on the top of the stack which must be preserved.
1381 int uninitialized_var(saveprompt
);
1382 struct heredoc
*saveheredoclist
;
1383 struct nodelist
**nlpp
;
1391 STADJUST(oldstyle
- 1, out
);
1395 savelen
= out
- (char *)stackblock();
1396 grabstackblock(savelen
);
1398 /* We must read until the closing backquote, giving special
1399 treatment to some slashes, and then push the string and
1400 reread it as input, interpreting it normally. */
1404 STARTSTACKSTR(pout
);
1409 switch (pc
= pgetc_eatbnl()) {
1415 if (pc
!= '\\' && pc
!= '`' && pc
!= '$'
1416 && (!synstack
->dblquote
|| pc
!= '"'))
1421 synerror("EOF in backquote substitution");
1434 psavelen
= pout
- (char *)stackblock();
1435 pstr
= grabstackstr(pout
);
1436 setinputstring(pstr
);
1440 nlpp
= &(*nlpp
)->next
;
1441 *nlpp
= (struct nodelist
*)stalloc(sizeof (struct nodelist
));
1442 (*nlpp
)->next
= NULL
;
1444 saveheredoclist
= heredoclist
;
1448 saveprompt
= doprompt
;
1455 doprompt
= saveprompt
;
1457 if (readtoken() != TRP
)
1459 setinputstring(nullstr
);
1463 heredoclist
= saveheredoclist
;
1466 /* Start reading from old file again. */
1469 out
= stnputs(str
, savelen
, stackblock());
1472 /* Ignore any pushed back tokens left from the backquote
1477 pstr
[psavelen
- 1] = '`';
1478 out
= stnputs(pstr
, psavelen
, out
);
1480 goto parsebackq_oldreturn
;
1483 out
= commandtextcont(n
, out
);
1486 goto parsebackq_newreturn
;
1491 * Parse an arithmetic expansion (indicate start of one and set state)
1495 synstack_push(&synstack
,
1496 synstack
->prev
?: alloca(sizeof(*synstack
)),
1498 synstack
->dblquote
= 1;
1505 goto parsearith_return
;
1508 } /* end of readtoken */
1518 * Return of a legal variable name (a letter or underscore followed by zero or
1519 * more letters, underscores, and digits).
1523 endofname(const char *name
)
1531 if (! is_in_name(*p
))
1539 * Called when an unexpected token is read during the parse. The argument
1540 * is the token that is expected, or -1 if more than one type of token can
1541 * occur at this point.
1545 synexpect(int token
)
1550 fmtstr(msg
, 64, "%s unexpected (expecting %s)",
1551 tokname
[lasttoken
], tokname
[token
]);
1553 fmtstr(msg
, 64, "%s unexpected", tokname
[lasttoken
]);
1561 synerror(const char *msg
)
1564 sh_error("Syntax error: %s", msg
);
1569 setprompt(int which
)
1571 struct stackmark smark
;
1575 whichprompt
= which
;
1583 pushstackmark(&smark
, stackblocksize());
1584 out2str(getprompt(NULL
));
1585 popstackmark(&smark
);
1590 expandstr(const char *ps
)
1592 struct parsefile
*file_stop
;
1593 struct jmploc
*volatile savehandler
;
1594 struct heredoc
*saveheredoclist
;
1597 struct jmploc jmploc
;
1601 file_stop
= parsefile
;
1603 /* XXX Fix (char *) cast. */
1604 setinputstring((char *)ps
);
1606 saveheredoclist
= heredoclist
;
1608 saveprompt
= doprompt
;
1611 savehandler
= handler
;
1612 if (unlikely(err
= setjmp(jmploc
.loc
)))
1616 readtoken1(pgetc_eatbnl(), DQSYNTAX
, FAKEEOFMARK
, 0);
1620 n
.narg
.text
= wordtext
;
1621 n
.narg
.backquote
= backquotelist
;
1623 expandarg(&n
, NULL
, EXP_QUOTED
);
1624 result
= stackblock();
1627 restore_handler_expandarg(savehandler
, err
);
1629 doprompt
= saveprompt
;
1630 unwindfiles(file_stop
);
1631 heredoclist
= saveheredoclist
;
1637 * called by editline -- any expansions to the prompt
1638 * should be added here.
1641 getprompt(void *unused
)
1645 switch (whichprompt
) {
1648 return "<internal prompt error>";
1660 return expandstr(prompt
);
1664 findkwd(const char *s
)
1667 s
, parsekwd
, sizeof(parsekwd
) / sizeof(const char *)