summaryrefslogtreecommitdiffstats
path: root/bin/sh/parser.c
diff options
context:
space:
mode:
authorpeter <peter@FreeBSD.org>1996-09-01 10:22:36 +0000
committerpeter <peter@FreeBSD.org>1996-09-01 10:22:36 +0000
commit5195be912eb257c05a0c97e561e72f01af2583ff (patch)
treee47ab3981b495c675a987dd1e943d1f4c823f314 /bin/sh/parser.c
parent2fc7d7d1fa299368ccdddede67b31695266698bd (diff)
downloadFreeBSD-src-5195be912eb257c05a0c97e561e72f01af2583ff.zip
FreeBSD-src-5195be912eb257c05a0c97e561e72f01af2583ff.tar.gz
Merge of 4.4-Lite2 sh source, plus some gcc -Wall cleaning. This is a
merge of parallel duplicate work by Steve Price and myself. :-] There are some changes to the build that are my fault... mkinit.c was trying (poorly) to duplicate some of the work that make(1) is designed to do. The Makefile hackery is my fault too, the depend list was incomplete because of some explicit OBJS+= entries, so mkdep wasn't picking up their source file #includes. This closes a pile of /bin/sh PR's, but not all of them.. Submitted by: Steve Price <steve@bonsai.hiwaay.net>, peter
Diffstat (limited to 'bin/sh/parser.c')
-rw-r--r--bin/sh/parser.c247
1 files changed, 166 insertions, 81 deletions
diff --git a/bin/sh/parser.c b/bin/sh/parser.c
index ef9c40c..64a0cd0 100644
--- a/bin/sh/parser.c
+++ b/bin/sh/parser.c
@@ -33,13 +33,15 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: parser.c,v 1.10 1995/12/10 17:59:23 joerg Exp $
+ * $Id: parser.c,v 1.11 1996/02/03 13:27:55 joerg Exp $
*/
#ifndef lint
-static char sccsid[] = "@(#)parser.c 8.1 (Berkeley) 5/31/93";
+static char sccsid[] = "@(#)parser.c 8.7 (Berkeley) 5/16/95";
#endif /* not lint */
+#include <stdlib.h>
+
#include "shell.h"
#include "parser.h"
#include "nodes.h"
@@ -54,8 +56,10 @@ static char sccsid[] = "@(#)parser.c 8.1 (Berkeley) 5/31/93";
#include "memalloc.h"
#include "mystring.h"
#include "alias.h"
+#include "show.h"
+#ifndef NO_HISTORY
#include "myhistedit.h"
-
+#endif
/*
* Shell command parser.
@@ -64,7 +68,7 @@ static char sccsid[] = "@(#)parser.c 8.1 (Berkeley) 5/31/93";
#define EOFMARKLEN 79
/* values returned by readtoken */
-#include "token.def"
+#include "token.h"
@@ -104,15 +108,18 @@ STATIC union node *andor __P((void));
STATIC union node *pipeline __P((void));
STATIC union node *command __P((void));
STATIC union node *simplecmd __P((union node **, union node *));
+STATIC union node *makename __P((void));
STATIC void parsefname __P((void));
STATIC void parseheredoc __P((void));
+STATIC int peektoken __P((void));
STATIC int readtoken __P((void));
+STATIC int xxreadtoken __P((void));
STATIC int readtoken1 __P((int, char const *, char *, int));
-STATIC void attyline __P((void));
STATIC int noexpand __P((char *));
STATIC void synexpect __P((int));
STATIC void synerror __P((char *));
-STATIC void setprompt __P((int));
+STATIC void setprompt __P((int));
+
/*
* Read and parse a command. Returns NEOF on end of file. (NULL is a
@@ -120,7 +127,9 @@ STATIC void setprompt __P((int));
*/
union node *
-parsecmd(interact) {
+parsecmd(interact)
+ int interact;
+{
int t;
doprompt = interact;
@@ -140,31 +149,58 @@ parsecmd(interact) {
STATIC union node *
-list(nlflag) {
+list(nlflag)
+ int nlflag;
+{
union node *n1, *n2, *n3;
+ int tok;
checkkwd = 2;
if (nlflag == 0 && tokendlist[peektoken()])
return NULL;
- n1 = andor();
+ n1 = NULL;
for (;;) {
- switch (readtoken()) {
- case TBACKGND:
- case TNL:
- parseheredoc();
- if (nlflag)
- return n1;
- /* fall through */
- case TSEMI:
- checkkwd = 2;
- if (tokendlist[peektoken()])
- return n1;
- n2 = andor();
+ n2 = andor();
+ tok = readtoken();
+ if (tok == TBACKGND) {
+ if (n2->type == NCMD || n2->type == NPIPE) {
+ n2->ncmd.backgnd = 1;
+ } else if (n2->type == NREDIR) {
+ n2->type = NBACKGND;
+ } else {
+ n3 = (union node *)stalloc(sizeof (struct nredir));
+ n3->type = NBACKGND;
+ n3->nredir.n = n2;
+ n3->nredir.redirect = NULL;
+ n2 = n3;
+ }
+ }
+ if (n1 == NULL) {
+ n1 = n2;
+ }
+ else {
n3 = (union node *)stalloc(sizeof (struct nbinary));
n3->type = NSEMI;
n3->nbinary.ch1 = n1;
n3->nbinary.ch2 = n2;
n1 = n3;
+ }
+ switch (tok) {
+ case TBACKGND:
+ case TSEMI:
+ tok = readtoken();
+ /* fall through */
+ case TNL:
+ if (tok == TNL) {
+ parseheredoc();
+ if (nlflag)
+ return n1;
+ } else {
+ tokpushback++;
+ }
+ checkkwd = 2;
+ if (tokendlist[peektoken()])
+ return n1;
break;
case TEOF:
if (heredoclist)
@@ -195,19 +231,6 @@ andor() {
} else if (t == TOR) {
t = NOR;
} else {
- if (t == TBACKGND) {
- if (n1->type == NCMD || n1->type == NPIPE) {
- n1->ncmd.backgnd = 1;
- } else if (n1->type == NREDIR) {
- n1->type = NBACKGND;
- } else {
- n3 = (union node *)stalloc(sizeof (struct nredir));
- n3->type = NBACKGND;
- n3->nredir.n = n1;
- n3->nredir.redirect = NULL;
- n1 = n3;
- }
- }
tokpushback++;
return n1;
}
@@ -272,7 +295,8 @@ command() {
int t;
checkkwd = 2;
- redir = 0;
+ redir = NULL;
+ n1 = NULL;
rpp = &redir;
/* Check for redirection which may precede command */
while (readtoken() == TREDIR) {
@@ -438,13 +462,19 @@ TRACE(("expecting DO got %s %s\n", tokname[got], got == TWORD ? wordtext : ""));
checkkwd = 1;
break;
/* Handle an empty command like other simple commands. */
- case TAND:
- case TOR:
- case TNL:
case TSEMI:
- /* Handle EOF as an empty command, too */
+ /*
+ * An empty command before a ; doesn't make much sense, and
+ * should certainly be disallowed in the case of `if ;'.
+ */
+ if (!redir)
+ synexpect(-1);
+ case TAND: /* XXX merge query! */
+ case TOR: /* XXX merge query! */
+ case TNL:
case TEOF:
case TWORD:
+ case TRP:
tokpushback++;
return simplecmd(rpp, redir);
default:
@@ -478,7 +508,7 @@ simplecmd(rpp, redir)
{
union node *args, **app;
union node **orig_rpp = rpp;
- union node *n;
+ union node *n = NULL;
/* If we don't have any redirections already, then we must reset */
/* rpp to be the address of the local redir variable. */
@@ -533,6 +563,40 @@ simplecmd(rpp, redir)
return n;
}
+STATIC union node *
+makename() {
+ union node *n;
+
+ n = (union node *)stalloc(sizeof (struct narg));
+ n->type = NARG;
+ n->narg.next = NULL;
+ n->narg.text = wordtext;
+ n->narg.backquote = backquotelist;
+ return n;
+}
+
+void fixredir(n, text, err)
+ union node *n;
+ const char *text;
+ int err;
+ {
+ TRACE(("Fix redir %s %d\n", text, err));
+ if (!err)
+ n->ndup.vname = NULL;
+
+ if (is_digit(text[0]) && text[1] == '\0')
+ n->ndup.dupfd = digit_val(text[0]);
+ else if (text[0] == '-' && text[1] == '\0')
+ n->ndup.dupfd = -1;
+ else {
+
+ if (err)
+ synerror("Bad fd number");
+ else
+ n->ndup.vname = makename();
+ }
+}
+
STATIC void
parsefname() {
@@ -564,23 +628,9 @@ parsefname() {
p->next = here;
}
} else if (n->type == NTOFD || n->type == NFROMFD) {
- if (is_digit(wordtext[0]))
- n->ndup.dupfd = digit_val(wordtext[0]);
- else if (wordtext[0] == '-')
- n->ndup.dupfd = -1;
- else
- goto bad;
- if (wordtext[1] != '\0') {
-bad:
- synerror("Bad fd number");
- }
+ fixredir(n, wordtext, 0);
} else {
- n->nfile.fname = (union node *)stalloc(sizeof (struct narg));
- n = n->nfile.fname;
- n->type = NARG;
- n->narg.next = NULL;
- n->narg.text = wordtext;
- n->narg.backquote = backquotelist;
+ n->nfile.fname = makename();
}
}
@@ -650,17 +700,19 @@ readtoken() {
/*
* check for keywords and aliases
*/
- if (t == TWORD && !quoteflag) {
- register char * const *pp, *s;
+ if (t == TWORD && !quoteflag)
+ {
+ register char * const *pp;
for (pp = (char **)parsekwd; *pp; pp++) {
- if (**pp == *wordtext && equal(*pp, wordtext)) {
+ if (**pp == *wordtext && equal(*pp, wordtext))
+ {
lasttoken = t = pp - parsekwd + KWDOFFSET;
TRACE(("keyword %s recognized\n", tokname[t]));
goto out;
}
}
- if (ap = lookupalias(wordtext, 1)) {
+ if ((ap = lookupalias(wordtext, 1)) != NULL) {
pushstring(ap->val, strlen(ap->val), ap);
checkkwd = savecheckkwd;
goto top;
@@ -796,8 +848,8 @@ readtoken1(firstc, syntax, eofmark, striptabs)
char *eofmark;
int striptabs;
{
- register c = firstc;
- register char *out;
+ int c = firstc;
+ char *out;
int len;
char line[EOFMARKLEN + 1];
struct nodelist *bqlist;
@@ -808,6 +860,18 @@ readtoken1(firstc, syntax, eofmark, striptabs)
int parenlevel; /* levels of parens in arithmetic */
int oldstyle;
char const *prevsyntax; /* syntax before arithmetic */
+#if __GNUC__
+ /* Avoid longjmp clobbering */
+ (void) &out;
+ (void) &quotef;
+ (void) &dblquote;
+ (void) &varnest;
+ (void) &arinest;
+ (void) &parenlevel;
+ (void) &oldstyle;
+ (void) &prevsyntax;
+ (void) &syntax;
+#endif
startlinno = plinno;
dblquote = 0;
@@ -834,13 +898,6 @@ readtoken1(firstc, syntax, eofmark, striptabs)
CHECKEND(); /* set c to PEOF if at end of here document */
for (;;) { /* until end of line or end of word */
CHECKSTRSPACE(3, out); /* permit 3 calls to USTPUTC */
- if (parsebackquote && c == '\\') {
- c = pgetc(); /* XXX - compat with old /bin/sh */
- if (/*c != '\\' && */c != '`' && c != '$') {
- pungetc();
- c = '\\';
- }
- }
switch(syntax[c]) {
case CNL: /* '\n' */
if (syntax == BASESYNTAX)
@@ -1098,7 +1155,14 @@ parsesub: {
subtype = VSNORMAL;
if (c == '{') {
c = pgetc();
- subtype = 0;
+ if (c == '#') {
+ if ((c = pgetc()) == '}')
+ c = '#';
+ else
+ subtype = VSLENGTH;
+ }
+ else
+ subtype = 0;
}
if (is_name(c)) {
do {
@@ -1114,14 +1178,31 @@ badsub: synerror("Bad substitution");
STPUTC('=', out);
flags = 0;
if (subtype == 0) {
- if (c == ':') {
+ switch (c) {
+ case ':':
flags = VSNUL;
c = pgetc();
+ /*FALLTHROUGH*/
+ default:
+ p = strchr(types, c);
+ if (p == NULL)
+ goto badsub;
+ subtype = p - types + VSNORMAL;
+ break;
+ case '%':
+ case '#':
+ {
+ int cc = c;
+ subtype = c == '#' ? VSTRIMLEFT :
+ VSTRIMRIGHT;
+ c = pgetc();
+ if (c == cc)
+ subtype++;
+ else
+ pungetc();
+ break;
+ }
}
- p = strchr(types, c);
- if (p == NULL)
- goto badsub;
- subtype = p - types + VSNORMAL;
} else {
pungetc();
}
@@ -1164,7 +1245,7 @@ parsebackq: {
savelen = out - stackblock();
if (savelen > 0) {
str = ckmalloc(savelen);
- bcopy(stackblock(), str, savelen);
+ memcpy(str, stackblock(), savelen);
}
savehandler = handler;
handler = &jmploc;
@@ -1186,7 +1267,7 @@ parsebackq: {
}
if (c == '\\') {
c = pgetc ();
- if ( c != '\\' && c != '`' && c != '$'
+ if (c != '\\' && c != '`' && c != '$'
&& (!dblquote || c != '"'))
STPUTC('\\', out);
}
@@ -1196,9 +1277,9 @@ parsebackq: {
savelen = out - stackblock();
if (savelen > 0) {
str = ckmalloc(savelen);
- bcopy(stackblock(), str, savelen);
+ memcpy(str, stackblock(), savelen);
+ setinputstring(str, 1);
}
- setinputstring(str, 1);
}
nlpp = &bqlist;
while (*nlpp)
@@ -1217,7 +1298,7 @@ parsebackq: {
growstackblock();
STARTSTACKSTR(out);
if (str) {
- bcopy(str, out, savelen);
+ memcpy(out, str, savelen);
STADJUST(savelen, out);
INTOFF;
ckfree(str);
@@ -1318,7 +1399,9 @@ goodname(name)
*/
STATIC void
-synexpect(token) {
+synexpect(token)
+ int token;
+{
char msg[64];
if (token >= 0) {
@@ -1347,7 +1430,9 @@ setprompt(which)
{
whichprompt = which;
+#ifndef NO_HISTORY
if (!el)
+#endif
out2str(getprompt(NULL));
}
OpenPOWER on IntegriCloud