about summary refs log tree commit diff
path: root/Src
diff options
context:
space:
mode:
authorBart Schaefer <barts@users.sourceforge.net>2001-06-25 16:10:59 +0000
committerBart Schaefer <barts@users.sourceforge.net>2001-06-25 16:10:59 +0000
commit6e01a977cc49a19fe6b223b44e12ded7d9ef2061 (patch)
treeb7a434c6a8debd1b3a21306f83a332170d6e5dfd /Src
parent19cfee56c99ba1bbf299d2d31f06d513fb9262ed (diff)
downloadzsh-6e01a977cc49a19fe6b223b44e12ded7d9ef2061.tar.gz
zsh-6e01a977cc49a19fe6b223b44e12ded7d9ef2061.tar.xz
zsh-6e01a977cc49a19fe6b223b44e12ded7d9ef2061.zip
Merge a few more dev changes before 4.0.2.
Diffstat (limited to 'Src')
-rw-r--r--Src/options.c54
-rw-r--r--Src/subst.c183
-rw-r--r--Src/zsh.h135
3 files changed, 276 insertions, 96 deletions
diff --git a/Src/options.c b/Src/options.c
index 3e130a63e..2c63f194a 100644
--- a/Src/options.c
+++ b/Src/options.c
@@ -69,6 +69,7 @@ mod_export HashTable optiontab;
  * to avoid formatting problems.
  */
 static struct optname optns[] = {
+{NULL, "aliases",	      OPT_EMULATE|OPT_ALL,	 ALIASESOPT},
 {NULL, "allexport",	      OPT_EMULATE,		 ALLEXPORT},
 {NULL, "alwayslastprompt",    OPT_ALL,			 ALWAYSLASTPROMPT},
 {NULL, "alwaystoend",	      0,			 ALWAYSTOEND},
@@ -90,6 +91,7 @@ static struct optname optns[] = {
 {NULL, "bgnice",	      OPT_EMULATE|OPT_NONBOURNE, BGNICE},
 {NULL, "braceccl",	      OPT_EMULATE,		 BRACECCL},
 {NULL, "bsdecho",	      OPT_EMULATE|OPT_SH,	 BSDECHO},
+{NULL, "cbases",	      0,			 CBASES},
 {NULL, "cdablevars",	      OPT_EMULATE,		 CDABLEVARS},
 {NULL, "chasedots",	      OPT_EMULATE,		 CHASEDOTS},
 {NULL, "chaselinks",	      OPT_EMULATE,		 CHASELINKS},
@@ -112,6 +114,7 @@ static struct optname optns[] = {
 {NULL, "flowcontrol",	      OPT_ALL,			 FLOWCONTROL},
 {NULL, "functionargzero",     OPT_EMULATE|OPT_NONBOURNE, FUNCTIONARGZERO},
 {NULL, "glob",		      OPT_EMULATE|OPT_ALL,	 GLOBOPT},
+{NULL, "globalexport",        OPT_EMULATE|OPT_ZSH,	 GLOBALEXPORT},
 {NULL, "globalrcs",           OPT_ALL,			 GLOBALRCS},
 {NULL, "globassign",	      OPT_EMULATE|OPT_CSH,	 GLOBASSIGN},
 {NULL, "globcomplete",	      0,			 GLOBCOMPLETE},
@@ -142,6 +145,7 @@ static struct optname optns[] = {
 {NULL, "kshautoload",	      OPT_EMULATE|OPT_BOURNE,	 KSHAUTOLOAD},
 {NULL, "kshglob",             OPT_EMULATE|OPT_KSH,       KSHGLOB},
 {NULL, "kshoptionprint",      OPT_EMULATE|OPT_KSH,	 KSHOPTIONPRINT},
+{NULL, "kshtypeset",          OPT_EMULATE|OPT_KSH,	 KSHTYPESET},
 {NULL, "listambiguous",	      OPT_ALL,			 LISTAMBIGUOUS},
 {NULL, "listbeep",	      OPT_ALL,			 LISTBEEP},
 {NULL, "listpacked",	      0,			 LISTPACKED},
@@ -161,6 +165,7 @@ static struct optname optns[] = {
 {NULL, "notify",	      OPT_ZSH,			 NOTIFY},
 {NULL, "nullglob",	      OPT_EMULATE,		 NULLGLOB},
 {NULL, "numericglobsort",     OPT_EMULATE,		 NUMERICGLOBSORT},
+{NULL, "octalzeroes",         OPT_EMULATE|OPT_SH,	 OCTALZEROES},
 {NULL, "overstrike",	      0,			 OVERSTRIKE},
 {NULL, "pathdirs",	      OPT_EMULATE,		 PATHDIRS},
 {NULL, "posixbuiltins",	      OPT_EMULATE|OPT_BOURNE,	 POSIXBUILTINS},
@@ -209,6 +214,7 @@ static struct optname optns[] = {
 {NULL, "promptvars",	      OPT_ALIAS, /* bash */	 PROMPTSUBST},
 {NULL, "stdin",		      OPT_ALIAS, /* ksh */	 SHINSTDIN},
 {NULL, "trackall",	      OPT_ALIAS, /* ksh */	 HASHCMDS},
+{NULL, "dvorak",	      0,			 DVORAK},
 {NULL, NULL, 0, 0}
 };
 
@@ -642,6 +648,9 @@ dosetopt(int optno, int value, int force)
 	    for (s = rparams; *s; s++)
 		restrictparam(*s);
 	}
+    } else if(!force && optno == EXECOPT && !value && interact) {
+	/* cannot set noexec when interactive */
+	return -1;
     } else if(!force && (optno == INTERACTIVE || optno == SHINSTDIN ||
 	    optno == SINGLECOMMAND)) {
 	if (opts[optno] == value)
@@ -691,3 +700,48 @@ dashgetfn(Param pm)
     *val = '\0';
     return buf;
 }
+
+/* Print option list for --help */
+
+/**/
+void
+printoptionlist(void)
+{
+    short *lp;
+    char c;
+
+    printf("\nNamed options:\n");
+    scanhashtable(optiontab, 1, 0, OPT_ALIAS, printoptionlist_printoption, 0);
+    printf("\nOption aliases:\n");
+    scanhashtable(optiontab, 1, OPT_ALIAS, 0, printoptionlist_printoption, 0);
+    printf("\nOption letters:\n");
+    for(lp = optletters, c = FIRST_OPT; c <= LAST_OPT; lp++, c++) {
+	if(!*lp)
+	    continue;
+	printf("  -%c  ", c);
+	printoptionlist_printequiv(*lp);
+    }
+}
+
+/**/
+static void
+printoptionlist_printoption(HashNode hn, int ignored)
+{
+    Optname on = (Optname) hn;
+
+    if(on->flags & OPT_ALIAS) {
+	printf("  --%-19s  ", on->nam);
+	printoptionlist_printequiv(on->optno);
+    } else
+	printf("  --%s\n", on->nam);
+}
+
+/**/
+static void
+printoptionlist_printequiv(int optno)
+{
+    int isneg = optno < 0;
+
+    optno *= (isneg ? -1 : 1);
+    printf("  equivalent to --%s%s\n", isneg ? "no-" : "", optns[optno-1].nam);
+}
diff --git a/Src/subst.c b/Src/subst.c
index 408a9d406..b5480d75e 100644
--- a/Src/subst.c
+++ b/Src/subst.c
@@ -50,7 +50,9 @@ mod_export void
 prefork(LinkList list, int flags)
 {
     LinkNode node;
+    int asssub = (flags & PF_TYPESET) && isset(KSHTYPESET);
 
+    queue_signals();
     for (node = firstnode(list); node; incnode(node)) {
 	char *str, c;
 
@@ -61,14 +63,18 @@ prefork(LinkList list, int flags)
 		setdata(node, (void *) getproc(str));	/* <(...) or >(...) */
 	    else
 		setdata(node, (void *) getoutputfile(str));	/* =(...) */
-	    if (!getdata(node))
+	    if (!getdata(node)) {
+		unqueue_signals();
 		return;
+	    }
 	} else {
 	    if (isset(SHFILEEXPANSION))
 		filesub((char **)getaddrdata(node),
 			flags & (PF_TYPESET|PF_ASSIGN));
-	    if (!(node = stringsubst(list, node, flags & PF_SINGLE)))
+	    if (!(node = stringsubst(list, node, flags & PF_SINGLE, asssub))) {
+		unqueue_signals();
 		return;
+	    }
 	}
     }
     for (node = firstnode(list); node; incnode(node)) {
@@ -82,14 +88,17 @@ prefork(LinkList list, int flags)
 			flags & (PF_TYPESET|PF_ASSIGN));
 	} else if (!(flags & PF_SINGLE))
 	    uremnode(list, node);
-	if (errflag)
+	if (errflag) {
+	    unqueue_signals();
 	    return;
+	}
     }
+    unqueue_signals();
 }
 
 /**/
 static LinkNode
-stringsubst(LinkList list, LinkNode node, int ssub)
+stringsubst(LinkList list, LinkNode node, int ssub, int asssub)
 {
     int qt;
     char *str3 = (char *)getdata(node);
@@ -203,6 +212,12 @@ stringsubst(LinkList list, LinkNode node, int ssub)
 	    str3 = str2;
 	    setdata(node, str3);
 	    continue;
+	} else if (asssub && ((c == '=') || c == Equals) && str != str3) {
+	    /*
+	     * We are in a normal argument which looks like an assignment
+	     * and is to be treated like one, with no word splitting.
+	     */
+	    ssub = 1;
 	}
 	str++;
     }
@@ -307,7 +322,7 @@ multsub(char **s, char ***a, int *isarr, char *sep)
 mod_export void
 filesub(char **namptr, int assign)
 {
-    char *sub = NULL, *str, *ptr;
+    char *eql = NULL, *sub = NULL, *str, *ptr;
     int len;
 
     filesubstr(namptr, assign);
@@ -316,7 +331,7 @@ filesub(char **namptr, int assign)
 	return;
 
     if (assign & PF_TYPESET) {
-	if ((*namptr)[1] && (sub = strchr(*namptr + 1, Equals))) {
+	if ((*namptr)[1] && (eql = sub = strchr(*namptr + 1, Equals))) {
 	    str = sub + 1;
 	    if ((sub[1] == Tilde || sub[1] == Equals) && filesubstr(&str, assign)) {
 		sub[1] = '\0';
@@ -330,7 +345,9 @@ filesub(char **namptr, int assign)
     while ((sub = strchr(ptr, ':'))) {
 	str = sub + 1;
 	len = sub - *namptr;
-	if ((sub[1] == Tilde || sub[1] == Equals) && filesubstr(&str, assign)) {
+	if (sub > eql &&
+	    (sub[1] == Tilde || sub[1] == Equals) &&
+	    filesubstr(&str, assign)) {
 	    sub[1] = '\0';
 	    *namptr = dyncat(*namptr, str);
 	}
@@ -702,17 +719,21 @@ get_intarg(char **s)
 /* Parsing for the (e) flag. */
 
 static int
-subst_parse_str(char **sp, int single)
+subst_parse_str(char **sp, int single, int err)
 {
     char *s;
 
     *sp = s = dupstring(*sp);
 
-    if (!parsestr(s)) {
+    if (!(err ? parsestr(s) : parsestrnoerr(s))) {
 	if (!single) {
+            int qt = 0;
+
 	    for (; *s; s++)
-		if (*s == Qstring)
+		if (!qt && *s == Qstring)
 		    *s = String;
+                else if (*s == Dnull)
+                    qt = !qt;
 	}
 	return 0;
     }
@@ -750,6 +771,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
     int casmod = 0;
     int quotemod = 0, quotetype = 0, quoteerr = 0;
     int visiblemod = 0;
+    int shsplit = 0;
     char *sep = NULL, *spsep = NULL;
     char *premul = NULL, *postmul = NULL, *preone = NULL, *postone = NULL;
     char *replstr = NULL;	/* replacement string for /orig/repl */
@@ -971,6 +993,10 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
 		    presc++;
 		    break;
 
+		case 'z':
+		    shsplit = 1;
+		    break;
+
 		default:
 		  flagerr:
 		    zerr("error in flags", NULL, 0);
@@ -1000,7 +1026,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
 		spbreak = 0;
 		s++;
 	    } else
-		spbreak = 1;
+		spbreak = 2;
 	} else if ((c == '#' || c == Pound) &&
 		   (iident(cc = s[1])
 		    || cc == '*' || cc == Star || cc == '@'
@@ -1053,7 +1079,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
 	    s++;
 	v = (Value) NULL;
     } else if (aspar) {
-	if ((v = getvalue(&vbuf, &s, 1))) {
+	if ((v = fetchvalue(&vbuf, &s, 1, (qt ? SCANPM_DQUOTED : 0)))) {
 	    val = idbeg = getstrvalue(v);
 	    subexp = 1;
 	} else
@@ -1065,7 +1091,9 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
 	if (!(v = fetchvalue(&vbuf, (subexp ? &ov : &s),
 			     (wantt ? -1 :
 			      ((unset(KSHARRAYS) || inbrace) ? 1 : -1)),
-			     hkeys|hvals|(arrasg ? SCANPM_ASSIGNING : 0))) ||
+			     hkeys|hvals|
+			     (arrasg ? SCANPM_ASSIGNING : 0)|
+			     (qt ? SCANPM_DQUOTED : 0))) ||
 	    (v->pm && (v->pm->flags & PM_UNSET)))
 	    vunset = 1;
 
@@ -1104,6 +1132,8 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
 		    val = dyncat(val, "-unique");
 		if (f & PM_HIDE)
 		    val = dyncat(val, "-hide");
+		if (f & PM_HIDE)
+		    val = dyncat(val, "-hideval");
 		if (f & PM_SPECIAL)
 		    val = dyncat(val, "-special");
 		vunset = 0;
@@ -1126,6 +1156,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
 		isarr = 0;
 	    }
 	    pm = createparam(nulstring, isarr ? PM_ARRAY : PM_SCALAR);
+	    DPUTS(!pm, "BUG: parameter not created");
 	    if (isarr)
 		pm->u.arr = aval;
 	    else
@@ -1133,8 +1164,8 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
 	    v = (Value) hcalloc(sizeof *v);
 	    v->isarr = isarr;
 	    v->pm = pm;
-	    v->b = -1;
-	    if (getindex(&s, v) || s == os)
+	    v->end = -1;
+	    if (getindex(&s, v, qt) || s == os)
 		break;
 	}
 	if ((isarr = v->isarr)) {
@@ -1149,9 +1180,9 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
 	    if (v->pm->flags & PM_ARRAY) {
 		int tmplen = arrlen(v->pm->gets.afn(v->pm));
 
-		if (v->a < 0)
-		    v->a += tmplen + v->inv;
-		if (!v->inv && (v->a >= tmplen || v->a < 0))
+		if (v->start < 0)
+		    v->start += tmplen + v->inv;
+		if (!v->inv && (v->start >= tmplen || v->start < 0))
 		    vunset = 1;
 	    }
 	    if (!vunset) {
@@ -1225,6 +1256,15 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
 	if (!inbrace)
 	    break;
     }
+    if (inbrace &&
+	(c = *s) != '-' && c != '+' && c != ':' && c != '%'  && c != '/' &&
+	c != '=' && c != Equals &&
+	c != '#' && c != Pound &&
+	c != '?' && c != Quest &&
+	c != '}' && c != Outbrace) {
+	zerr("bad substitution", NULL, 0);
+	return NULL;
+    }
     if (isarr) {
 	if (nojoin)
 	    isarr = -1;
@@ -1353,7 +1393,14 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
 	case '-':
 	    if (vunset) {
 		val = dupstring(s);
-		multsub(&val, NULL, &isarr, NULL);
+		/*
+		 * This is not good enough for sh emulation!  Sh would
+		 * split unquoted substrings, yet not split quoted ones
+		 * (except according to $@ rules); but this leaves the
+		 * unquoted substrings unsplit, and other code below
+		 * for spbreak splits even within the quoted substrings.
+		 */
+		multsub(&val, (aspar ? NULL : &aval), &isarr, NULL);
 		copied = 1;
 	    }
 	    break;
@@ -1381,8 +1428,6 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
 		    if (spsep || spbreak) {
 			aval = sepsplit(val, spsep, 0, 1);
 			isarr = 2;
-			sep = spsep = NULL;
-			spbreak = 0;
 			l = arrlen(aval);
 			if (l && !*(aval[l-1]))
 			    l--;
@@ -1420,6 +1465,16 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
 		}
 		*idend = sav;
 		copied = 1;
+		if (isarr) {
+		  if (nojoin)
+		    isarr = -1;
+		  if (qt && !getlen && isarr > 0 && !spsep && spbreak < 2) {
+		    val = sepjoin(aval, sep, 1);
+		    isarr = 0;
+		  }
+		  sep = spsep = NULL;
+		  spbreak = 0;
+		}
 	    }
 	    break;
 	case '?':
@@ -1440,7 +1495,14 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
 	case '#':
 	case Pound:
 	case '/':
-	    if (qt) {
+            /* This once was executed only `if (qt) ...'. But with that
+             * patterns in a expansion resulting from a ${(e)...} aren't
+             * tokenized even though this function thinks they are (it thinks
+             * they are because subst_parse_string() turns Qstring tokens
+             * into String tokens and for unquoted parameter expansions the
+             * lexer normally does tokenize patterns inside parameter
+             * expansions). */
+            {
 		int one = noerrs, oef = errflag, haserr;
 
 		if (!quoteerr)
@@ -1458,9 +1520,18 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
 		}
 	    }
 	    {
+#if 0
+		/*
+		 * This allows # and % to be at the start of
+		 * a parameter in the substitution, which is
+		 * a bit nasty, and can be done (although
+		 * less efficiently) with anchors.
+		 */
+
 		char t = s[-1];
 
 		singsub(&s);
+
 		if (t == '/' && (flags & SUB_SUBSTR)) {
 		    if ((c = *s) == '#' || c == '%') {
 			flags &= ~SUB_SUBSTR;
@@ -1471,6 +1542,9 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
 			s++;
 		    }
 		}
+#else
+		singsub(&s);
+#endif
 	    }
 
 	    if (!vunset && isarr) {
@@ -1635,18 +1709,24 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
 		aval = arrdup(aval), copied = 1;
 	    ap = aval;
 	    for (; *ap; ap++) {
+		char *tmps;
 		unmetafy(*ap, &len);
 		untokenize(*ap);
-		*ap = unmetafy(promptexpand(metafy(*ap, len, META_NOALLOC),
-					    0, NULL, NULL), &len);
+		tmps = unmetafy(promptexpand(metafy(*ap, len, META_NOALLOC),
+					     0, NULL, NULL), &len);
+		*ap = dupstring(tmps);
+		free(tmps);
 	    }
 	} else {
+	    char *tmps;
 	    if (!copied)
 		val = dupstring(val), copied = 1;
 	    unmetafy(val, &len);
 	    untokenize(val);
-	    val = unmetafy(promptexpand(metafy(val, len, META_NOALLOC),
+	    tmps = unmetafy(promptexpand(metafy(val, len, META_NOALLOC),
 					0, NULL, NULL), &len);
+	    val = dupstring(tmps);
+	    free(tmps);
 	}
 	opts[PROMPTSUBST] = ops;
 	opts[PROMPTBANG] = opb;
@@ -1748,6 +1828,34 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
 	    val = nicedupstring(val);
 	}
     }
+    if (shsplit) {
+	LinkList list = NULL;
+
+	if (isarr) {
+	    char **ap;
+	    for (ap = aval; *ap; ap++)
+		list = bufferwords(list, *ap, NULL);
+	    isarr = 0;
+	} else
+	    list = bufferwords(NULL, val, NULL);
+
+	if (!firstnode(list))
+	    val = dupstring("");
+	else if (!nextnode(firstnode(list)))
+	    val = getdata(firstnode(list));
+	else {
+	    char **ap;
+	    LinkNode node;
+
+	    aval = ap = (char **) zhalloc((countlinknodes(list) + 1) *
+					  sizeof(char *));
+	    for (node = firstnode(list); node; incnode(node))
+		*ap++ = (char *) getdata(node);
+	    *ap = NULL;
+	    mult_isarr = isarr = 2;
+	}
+	copied = 1;
+    }
     if (isarr) {
 	char *x;
 	char *y;
@@ -1784,7 +1892,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
 
 	    *--fstr = Marker;
 	    init_list1(tl, fstr);
-	    if (!eval && !stringsubst(&tl, firstnode(&tl), ssub))
+	    if (!eval && !stringsubst(&tl, firstnode(&tl), ssub, 0))
 		return NULL;
 	    *str = aptr;
 	    tn = firstnode(&tl);
@@ -1792,7 +1900,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
 		if (prenum || postnum)
 		    x = dopadding(x, prenum, postnum, preone, postone,
 				  premul, postmul);
-		if (eval && subst_parse_str(&x, (qt && !nojoin)))
+		if (eval && subst_parse_str(&x, (qt && !nojoin), quoteerr))
 		    return NULL;
 		xlen = strlen(x);
 		for (tn = firstnode(&tl);
@@ -1828,7 +1936,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
 	    if (prenum || postnum)
 		x = dopadding(x, prenum, postnum, preone, postone,
 			      premul, postmul);
-	    if (eval && subst_parse_str(&x, (qt && !nojoin)))
+	    if (eval && subst_parse_str(&x, (qt && !nojoin), quoteerr))
 		return NULL;
 	    xlen = strlen(x);
 	    strcatsub(&y, ostr, aptr, x, xlen, NULL, globsubst, copied);
@@ -1843,7 +1951,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
 		if (prenum || postnum)
 		    x = dopadding(x, prenum, postnum, preone, postone,
 				  premul, postmul);
-		if (eval && subst_parse_str(&x, (qt && !nojoin)))
+		if (eval && subst_parse_str(&x, (qt && !nojoin), quoteerr))
 		    return NULL;
 		if (qt && !*x && isarr != 2)
 		    y = dupstring(nulstring);
@@ -1859,7 +1967,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
 	    if (prenum || postnum)
 		x = dopadding(x, prenum, postnum, preone, postone,
 			      premul, postmul);
-	    if (eval && subst_parse_str(&x, (qt && !nojoin)))
+	    if (eval && subst_parse_str(&x, (qt && !nojoin), quoteerr))
 		return NULL;
 	    xlen = strlen(x);
 	    *str = strcatsub(&y, aptr, aptr, x, xlen, fstr, globsubst, copied);
@@ -1878,7 +1986,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
 	if (prenum || postnum)
 	    x = dopadding(x, prenum, postnum, preone, postone,
 			  premul, postmul);
-	if (eval && subst_parse_str(&x, (qt && !nojoin)))
+	if (eval && subst_parse_str(&x, (qt && !nojoin), quoteerr))
 	    return NULL;
 	xlen = strlen(x);
 	*str = strcatsub(&y, ostr, aptr, x, xlen, fstr, globsubst, copied);
@@ -1905,15 +2013,18 @@ static char *
 arithsubst(char *a, char **bptr, char *rest)
 {
     char *s = *bptr, *t;
-    char buf[DIGBUFSIZE], *b = buf;
+    char buf[BDIGBUFSIZE], *b = buf;
     mnumber v;
 
     singsub(&a);
     v = matheval(a);
-    if (v.type & MN_FLOAT)
+    if ((v.type & MN_FLOAT) && !outputradix)
 	b = convfloat(v.u.d, 0, 0, NULL);
-    else
-	convbase(buf, v.u.l, 0);
+    else {
+	if (v.type & MN_FLOAT)
+	    v.u.l = (zlong) v.u.d;
+	convbase(buf, v.u.l, outputradix);
+    }
     t = *bptr = (char *) hcalloc(strlen(*bptr) + strlen(b) + 
 				 strlen(rest) + 1);
     t--;
@@ -1975,7 +2086,7 @@ modify(char **str, char **ptr)
 		if (*ptr1) {
 		    zsfree(hsubl);
 		    hsubl = ztrdup(ptr1);
-		}
+ 		}
 		if (!hsubl) {
 		    zerr("no previous substitution", NULL, 0);
 		    return;
diff --git a/Src/zsh.h b/Src/zsh.h
index 41add5c35..3b6c0aad4 100644
--- a/Src/zsh.h
+++ b/Src/zsh.h
@@ -30,7 +30,6 @@
 #define trashzle()      trashzleptr()
 #define zleread(X,Y,H)  zlereadptr(X,Y,H)
 #define spaceinline(X)  spaceinlineptr(X)
-#define gotword()       gotwordptr()
 #define zrefresh()      refreshptr()
 
 #define compctlread(N,A,O,R) compctlreadptr(N,A,O,R)
@@ -234,31 +233,31 @@ enum {
  * below.                                                              */
 
 enum {
-    WRITE,		/* > */
-    WRITENOW,		/* >| */
-    APP,		/* >> */
-    APPNOW,		/* >>| */
-    ERRWRITE,		/* &>, >& */
-    ERRWRITENOW,	/* >&| */
-    ERRAPP,		/* >>& */
-    ERRAPPNOW,		/* >>&| */
-    READWRITE,		/* <> */
-    READ,		/* < */
-    HEREDOC,		/* << */
-    HEREDOCDASH,	/* <<- */
-    HERESTR,		/* <<< */
-    MERGEIN,		/* <&n */
-    MERGEOUT,		/* >&n */
-    CLOSE,		/* >&-, <&- */
-    INPIPE,		/* < <(...) */
-    OUTPIPE		/* > >(...) */
+    REDIR_WRITE,		/* > */
+    REDIR_WRITENOW,		/* >| */
+    REDIR_APP,		/* >> */
+    REDIR_APPNOW,		/* >>| */
+    REDIR_ERRWRITE,		/* &>, >& */
+    REDIR_ERRWRITENOW,	/* >&| */
+    REDIR_ERRAPP,		/* >>& */
+    REDIR_ERRAPPNOW,		/* >>&| */
+    REDIR_READWRITE,		/* <> */
+    REDIR_READ,		/* < */
+    REDIR_HEREDOC,		/* << */
+    REDIR_HEREDOCDASH,	/* <<- */
+    REDIR_HERESTR,		/* <<< */
+    REDIR_MERGEIN,		/* <&n */
+    REDIR_MERGEOUT,		/* >&n */
+    REDIR_CLOSE,		/* >&-, <&- */
+    REDIR_INPIPE,		/* < <(...) */
+    REDIR_OUTPIPE		/* > >(...) */
 };
 
-#define IS_WRITE_FILE(X)      ((X)>=WRITE && (X)<=READWRITE)
+#define IS_WRITE_FILE(X)      ((X)>=REDIR_WRITE && (X)<=REDIR_READWRITE)
 #define IS_APPEND_REDIR(X)    (IS_WRITE_FILE(X) && ((X) & 2))
 #define IS_CLOBBER_REDIR(X)   (IS_WRITE_FILE(X) && ((X) & 1))
-#define IS_ERROR_REDIR(X)     ((X)>=ERRWRITE && (X)<=ERRAPPNOW)
-#define IS_READFD(X)          (((X)>=READWRITE && (X)<=MERGEIN) || (X)==INPIPE)
+#define IS_ERROR_REDIR(X)     ((X)>=REDIR_ERRWRITE && (X)<=REDIR_ERRAPPNOW)
+#define IS_READFD(X)          (((X)>=REDIR_READWRITE && (X)<=REDIR_MERGEIN) || (X)==REDIR_INPIPE)
 #define IS_REDIROP(X)         ((X)>=OUTANG && (X)<=TRINANG)
 
 /* Flags for input stack */
@@ -468,8 +467,8 @@ struct value {
     int isarr;
     Param pm;		/* parameter node                      */
     int inv;		/* should we return the index ?        */
-    int a;		/* first element of array slice, or -1 */
-    int b;		/* last element of array slice, or -1  */
+    int start;		/* first element of array slice, or -1 */
+    int end;		/* 1-rel last element of array slice, or -1 */
     char **arr;		/* cache for hash turned into array */
 };
 
@@ -487,7 +486,8 @@ typedef struct eprog *Eprog;
 
 struct funcdump {
     FuncDump next;		/* next in list */
-    char *name;			/* path name */
+    dev_t dev;			/* device */
+    ino_t ino;			/* indoe number */
     int fd;			/* file descriptor */
     Wordcode map;		/* pointer to header */
     Wordcode addr;		/* mapped region */
@@ -496,7 +496,7 @@ struct funcdump {
 };
 
 struct eprog {
-    int alloc;			/* EA_* below */
+    int flags;			/* EF_* below */
     int len;			/* total block length */
     int npats;			/* Patprog cache size */
     Patprog *pats;		/* the memory block, the patterns */
@@ -506,9 +506,10 @@ struct eprog {
     FuncDump dump;		/* dump file this is in */
 };
 
-#define EA_REAL 0
-#define EA_HEAP 1
-#define EA_MAP  2
+#define EF_REAL 1
+#define EF_HEAP 2
+#define EF_MAP  4
+#define EF_RUN  8
 
 typedef struct estate *Estate;
 
@@ -521,9 +522,9 @@ struct estate {
 typedef struct eccstr *Eccstr;
 
 struct eccstr {
-    Eccstr next;
+    Eccstr left, right;
     char *str;
-    wordcode offs;
+    wordcode offs, aoffs;
     int nfunc;
 };
 
@@ -659,8 +660,9 @@ struct eccstr {
 /* Defintions for job table and job control */
 /********************************************/
 
-/* size of job table */
-#define MAXJOB 50
+#ifdef NEED_LINUX_TASKS_H
+#include <linux/tasks.h>
+#endif
 
 /* entry in the job table */
 
@@ -751,6 +753,8 @@ struct dirsav {
     ino_t ino;
 };
 
+#define MAX_PIPESTATS 256
+
 /*******************************/
 /* Definitions for Hash Tables */
 /*******************************/
@@ -953,6 +957,7 @@ struct module {
     union {
 	void *handle;
 	Linkedmod linked;
+	char *alias;
     } u;
     LinkList deps;
     int wrapper;
@@ -964,6 +969,7 @@ struct module {
 #define MOD_LINKED  (1<<3)
 #define MOD_INIT_S  (1<<4)
 #define MOD_INIT_B  (1<<5)
+#define MOD_ALIAS   (1<<6)
 
 typedef int (*Module_func) _((Module));
 
@@ -1019,6 +1025,8 @@ struct patprog {
 #define PAT_STATIC	0x0040	/* Don't copy pattern to heap as per default */
 #define PAT_SCAN	0x0080	/* Scanning, so don't try must-match test */
 #define PAT_ZDUP        0x0100  /* Copy pattern in real memory */
+#define PAT_NOTSTART	0x0200	/* Start of string is not real start */
+#define PAT_NOTEND	0x0400	/* End of string is not real end */
 
 /* Globbing flags: lower 8 bits gives approx count */
 #define GF_LCMATCHUC	0x0100
@@ -1111,20 +1119,22 @@ struct param {
 #define PM_UNALIASED	(1<<13)	/* do not expand aliases when autoloading   */
 
 #define PM_HIDE		(1<<14)	/* Special behaviour hidden by local        */
-#define PM_TIED 	(1<<15)	/* array tied to colon-path or v.v.         */
+#define PM_HIDEVAL	(1<<15)	/* Value not shown in `typeset' commands    */
+#define PM_TIED 	(1<<16)	/* array tied to colon-path or v.v.         */
 
 /* Remaining flags do not correspond directly to command line arguments */
-#define PM_LOCAL	(1<<16) /* this parameter will be made local        */
-#define PM_SPECIAL	(1<<17) /* special builtin parameter                */
-#define PM_DONTIMPORT	(1<<18)	/* do not import this variable              */
-#define PM_RESTRICTED	(1<<19) /* cannot be changed in restricted mode     */
-#define PM_UNSET	(1<<20)	/* has null value                           */
-#define PM_REMOVABLE	(1<<21)	/* special can be removed from paramtab     */
-#define PM_AUTOLOAD	(1<<22) /* autoloaded from module                   */
-#define PM_NORESTORE	(1<<23)	/* do not restore value of local special    */
+#define PM_LOCAL	(1<<17) /* this parameter will be made local        */
+#define PM_SPECIAL	(1<<18) /* special builtin parameter                */
+#define PM_DONTIMPORT	(1<<19)	/* do not import this variable              */
+#define PM_RESTRICTED	(1<<20) /* cannot be changed in restricted mode     */
+#define PM_UNSET	(1<<21)	/* has null value                           */
+#define PM_REMOVABLE	(1<<22)	/* special can be removed from paramtab     */
+#define PM_AUTOLOAD	(1<<23) /* autoloaded from module                   */
+#define PM_NORESTORE	(1<<24)	/* do not restore value of local special    */
+#define PM_HASHELEM     (1<<25) /* is a hash-element */
 
 /* The option string corresponds to the first of the variables above */
-#define TYPESET_OPTSTR "aiEFALRZlurtxUhT"
+#define TYPESET_OPTSTR "aiEFALRZlurtxUhHT"
 
 /* These typeset options take an optional numeric argument */
 #define TYPESET_OPTNUM "LRZiEF"
@@ -1138,6 +1148,7 @@ struct param {
 #define SCANPM_MATCHMANY  (1<<5)
 #define SCANPM_ASSIGNING  (1<<6)
 #define SCANPM_KEYMATCH   (1<<7)
+#define SCANPM_DQUOTED    (1<<8)
 #define SCANPM_ISVAR_AT   ((-1)<<15)	/* Only sign bit is significant */
 
 /*
@@ -1205,13 +1216,14 @@ struct nameddir {
 #define PRINT_TYPE		(1<<1)
 #define PRINT_LIST		(1<<2)
 #define PRINT_KV_PAIR		(1<<3)
+#define PRINT_INCLUDEVALUE	(1<<4)
 
 /* flags for printing for the whence builtin */
-#define PRINT_WHENCE_CSH	(1<<4)
-#define PRINT_WHENCE_VERBOSE	(1<<5)
-#define PRINT_WHENCE_SIMPLE	(1<<6)
-#define PRINT_WHENCE_FUNCDEF	(1<<7)
-#define PRINT_WHENCE_WORD	(1<<8)
+#define PRINT_WHENCE_CSH	(1<<5)
+#define PRINT_WHENCE_VERBOSE	(1<<6)
+#define PRINT_WHENCE_SIMPLE	(1<<7)
+#define PRINT_WHENCE_FUNCDEF	(1<<9)
+#define PRINT_WHENCE_WORD	(1<<10)
 
 /***********************************/
 /* Definitions for history control */
@@ -1240,6 +1252,7 @@ struct histent {
 #define HIST_READ	0x00000004	/* Command was read back from disk*/
 #define HIST_DUP	0x00000008	/* Command duplicates a later line */
 #define HIST_FOREIGN	0x00000010	/* Command came from another shell */
+#define HIST_TMPSTORE	0x00000020	/* Kill when user enters another cmd */
 
 #define GETHIST_UPWARD  (-1)
 #define GETHIST_DOWNWARD  1
@@ -1294,6 +1307,7 @@ struct histent {
 
 enum {
     OPT_INVALID,
+    ALIASESOPT,
     ALLEXPORT,
     ALWAYSLASTPROMPT,
     ALWAYSTOEND,
@@ -1315,6 +1329,7 @@ enum {
     BGNICE,
     BRACECCL,
     BSDECHO,
+    CBASES,
     CDABLEVARS,
     CHASEDOTS,
     CHASELINKS,
@@ -1336,8 +1351,9 @@ enum {
     EXTENDEDHISTORY,
     FLOWCONTROL,
     FUNCTIONARGZERO,
-    GLOBALRCS,
     GLOBOPT,
+    GLOBALEXPORT,
+    GLOBALRCS,
     GLOBASSIGN,
     GLOBCOMPLETE,
     GLOBDOTS,
@@ -1367,6 +1383,7 @@ enum {
     KSHAUTOLOAD,
     KSHGLOB,
     KSHOPTIONPRINT,
+    KSHTYPESET,
     LISTAMBIGUOUS,
     LISTBEEP,
     LISTPACKED,
@@ -1386,6 +1403,7 @@ enum {
     NOTIFY,
     NULLGLOB,
     NUMERICGLOBSORT,
+    OCTALZEROES,
     OVERSTRIKE,
     PATHDIRS,
     POSIXBUILTINS,
@@ -1422,6 +1440,7 @@ enum {
     VERBOSE,
     XTRACE,
     USEZLE,
+    DVORAK,
     OPT_SIZE
 };
 
@@ -1508,7 +1527,11 @@ struct ttyinfo {
 #define TCSTANDOUTEND  22
 #define TCUNDERLINEEND 23
 #define TCHORIZPOS     24
-#define TC_COUNT       25
+#define TCUPCURSOR     25
+#define TCDOWNCURSOR   26
+#define TCLEFTCURSOR   27
+#define TCRIGHTCURSOR  28
+#define TC_COUNT       29
 
 #define tccan(X) (tclen[X])
 
@@ -1612,13 +1635,11 @@ struct heap {
 #endif
 ;
 
-# define LASTALLOC_RETURN return
-
 # define NEWHEAPS(h)    do { Heap _switch_oldheaps = h = new_heaps(); do
 # define OLDHEAPS       while (0); old_heaps(_switch_oldheaps); } while (0);
 
-# define SWITCHHEAPS(h)  do { Heap _switch_oldheaps = switch_heaps(h); do
-# define SWITCHBACKHEAPS while (0); switch_heaps(_switch_oldheaps); } while (0);
+# define SWITCHHEAPS(o, h)  do { o = switch_heaps(h); do
+# define SWITCHBACKHEAPS(o) while (0); switch_heaps(o); } while (0);
 
 /****************/
 /* Debug macros */
@@ -1666,12 +1687,6 @@ typedef void (*ZleVoidIntFn) _((int));
 typedef unsigned char * (*ZleReadFn) _((char *, char *, int));
 
 /***************************************/
-/* Pseudo-keyword to mark exportedness */
-/***************************************/
-
-#define mod_export
-
-/***************************************/
 /* Hooks in core.                      */
 /***************************************/