about summary refs log tree commit diff
path: root/Src/parse.c
diff options
context:
space:
mode:
Diffstat (limited to 'Src/parse.c')
-rw-r--r--Src/parse.c119
1 files changed, 84 insertions, 35 deletions
diff --git a/Src/parse.c b/Src/parse.c
index 94ac04922..8769baae4 100644
--- a/Src/parse.c
+++ b/Src/parse.c
@@ -309,7 +309,6 @@ parse_context_restore(const struct parse_stack *ps, int toplevel)
     incond = ps->incond;
     inredir = ps->inredir;
     incasepat = ps->incasepat;
-    incasepat = ps->incasepat;
     isnewlin = ps->isnewlin;
     infor = ps->infor;
     inrepeat_ = ps->inrepeat_;
@@ -595,7 +594,7 @@ par_event(int endtok)
     if (tok == ENDINPUT)
 	return 0;
     if (tok == endtok)
-	return 0;
+	return 1;
 
     p = ecadd(0);
 
@@ -1739,6 +1738,7 @@ par_simple(int *cmplx, int nr)
 {
     int oecused = ecused, isnull = 1, r, argc = 0, p, isfunc = 0, sr = 0;
     int c = *cmplx, nrediradd, assignments = 0, ppost = 0, is_typeset = 0;
+    char *hasalias = input_hasalias();
     wordcode postassigns = 0;
 
     r = ecused;
@@ -1810,6 +1810,8 @@ par_simple(int *cmplx, int nr)
 	} else
 	    break;
 	zshlex();
+	if (!hasalias)
+	    hasalias = input_hasalias();
     }
     if (tok == AMPER || tok == AMPERBANG)
 	YYERROR(oecused);
@@ -1834,12 +1836,14 @@ par_simple(int *cmplx, int nr)
 
 		if (*ptr == Outbrace && ptr > tokstr + 1)
 		{
-		    if (itype_end(tokstr+1, IIDENT, 0) >= ptr - 1)
+		    if (itype_end(tokstr+1, IIDENT, 0) >= ptr)
 		    {
 			char *toksave = tokstr;
 			char *idstring = dupstrpfx(tokstr+1, eptr-tokstr-1);
 			redir_var = 1;
 			zshlex();
+			if (!hasalias)
+			    hasalias = input_hasalias();
 
 			if (IS_REDIROP(tok) && tokfd == -1)
 			{
@@ -1875,6 +1879,8 @@ par_simple(int *cmplx, int nr)
 		    argc++;
 		}
 		zshlex();
+		if (!hasalias)
+		    hasalias = input_hasalias();
 	    }
 	} else if (IS_REDIROP(tok)) {
 	    *cmplx = c = 1;
@@ -1903,6 +1909,8 @@ par_simple(int *cmplx, int nr)
 	    ecstr(name);
 	    ecstr(str);
 	    zshlex();
+	    if (!hasalias)
+		hasalias = input_hasalias();
 	} else if (tok == ENVARRAY) {
 	    int n, parr;
 
@@ -1937,6 +1945,11 @@ par_simple(int *cmplx, int nr)
 	    /* Error if preceding assignments */
 	    if (assignments || postassigns)
 		YYERROR(oecused);
+	    if (hasalias && !isset(ALIASFUNCDEF) && argc &&
+		hasalias != input_hasalias()) {
+		zwarn("defining function based on alias `%s'", hasalias);
+		YYERROR(oecused);
+	    }
 
 	    *cmplx = c;
 	    lineno = 0;
@@ -2017,10 +2030,21 @@ par_simple(int *cmplx, int nr)
 		/* Unnamed function */
 		int parg = ecadd(0);
 		ecadd(0);
-		while (tok == STRING) {
-		    ecstr(tokstr);
-		    argc++;
-		    zshlex();
+		while (tok == STRING || IS_REDIROP(tok)) {
+		    if (tok == STRING)
+		    {
+			ecstr(tokstr);
+			argc++;
+			zshlex();
+		    } else {
+			*cmplx = c = 1;
+			nrediradd = par_redir(&r, NULL);
+			p += nrediradd;
+			if (ppost)
+			    ppost += nrediradd;
+			sr += nrediradd;
+			parg += nrediradd;
+		    }
 		}
 		if (argc > 0)
 		    *cmplx = 1;
@@ -2130,7 +2154,7 @@ par_redir(int *rp, char *idstring)
 	 * the definition of WC_REDIR_WORDS. */
 	ecispace(r, ncodes);
 	*rp = r + ncodes;
-	ecbuf[r] = WCB_REDIR(type);
+	ecbuf[r] = WCB_REDIR(type | REDIR_FROM_HEREDOC_MASK);
 	ecbuf[r + 1] = fd1;
 
 	/*
@@ -2304,6 +2328,19 @@ par_cond_1(void)
 }
 
 /*
+ * Return 1 if condition matches.  This also works for non-elided options.
+ *
+ * input is test string, may begin - or Dash.
+ * cond is condition following the -.
+ */
+static int check_cond(const char *input, const char *cond)
+{
+    if (!IS_DASH(input[0]))
+	return 0;
+    return !strcmp(input + 1, cond);
+}
+
+/*
  * cond_2	: BANG cond_2
 				| INPAR { SEPER } cond_2 { SEPER } OUTPAR
 				| STRING STRING STRING
@@ -2329,7 +2366,7 @@ par_cond_2(void)
 	    s1 = tokstr;
 	    condlex();
 	    /* ksh behavior: [ -t ] means [ -t 1 ]; bash disagrees */
-	    if (unset(POSIXBUILTINS) && !strcmp(s1, "-t"))
+	    if (unset(POSIXBUILTINS) && check_cond(s1, "t"))
 		return par_cond_double(s1, dupstring("1"));
 	    return par_cond_double(dupstring("-n"), s1);
 	}
@@ -2339,7 +2376,7 @@ par_cond_2(void)
 	    if (!strcmp(*testargs, "=")  ||
 		!strcmp(*testargs, "==") ||
 		!strcmp(*testargs, "!=") ||
-		(**testargs == '-' && get_cond_num(*testargs + 1) >= 0)) {
+		(IS_DASH(**testargs) && get_cond_num(*testargs + 1) >= 0)) {
 		s1 = tokstr;
 		condlex();
 		s2 = tokstr;
@@ -2361,8 +2398,8 @@ par_cond_2(void)
 	 * In "test" compatibility mode, "! -a ..." and "! -o ..."
 	 * are treated as "[string] [and] ..." and "[string] [or] ...".
 	 */
-	if (!(n_testargs > 1 &&
-	      (!strcmp(*testargs, "-a") || !strcmp(*testargs, "-o"))))
+	if (!(n_testargs > 1 && (check_cond(*testargs, "a") ||
+				 check_cond(*testargs, "o"))))
 	{
 	    condlex();
 	    ecadd(WCB_COND(COND_NOT, 0));
@@ -2384,9 +2421,9 @@ par_cond_2(void)
 	return r;
     }
     s1 = tokstr;
-    dble = (s1 && *s1 == '-'
+    dble = (s1 && IS_DASH(*s1)
 	    && (!n_testargs
-		|| strspn(s1+1, "abcdefghknoprstuwxzLONGS") == 1)
+		|| strspn(s1+1, "abcdefghknoprstuvwxzLONGS") == 1)
 	    && !s1[2]);
     if (tok != STRING) {
 	/* Check first argument for [[ STRING ]] re-interpretation */
@@ -2398,7 +2435,7 @@ par_cond_2(void)
 	    YYERROR(ecused);
     }
     condlex();
-    if (n_testargs == 2 && tok != STRING && tokstr && s1[0] == '-') {
+    if (n_testargs == 2 && tok != STRING && tokstr && IS_DASH(s1[0])) {
 	/*
 	 * Something like "test -z" followed by a token.
 	 * We'll turn the token into a string (we've also
@@ -2433,9 +2470,9 @@ par_cond_2(void)
 	} else
 	    YYERROR(ecused);
     }
-    s2 = tokstr;   
+    s2 = tokstr;
     if (!n_testargs)
-	dble = (s2 && *s2 == '-' && !s2[2]);
+	dble = (s2 && IS_DASH(*s2) && !s2[2]);
     incond++;			/* parentheses do globbing */
     do condlex(); while (COND_SEP());
     incond--;			/* parentheses do grouping */
@@ -2463,9 +2500,9 @@ par_cond_2(void)
 static int
 par_cond_double(char *a, char *b)
 {
-    if (a[0] != '-' || !a[1])
+    if (!IS_DASH(a[0]) || !a[1])
 	COND_ERROR("parse error: condition expected: %s", a);
-    else if (!a[2] && strspn(a+1, "abcdefgknoprstuwxzhLONGS") == 1) {
+    else if (!a[2] && strspn(a+1, "abcdefgknoprstuvwxzhLONGS") == 1) {
 	ecadd(WCB_COND(a[1], 0));
 	ecstr(b);
     } else {
@@ -2498,12 +2535,17 @@ par_cond_triple(char *a, char *b, char *c)
 {
     int t0;
 
-    if ((b[0] == Equals || b[0] == '=') &&
-	(!b[1] || ((b[1] == Equals || b[1] == '=') && !b[2]))) {
+    if ((b[0] == Equals || b[0] == '=') && !b[1]) {
 	ecadd(WCB_COND(COND_STREQ, 0));
 	ecstr(a);
 	ecstr(c);
 	ecadd(ecnpats++);
+    } else if ((b[0] == Equals || b[0] == '=') &&
+	       (b[1] == Equals || b[1] == '=') && !b[2]) {
+	ecadd(WCB_COND(COND_STRDEQ, 0));
+	ecstr(a);
+	ecstr(c);
+	ecadd(ecnpats++);
     } else if (b[0] == '!' && (b[1] == Equals || b[1] == '=') && !b[2]) {
 	ecadd(WCB_COND(COND_STRNEQ, 0));
 	ecstr(a);
@@ -2516,7 +2558,7 @@ par_cond_triple(char *a, char *b, char *c)
 	ecadd(WCB_COND(COND_REGEX, 0));
 	ecstr(a);
 	ecstr(c);
-    } else if (b[0] == '-') {
+    } else if (IS_DASH(b[0])) {
 	if ((t0 = get_cond_num(b + 1)) > -1) {
 	    ecadd(WCB_COND(t0 + COND_NT, 0));
 	    ecstr(a);
@@ -2527,7 +2569,7 @@ par_cond_triple(char *a, char *b, char *c)
 	    ecstr(a);
 	    ecstr(c);
 	}
-    } else if (a[0] == '-' && a[1]) {
+    } else if (IS_DASH(a[0]) && a[1]) {
 	ecadd(WCB_COND(COND_MOD, 2));
 	ecstr(a);
 	ecstr(b);
@@ -2542,7 +2584,7 @@ par_cond_triple(char *a, char *b, char *c)
 static int
 par_cond_multi(char *a, LinkList l)
 {
-    if (a[0] != '-' || !a[1])
+    if (!IS_DASH(a[0]) || !a[1])
 	COND_ERROR("condition expected: %s", a);
     else {
 	LinkNode n;
@@ -3238,10 +3280,10 @@ build_dump(char *nam, char *dump, char **files, int ali, int map, int flags)
     for (hlen = FD_PRELEN, tlen = 0; *files; files++) {
 	struct stat st;
 
-	if (!strcmp(*files, "-k")) {
+	if (check_cond(*files, "k")) {
 	    flags = (flags & ~(FDHF_KSHLOAD | FDHF_ZSHLOAD)) | FDHF_KSHLOAD;
 	    continue;
-	} else if (!strcmp(*files, "-z")) {
+	} else if (check_cond(*files, "z")) {
 	    flags = (flags & ~(FDHF_KSHLOAD | FDHF_ZSHLOAD)) | FDHF_ZSHLOAD;
 	    continue;
 	}
@@ -3320,7 +3362,7 @@ cur_add_func(char *nam, Shfunc shf, LinkList names, LinkList progs,
 	    return 1;
 	}
 	noaliases = (shf->node.flags & PM_UNALIASED);
-	if (!(prog = getfpfunc(shf->node.nam, NULL, NULL)) ||
+	if (!(prog = getfpfunc(shf->node.nam, NULL, NULL, NULL, 0)) ||
 	    prog == &dummy_eprog) {
 	    noaliases = ona;
 	    zwarnnam(nam, "can't load function: %s", shf->node.nam);
@@ -3395,6 +3437,7 @@ build_cur_dump(char *nam, char *dump, char **names, int match, int map,
 
 	for (; *names; names++) {
 	    tokenize(pat = dupstring(*names));
+	    /* Signal-safe here, caller queues signals */
 	    if (!(pprog = patcompile(pat, PAT_STATIC, NULL))) {
 		zwarnnam(nam, "bad pattern: %s", *names);
 		close(dfd);
@@ -3562,7 +3605,7 @@ load_dump_file(char *dump, struct stat *sbuf, int other, int len)
 
 /**/
 Eprog
-try_dump_file(char *path, char *name, char *file, int *ksh)
+try_dump_file(char *path, char *name, char *file, int *ksh, int test_only)
 {
     Eprog prog;
     struct stat std, stc, stn;
@@ -3571,7 +3614,7 @@ try_dump_file(char *path, char *name, char *file, int *ksh)
 
     if (strsfx(FD_EXT, path)) {
 	queue_signals();
-	prog = check_dump_file(path, NULL, name, ksh);
+	prog = check_dump_file(path, NULL, name, ksh, test_only);
 	unqueue_signals();
 	return prog;
     }
@@ -3590,14 +3633,14 @@ try_dump_file(char *path, char *name, char *file, int *ksh)
     if (!rd &&
 	(rc || std.st_mtime > stc.st_mtime) &&
 	(rn || std.st_mtime > stn.st_mtime) &&
-	(prog = check_dump_file(dig, &std, name, ksh))) {
+	(prog = check_dump_file(dig, &std, name, ksh, test_only))) {
 	unqueue_signals();
 	return prog;
     }
     /* No digest file. Now look for the per-function compiled file. */
     if (!rc &&
 	(rn || stc.st_mtime > stn.st_mtime) &&
-	(prog = check_dump_file(wc, &stc, name, ksh))) {
+	(prog = check_dump_file(wc, &stc, name, ksh, test_only))) {
 	unqueue_signals();
 	return prog;
     }
@@ -3625,7 +3668,7 @@ try_source_file(char *file)
 
     if (strsfx(FD_EXT, file)) {
 	queue_signals();
-	prog = check_dump_file(file, NULL, tail, NULL);
+	prog = check_dump_file(file, NULL, tail, NULL, 0);
 	unqueue_signals();
 	return prog;
     }
@@ -3636,7 +3679,7 @@ try_source_file(char *file)
 
     queue_signals();
     if (!rc && (rn || stc.st_mtime > stn.st_mtime) &&
-	(prog = check_dump_file(wc, &stc, tail, NULL))) {
+	(prog = check_dump_file(wc, &stc, tail, NULL, 0))) {
 	unqueue_signals();
 	return prog;
     }
@@ -3649,7 +3692,8 @@ try_source_file(char *file)
 
 /**/
 static Eprog
-check_dump_file(char *file, struct stat *sbuf, char *name, int *ksh)
+check_dump_file(char *file, struct stat *sbuf, char *name, int *ksh,
+		int test_only)
 {
     int isrec = 0;
     Wordcode d;
@@ -3691,6 +3735,11 @@ check_dump_file(char *file, struct stat *sbuf, char *name, int *ksh)
     if ((h = dump_find_func(d, name))) {
 	/* Found the name. If the file is already mapped, return the eprog,
 	 * otherwise map it and just go up. */
+	if (test_only)
+	{
+	    /* This is all we need.  Just return dummy. */
+	    return &dummy_eprog;
+	}
 
 #ifdef USE_MMAP
 
@@ -3727,7 +3776,7 @@ check_dump_file(char *file, struct stat *sbuf, char *name, int *ksh)
 
 #endif
 
-	    {
+	{
 	    Eprog prog;
 	    Patprog *pp;
 	    int np, fd, po = h->npats * sizeof(Patprog);