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 heredoc
*heredoclist
; /* list of here documents to read */
86 int doprompt
; /* if set, prompt the user */
87 int needprompt
; /* true if interactive and at start of line */
88 int lasttoken
; /* last token read */
89 int tokpushback
; /* last token pushed back */
90 char *wordtext
; /* text of last word returned by readtoken */
92 struct nodelist
*backquotelist
;
93 union node
*redirnode
;
94 struct heredoc
*heredoc
;
95 int quoteflag
; /* set if (part of) last token was quoted */
98 STATIC
union node
*list(int);
99 STATIC
union node
*andor(void);
100 STATIC
union node
*pipeline(void);
101 STATIC
union node
*command(void);
102 STATIC
union node
*simplecmd(void);
103 STATIC
union node
*makename(void);
104 STATIC
void parsefname(void);
105 STATIC
void parseheredoc(void);
106 STATIC
int peektoken(void);
107 STATIC
int readtoken(void);
108 STATIC
int xxreadtoken(void);
109 STATIC
int readtoken1(int, char const *, char *, int);
110 STATIC
void synexpect(int) __attribute__((__noreturn__
));
111 STATIC
void synerror(const char *) __attribute__((__noreturn__
));
112 STATIC
void setprompt(int);
116 isassignment(const char *p
)
118 const char *q
= endofname(p
);
124 static inline int realeofmark(const char *eofmark
)
126 return eofmark
&& eofmark
!= FAKEEOFMARK
;
131 * Read and parse a command. Returns NEOF on end of file. (NULL is a
132 * valid parse tree indicating a blank line.)
136 parsecmd(int interact
)
152 union node
*n1
, *n2
, *n3
;
157 switch (peektoken()) {
165 if (!n1
&& (nlflag
& 1))
171 checkkwd
= CHKNL
| CHKKWD
| CHKALIAS
;
172 if (nlflag
== 2 && tokendlist
[peektoken()])
178 if (tok
== TBACKGND
) {
179 if (n2
->type
== NPIPE
) {
180 n2
->npipe
.backgnd
= 1;
182 if (n2
->type
!= NREDIR
) {
183 n3
= stalloc(sizeof(struct nredir
));
185 n3
->nredir
.redirect
= NULL
;
195 n3
= (union node
*)stalloc(sizeof (struct nbinary
));
197 n3
->nbinary
.ch1
= n1
;
198 n3
->nbinary
.ch2
= n2
;
223 union node
*n1
, *n2
, *n3
;
228 if ((t
= readtoken()) == TAND
) {
230 } else if (t
== TOR
) {
236 checkkwd
= CHKNL
| CHKKWD
| CHKALIAS
;
238 n3
= (union node
*)stalloc(sizeof (struct nbinary
));
240 n3
->nbinary
.ch1
= n1
;
241 n3
->nbinary
.ch2
= n2
;
251 union node
*n1
, *n2
, *pipenode
;
252 struct nodelist
*lp
, *prev
;
256 TRACE(("pipeline: entered\n"));
257 if (readtoken() == TNOT
) {
259 checkkwd
= CHKKWD
| CHKALIAS
;
263 if (readtoken() == TPIPE
) {
264 pipenode
= (union node
*)stalloc(sizeof (struct npipe
));
265 pipenode
->type
= NPIPE
;
266 pipenode
->npipe
.backgnd
= 0;
267 lp
= (struct nodelist
*)stalloc(sizeof (struct nodelist
));
268 pipenode
->npipe
.cmdlist
= lp
;
272 lp
= (struct nodelist
*)stalloc(sizeof (struct nodelist
));
273 checkkwd
= CHKNL
| CHKKWD
| CHKALIAS
;
276 } while (readtoken() == TPIPE
);
282 n2
= (union node
*)stalloc(sizeof (struct nnot
));
296 union node
*ap
, **app
;
297 union node
*cp
, **cpp
;
298 union node
*redir
, **rpp
;
308 switch (readtoken()) {
313 n1
= (union node
*)stalloc(sizeof (struct nif
));
315 n1
->nif
.test
= list(0);
316 if (readtoken() != TTHEN
)
318 n1
->nif
.ifpart
= list(0);
320 while (readtoken() == TELIF
) {
321 n2
->nif
.elsepart
= (union node
*)stalloc(sizeof (struct nif
));
322 n2
= n2
->nif
.elsepart
;
324 n2
->nif
.test
= list(0);
325 if (readtoken() != TTHEN
)
327 n2
->nif
.ifpart
= list(0);
329 if (lasttoken
== TELSE
)
330 n2
->nif
.elsepart
= list(0);
332 n2
->nif
.elsepart
= NULL
;
340 n1
= (union node
*)stalloc(sizeof (struct nbinary
));
341 n1
->type
= (lasttoken
== TWHILE
)? NWHILE
: NUNTIL
;
342 n1
->nbinary
.ch1
= list(0);
343 if ((got
=readtoken()) != TDO
) {
344 TRACE(("expecting DO got %s %s\n", tokname
[got
], got
== TWORD
? wordtext
: ""));
347 n1
->nbinary
.ch2
= list(0);
352 if (readtoken() != TWORD
|| quoteflag
|| ! goodname(wordtext
))
353 synerror("Bad for loop variable");
354 n1
= (union node
*)stalloc(sizeof (struct nfor
));
356 n1
->nfor
.linno
= savelinno
;
357 n1
->nfor
.var
= wordtext
;
358 checkkwd
= CHKNL
| CHKKWD
| CHKALIAS
;
359 if (readtoken() == TIN
) {
361 while (readtoken() == TWORD
) {
362 n2
= (union node
*)stalloc(sizeof (struct narg
));
364 n2
->narg
.text
= wordtext
;
365 n2
->narg
.backquote
= backquotelist
;
367 app
= &n2
->narg
.next
;
371 if (lasttoken
!= TNL
&& lasttoken
!= TSEMI
)
374 n2
= (union node
*)stalloc(sizeof (struct narg
));
376 n2
->narg
.text
= (char *)dolatstr
;
377 n2
->narg
.backquote
= NULL
;
378 n2
->narg
.next
= NULL
;
381 * Newline or semicolon here is optional (but note
382 * that the original Bourne shell only allowed NL).
384 if (lasttoken
!= TSEMI
)
387 checkkwd
= CHKNL
| CHKKWD
| CHKALIAS
;
388 if (readtoken() != TDO
)
390 n1
->nfor
.body
= list(0);
394 n1
= (union node
*)stalloc(sizeof (struct ncase
));
396 n1
->ncase
.linno
= savelinno
;
397 if (readtoken() != TWORD
)
399 n1
->ncase
.expr
= n2
= (union node
*)stalloc(sizeof (struct narg
));
401 n2
->narg
.text
= wordtext
;
402 n2
->narg
.backquote
= backquotelist
;
403 n2
->narg
.next
= NULL
;
404 checkkwd
= CHKNL
| CHKKWD
| CHKALIAS
;
405 if (readtoken() != TIN
)
407 cpp
= &n1
->ncase
.cases
;
409 checkkwd
= CHKNL
| CHKKWD
;
412 if (lasttoken
== TLP
)
414 *cpp
= cp
= (union node
*)stalloc(sizeof (struct nclist
));
416 app
= &cp
->nclist
.pattern
;
418 *app
= ap
= (union node
*)stalloc(sizeof (struct narg
));
420 ap
->narg
.text
= wordtext
;
421 ap
->narg
.backquote
= backquotelist
;
422 if (readtoken() != TPIPE
)
424 app
= &ap
->narg
.next
;
427 ap
->narg
.next
= NULL
;
428 if (lasttoken
!= TRP
)
430 cp
->nclist
.body
= list(2);
432 cpp
= &cp
->nclist
.next
;
434 checkkwd
= CHKNL
| CHKKWD
;
435 if ((t
= readtoken()) != TESAC
) {
445 n1
= (union node
*)stalloc(sizeof (struct nredir
));
446 n1
->type
= NSUBSHELL
;
447 n1
->nredir
.linno
= savelinno
;
448 n1
->nredir
.n
= list(0);
449 n1
->nredir
.redirect
= NULL
;
462 if (readtoken() != t
)
466 /* Now check for redirection which may follow command */
467 checkkwd
= CHKKWD
| CHKALIAS
;
469 while (readtoken() == TREDIR
) {
470 *rpp
= n2
= redirnode
;
471 rpp
= &n2
->nfile
.next
;
477 if (n1
->type
!= NSUBSHELL
) {
478 n2
= (union node
*)stalloc(sizeof (struct nredir
));
480 n2
->nredir
.linno
= savelinno
;
484 n1
->nredir
.redirect
= redir
;
493 union node
*args
, **app
;
494 union node
*n
= NULL
;
495 union node
*vars
, **vpp
;
496 union node
**rpp
, *redir
;
507 savecheckkwd
= CHKALIAS
;
510 checkkwd
= savecheckkwd
;
511 switch (readtoken()) {
513 n
= (union node
*)stalloc(sizeof (struct narg
));
515 n
->narg
.text
= wordtext
;
516 n
->narg
.backquote
= backquotelist
;
517 if (savecheckkwd
&& isassignment(wordtext
)) {
527 *rpp
= n
= redirnode
;
528 rpp
= &n
->nfile
.next
;
529 parsefname(); /* read name of redirection file */
533 args
&& app
== &args
->narg
.next
&&
536 struct builtincmd
*bcmd
;
539 /* We have a function */
540 if (readtoken() != TRP
)
545 (bcmd
= find_builtin(name
)) &&
546 bcmd
->flags
& BUILTIN_SPECIAL
549 synerror("Bad function name");
551 checkkwd
= CHKNL
| CHKKWD
| CHKALIAS
;
552 n
->ndefun
.text
= n
->narg
.text
;
553 n
->ndefun
.linno
= plinno
;
554 n
->ndefun
.body
= command();
567 n
= (union node
*)stalloc(sizeof (struct ncmd
));
569 n
->ncmd
.linno
= savelinno
;
571 n
->ncmd
.assign
= vars
;
572 n
->ncmd
.redirect
= redir
;
581 n
= (union node
*)stalloc(sizeof (struct narg
));
584 n
->narg
.text
= wordtext
;
585 n
->narg
.backquote
= backquotelist
;
589 void fixredir(union node
*n
, const char *text
, int err
)
591 TRACE(("Fix redir %s %d\n", text
, err
));
593 n
->ndup
.vname
= NULL
;
595 if (is_digit(text
[0]) && text
[1] == '\0')
596 n
->ndup
.dupfd
= digit_val(text
[0]);
597 else if (text
[0] == '-' && text
[1] == '\0')
602 synerror("Bad fd number");
604 n
->ndup
.vname
= makename();
612 union node
*n
= redirnode
;
614 if (n
->type
== NHERE
)
615 checkkwd
= CHKEOFMARK
;
616 if (readtoken() != TWORD
)
618 if (n
->type
== NHERE
) {
619 struct heredoc
*here
= heredoc
;
624 TRACE(("Here document %d\n", n
->type
));
626 here
->eofmark
= wordtext
;
628 if (heredoclist
== NULL
)
631 for (p
= heredoclist
; p
->next
; p
= p
->next
);
634 } else if (n
->type
== NTOFD
|| n
->type
== NFROMFD
) {
635 fixredir(n
, wordtext
, 0);
637 n
->nfile
.fname
= makename();
643 * Input any here documents.
649 struct heredoc
*here
;
659 readtoken1(pgetc(), here
->here
->type
== NHERE
? SQSYNTAX
: DQSYNTAX
,
660 here
->eofmark
, here
->striptabs
);
661 n
= (union node
*)stalloc(sizeof (struct narg
));
664 n
->narg
.text
= wordtext
;
665 n
->narg
.backquote
= backquotelist
;
666 here
->here
->nhere
.doc
= n
;
687 int alreadyseen
= tokpushback
;
703 if (t
!= TWORD
|| quoteflag
) {
711 const char *const *pp
;
713 if ((pp
= findkwd(wordtext
))) {
714 lasttoken
= t
= pp
- parsekwd
+ KWDOFFSET
;
715 TRACE(("keyword %s recognized\n", tokname
[t
]));
720 if (checkkwd
& CHKALIAS
) {
722 if ((ap
= lookupalias(wordtext
, 1)) != NULL
) {
724 pushstring(ap
->val
, ap
);
733 TRACE(("token %s %s\n", tokname
[t
], t
== TWORD
? wordtext
: ""));
735 TRACE(("reread token %s %s\n", tokname
[t
], t
== TWORD
? wordtext
: ""));
740 static void nlprompt(void)
747 static void nlnoprompt(void)
750 needprompt
= doprompt
;
755 * Read the next input token.
756 * If the token is a word, we set backquotelist to the list of cmds in
757 * backquotes. We set quoteflag to true if any part of the word was
759 * If the token is TREDIR, then we set redirnode to a structure containing
762 * [Change comment: here documents and internal procedures]
763 * [Readtoken shouldn't have any arguments. Perhaps we should make the
764 * word parsing code into a separate routine. In this case, readtoken
765 * doesn't need to have any internal procedures, but parseword does.
766 * We could also make parseoperator in essence the main routine, and
767 * have parseword (readtoken1?) handle both words and redirection.]
770 #define RETURN(token) return lasttoken = token
784 for (;;) { /* until token or start of word found */
791 while ((c
= pgetc()) != '\n' && c
!= PEOF
);
795 if (pgetc() == '\n') {
830 return readtoken1(c
, BASESYNTAX
, (char *)NULL
, 0);
834 static int pgetc_eatbnl(void)
838 while ((c
= pgetc()) == '\\') {
839 if (pgetc() != '\n') {
853 * If eofmark is NULL, read a word or a redirection symbol. If eofmark
854 * is not NULL, read a here document. In the latter case, eofmark is the
855 * word which marks the end of the document and striptabs is true if
856 * leading tabs should be stripped from the document. The argument firstc
857 * is the first character of the input token or document.
859 * Because C does not have internal subroutines, I have simulated them
860 * using goto's to implement the subroutine linkage. The following macros
861 * will run code that appears at the end of readtoken1.
864 #define CHECKEND() {goto checkend; checkend_return:;}
865 #define PARSEREDIR() {goto parseredir; parseredir_return:;}
866 #define PARSESUB() {goto parsesub; parsesub_return:;}
867 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
868 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
869 #define PARSEARITH() {goto parsearith; parsearith_return:;}
872 readtoken1(int firstc
, char const *syntax
, char *eofmark
, int striptabs
)
877 struct nodelist
*bqlist
;
880 int varnest
; /* levels of variables expansion */
881 int arinest
; /* levels of arithmetic expansion */
882 int parenlevel
; /* levels of parens in arithmetic */
883 int dqvarnest
; /* levels of variables expansion within double quotes */
885 /* syntax before arithmetic */
886 char const *uninitialized_var(prevsyntax
);
889 if (syntax
== DQSYNTAX
)
899 loop
: { /* for each line, until end of word */
901 if (c
== '\034' && doprompt
902 && attyset() && ! equal(termval(), "emacs")) {
904 if (syntax
== BASESYNTAX
)
910 CHECKEND(); /* set c to PEOF if at end of here document */
911 for (;;) { /* until end of line or end of word */
912 CHECKSTRSPACE(4, out
); /* permit 4 calls to USTPUTC */
915 if (syntax
== BASESYNTAX
)
916 goto endword
; /* exit outer loop */
920 goto loop
; /* continue outer loop */
925 if (eofmark
== NULL
|| dblquote
)
926 USTPUTC(CTLESC
, out
);
933 USTPUTC(CTLESC
, out
);
936 } else if (c
== '\n') {
941 c
!= '\\' && c
!= '`' &&
949 USTPUTC(CTLESC
, out
);
957 if (eofmark
== NULL
) {
958 USTPUTC(CTLQUOTEMARK
, out
);
966 if (eofmark
&& !varnest
)
969 if (dqvarnest
== 0) {
978 PARSESUB(); /* parse substitution */
980 case CENDVAR
: /* '}' */
986 USTPUTC(CTLENDVAR
, out
);
991 case CLP
: /* '(' in arithmetic */
995 case CRP
: /* ')' in arithmetic */
996 if (parenlevel
> 0) {
1000 if (pgetc() == ')') {
1001 USTPUTC(CTLENDARI
, out
);
1003 syntax
= prevsyntax
;
1007 * (don't 2nd guess - no error)
1014 case CBQUOTE
: /* '`' */
1018 goto endword
; /* exit outer loop */
1023 goto endword
; /* exit outer loop */
1032 if (syntax
== ARISYNTAX
)
1033 synerror("Missing '))'");
1034 if (syntax
!= BASESYNTAX
&& eofmark
== NULL
)
1035 synerror("Unterminated quoted string");
1038 synerror("Missing '}'");
1041 len
= out
- (char *)stackblock();
1043 if (eofmark
== NULL
) {
1044 if ((c
== '>' || c
== '<')
1047 && (*out
== '\0' || is_digit(*out
))) {
1049 return lasttoken
= TREDIR
;
1055 backquotelist
= bqlist
;
1056 grabstackblock(len
);
1058 return lasttoken
= TWORD
;
1059 /* end of readtoken routine */
1064 * Check to see whether we are at the end of the here document. When this
1065 * is called, c is set to the first character of the next input line. If
1066 * we are at the end of the here document, this routine sets the c to PEOF.
1070 if (realeofmark(eofmark
)) {
1083 markloc
= out
- (char *)stackblock();
1084 for (p
= eofmark
; STPUTC(c
, out
), *p
; p
++) {
1091 if (c
== '\n' || c
== PEOF
) {
1098 p
= (char *)stackblock() + markloc
+ 1;
1108 str
= alloca(len
+ 1);
1109 *(char *)mempcpy(str
, p
, len
) = 0;
1111 pushstring(str
, NULL
);
1116 STADJUST((char *)stackblock() + markloc
- out
, out
);
1118 goto checkend_return
;
1123 * Parse a redirection operator. The variable "out" points to a string
1124 * specifying the fd to be redirected. The variable "c" contains the
1125 * first character of the redirection operator.
1132 np
= (union node
*)stalloc(sizeof (struct nfile
));
1139 np
->type
= NCLOBBER
;
1146 } else { /* c == '<' */
1148 switch (c
= pgetc()) {
1150 if (sizeof (struct nfile
) != sizeof (struct nhere
)) {
1151 np
= (union node
*)stalloc(sizeof (struct nhere
));
1155 heredoc
= (struct heredoc
*)stalloc(sizeof (struct heredoc
));
1157 if ((c
= pgetc()) == '-') {
1158 heredoc
->striptabs
= 1;
1160 heredoc
->striptabs
= 0;
1180 np
->nfile
.fd
= digit_val(fd
);
1182 goto parseredir_return
;
1187 * Parse a substitution. At this point, we have read the dollar sign
1195 static const char types
[] = "}-+?=";
1199 (checkkwd
& CHKEOFMARK
) ||
1201 (c
!= '(' && c
!= '{' && !is_name(c
) && !is_special(c
))
1205 } else if (c
== '(') { /* $(command) or $((arith)) */
1206 if (pgetc_eatbnl() == '(') {
1213 USTPUTC(CTLVAR
, out
);
1214 typeloc
= out
- (char *)stackblock();
1217 if (likely(c
== '{')) {
1226 } while (is_in_name(c
));
1227 } else if (is_digit(c
)) {
1231 } while (is_digit(c
));
1237 if (!subtype
&& cc
== '#') {
1240 if (c
== '_' || isalnum(c
))
1245 if (cc
== '}' || c
!= '}') {
1253 if (!is_special(cc
)) {
1254 if (subtype
== VSLENGTH
)
1269 p
= strchr(types
, c
);
1272 subtype
|= p
- types
+ VSNORMAL
;
1278 subtype
= c
== '#' ? VSTRIMLEFT
:
1292 *((char *)stackblock() + typeloc
) = subtype
;
1293 if (subtype
!= VSNORMAL
) {
1300 goto parsesub_return
;
1305 * Called to parse command substitutions. Newstyle is set if the command
1306 * is enclosed inside $(...); nlpp is a pointer to the head of the linked
1307 * list of commands (passed by reference), and savelen is the number of
1308 * characters on the top of the stack which must be preserved.
1312 struct nodelist
**nlpp
;
1316 int uninitialized_var(saveprompt
);
1319 savelen
= out
- (char *)stackblock();
1321 str
= alloca(savelen
);
1322 memcpy(str
, stackblock(), savelen
);
1325 /* We must read until the closing backquote, giving special
1326 treatment to some slashes, and then push the string and
1327 reread it as input, interpreting it normally. */
1334 STARTSTACKSTR(pout
);
1339 switch (pc
= pgetc()) {
1344 if ((pc
= pgetc()) == '\n') {
1347 * If eating a newline, avoid putting
1348 * the newline into the new character
1349 * stream (via the STPUTC after the
1354 if (pc
!= '\\' && pc
!= '`' && pc
!= '$'
1355 && (!dblquote
|| pc
!= '"'))
1364 synerror("EOF in backquote substitution");
1377 psavelen
= pout
- (char *)stackblock();
1379 pstr
= grabstackstr(pout
);
1380 setinputstring(pstr
);
1385 nlpp
= &(*nlpp
)->next
;
1386 *nlpp
= (struct nodelist
*)stalloc(sizeof (struct nodelist
));
1387 (*nlpp
)->next
= NULL
;
1390 saveprompt
= doprompt
;
1397 doprompt
= saveprompt
;
1399 if (readtoken() != TRP
)
1406 * Start reading from old file again, ignoring any pushed back
1407 * tokens left from the backquote parsing
1412 while (stackblocksize() <= savelen
)
1416 memcpy(out
, str
, savelen
);
1417 STADJUST(savelen
, out
);
1419 USTPUTC(CTLBACKQ
, out
);
1421 goto parsebackq_oldreturn
;
1423 goto parsebackq_newreturn
;
1427 * Parse an arithmetic expansion (indicate start of one and set state)
1431 if (++arinest
== 1) {
1432 prevsyntax
= syntax
;
1435 USTPUTC(CTLARI
, out
);
1436 goto parsearith_return
;
1439 } /* end of readtoken */
1449 * Return of a legal variable name (a letter or underscore followed by zero or
1450 * more letters, underscores, and digits).
1454 endofname(const char *name
)
1462 if (! is_in_name(*p
))
1470 * Called when an unexpected token is read during the parse. The argument
1471 * is the token that is expected, or -1 if more than one type of token can
1472 * occur at this point.
1476 synexpect(int token
)
1481 fmtstr(msg
, 64, "%s unexpected (expecting %s)",
1482 tokname
[lasttoken
], tokname
[token
]);
1484 fmtstr(msg
, 64, "%s unexpected", tokname
[lasttoken
]);
1492 synerror(const char *msg
)
1495 sh_error("Syntax error: %s", msg
);
1500 setprompt(int which
)
1502 struct stackmark smark
;
1506 whichprompt
= which
;
1514 pushstackmark(&smark
, stackblocksize());
1515 out2str(getprompt(NULL
));
1516 popstackmark(&smark
);
1521 expandstr(const char *ps
)
1526 /* XXX Fix (char *) cast. */
1527 setinputstring((char *)ps
);
1529 saveprompt
= doprompt
;
1532 readtoken1(pgetc(), DQSYNTAX
, FAKEEOFMARK
, 0);
1534 doprompt
= saveprompt
;
1540 n
.narg
.text
= wordtext
;
1541 n
.narg
.backquote
= backquotelist
;
1543 expandarg(&n
, NULL
, EXP_QUOTED
);
1544 return stackblock();
1548 * called by editline -- any expansions to the prompt
1549 * should be added here.
1552 getprompt(void *unused
)
1556 switch (whichprompt
) {
1559 return "<internal prompt error>";
1571 return expandstr(prompt
);
1575 findkwd(const char *s
)
1578 s
, parsekwd
, sizeof(parsekwd
) / sizeof(const char *)