summaryrefslogtreecommitdiff
path: root/Src
diff options
context:
space:
mode:
Diffstat (limited to 'Src')
-rw-r--r--Src/Modules/parameter.c20
-rw-r--r--Src/Modules/regex.c23
-rw-r--r--Src/Zle/zle.h1
-rw-r--r--Src/Zle/zle_params.c32
-rw-r--r--Src/Zle/zle_utils.c30
-rw-r--r--Src/builtin.c100
-rw-r--r--Src/exec.c27
-rw-r--r--Src/glob.c15
-rw-r--r--Src/hashtable.c3
-rw-r--r--Src/hist.c3
-rw-r--r--Src/init.c123
-rw-r--r--Src/jobs.c24
-rw-r--r--Src/options.c16
-rw-r--r--Src/params.c141
-rw-r--r--Src/prompt.c16
-rw-r--r--Src/subst.c69
-rw-r--r--Src/utils.c53
-rw-r--r--Src/zsh_system.h4
18 files changed, 540 insertions, 160 deletions
diff --git a/Src/Modules/parameter.c b/Src/Modules/parameter.c
index 092efa0c3..4d29ba635 100644
--- a/Src/Modules/parameter.c
+++ b/Src/Modules/parameter.c
@@ -531,7 +531,11 @@ functracegetfn(UNUSED(Param pm))
char *colonpair;
colonpair = zhalloc(strlen(f->caller) + (f->lineno > 9999 ? 24 : 6));
+#if defined(ZLONG_IS_LONG_LONG) && defined(PRINTF_HAS_LLD)
+ sprintf(colonpair, "%s:%lld", f->caller, f->lineno);
+#else
sprintf(colonpair, "%s:%ld", f->caller, (long)f->lineno);
+#endif
*p = colonpair;
}
@@ -559,7 +563,11 @@ funcsourcetracegetfn(UNUSED(Param pm))
char *fname = f->filename ? f->filename : "";
colonpair = zhalloc(strlen(fname) + (f->flineno > 9999 ? 24 : 6));
+#if defined(ZLONG_IS_LONG_LONG) && defined(PRINTF_HAS_LLD)
+ sprintf(colonpair, "%s:%lld", fname, f->flineno);
+#else
sprintf(colonpair, "%s:%ld", fname, (long)f->flineno);
+#endif
*p = colonpair;
}
@@ -594,7 +602,11 @@ funcfiletracegetfn(UNUSED(Param pm))
*/
colonpair = zhalloc(strlen(f->caller) +
(f->lineno > 9999 ? 24 : 6));
+#if defined(ZLONG_IS_LONG_LONG) && defined(PRINTF_HAS_LLD)
+ sprintf(colonpair, "%s:%lld", f->caller, f->lineno);
+#else
sprintf(colonpair, "%s:%ld", f->caller, (long)f->lineno);
+#endif
} else {
/*
* Calling context is a function or eval; we need to find
@@ -604,7 +616,7 @@ funcfiletracegetfn(UNUSED(Param pm))
* together with the $functrace line number for the current
* context.
*/
- long flineno = (long)(f->prev->flineno + f->lineno);
+ zlong flineno = f->prev->flineno + f->lineno;
/*
* Line numbers in eval start from 1, not zero,
* so offset by one to get line in file.
@@ -614,7 +626,11 @@ funcfiletracegetfn(UNUSED(Param pm))
fname = f->prev->filename ? f->prev->filename : "";
colonpair = zhalloc(strlen(fname) + (flineno > 9999 ? 24 : 6));
- sprintf(colonpair, "%s:%ld", fname, flineno);
+#if defined(ZLONG_IS_LONG_LONG) && defined(PRINTF_HAS_LLD)
+ sprintf(colonpair, "%s:%lld", fname, flineno);
+#else
+ sprintf(colonpair, "%s:%ld", fname, (long)flineno);
+#endif
}
*p = colonpair;
diff --git a/Src/Modules/regex.c b/Src/Modules/regex.c
index 08e815003..ce57de986 100644
--- a/Src/Modules/regex.c
+++ b/Src/Modules/regex.c
@@ -3,7 +3,7 @@
*
* This file is part of zsh, the Z shell.
*
- * Copyright (c) 2007 Phil Pennock
+ * Copyright (c) 2007,2012 Phil Pennock
* All Rights Reserved.
*
* Permission is hereby granted, without written agreement and without
@@ -56,14 +56,19 @@ zcond_regex_match(char **a, int id)
regex_t re;
regmatch_t *m, *matches = NULL;
size_t matchessz = 0;
- char *lhstr, *rhre, *s, **arr, **x;
+ char *lhstr, *lhstr_zshmeta, *rhre, *rhre_zshmeta, *s, **arr, **x;
int r, n, return_value, rcflags, reflags, nelem, start;
- lhstr = cond_str(a,0,0);
- rhre = cond_str(a,1,0);
+ lhstr_zshmeta = cond_str(a,0,0);
+ rhre_zshmeta = cond_str(a,1,0);
rcflags = reflags = 0;
return_value = 0; /* 1 => matched successfully */
+ lhstr = ztrdup(lhstr_zshmeta);
+ unmetafy(lhstr, NULL);
+ rhre = ztrdup(rhre_zshmeta);
+ unmetafy(rhre, NULL);
+
switch(id) {
case ZREGEX_EXTENDED:
rcflags |= REG_EXTENDED;
@@ -101,7 +106,7 @@ zcond_regex_match(char **a, int id)
if (nelem) {
arr = x = (char **) zalloc(sizeof(char *) * (nelem + 1));
for (m = matches + start, n = start; n <= (int)re.re_nsub; ++n, ++m, ++x) {
- *x = ztrduppfx(lhstr + m->rm_so, m->rm_eo - m->rm_so);
+ *x = metafy(lhstr + m->rm_so, m->rm_eo - m->rm_so, META_DUP);
}
*x = NULL;
}
@@ -112,7 +117,7 @@ zcond_regex_match(char **a, int id)
char *ptr;
m = matches;
- s = ztrduppfx(lhstr + m->rm_so, m->rm_eo - m->rm_so);
+ s = metafy(lhstr + m->rm_so, m->rm_eo - m->rm_so, META_DUP);
setsparam("MATCH", s);
/*
* Count the characters before the match.
@@ -174,12 +179,16 @@ zcond_regex_match(char **a, int id)
break;
default:
DPUTS(1, "bad regex option");
- return 0; /* nothing to cleanup, especially not "re". */
+ return_value = 0;
+ goto CLEAN_BASEMETA;
}
if (matches)
zfree(matches, matchessz);
regfree(&re);
+CLEAN_BASEMETA:
+ free(lhstr);
+ free(rhre);
return return_value;
}
diff --git a/Src/Zle/zle.h b/Src/Zle/zle.h
index bedf28f17..cf44b47d2 100644
--- a/Src/Zle/zle.h
+++ b/Src/Zle/zle.h
@@ -269,6 +269,7 @@ struct change {
ZLE_STRING_T ins; /* characters to insert */
int insl; /* no. of characters in ins */
int old_cs, new_cs; /* old and new cursor positions */
+ zlong changeno; /* unique number of this change */
};
#define CH_NEXT (1<<0) /* next structure is also part of this change */
diff --git a/Src/Zle/zle_params.c b/Src/Zle/zle_params.c
index 3fdb5f8ed..a9bbf136a 100644
--- a/Src/Zle/zle_params.c
+++ b/Src/Zle/zle_params.c
@@ -93,6 +93,8 @@ static const struct gsu_integer pending_gsu =
{ get_pending, NULL, zleunsetfn };
static const struct gsu_integer region_active_gsu =
{ get_region_active, set_region_active, zleunsetfn };
+static const struct gsu_integer undo_change_no_gsu =
+{ get_undo_current_change, NULL, zleunsetfn };
static const struct gsu_array killring_gsu =
{ get_killring, set_killring, unset_killring };
@@ -133,6 +135,8 @@ static struct zleparam {
{ "RBUFFER", PM_SCALAR, GSU(rbuffer_gsu), NULL },
{ "REGION_ACTIVE", PM_INTEGER, GSU(region_active_gsu), NULL},
{ "region_highlight", PM_ARRAY, GSU(region_highlight_gsu), NULL },
+ { "UNDO_CHANGE_NO", PM_INTEGER | PM_READONLY, GSU(undo_change_no_gsu),
+ NULL },
{ "WIDGET", PM_SCALAR | PM_READONLY, GSU(widget_gsu), NULL },
{ "WIDGETFUNC", PM_SCALAR | PM_READONLY, GSU(widgetfunc_gsu), NULL },
{ "WIDGETSTYLE", PM_SCALAR | PM_READONLY, GSU(widgetstyle_gsu), NULL },
@@ -705,21 +709,17 @@ get_context(UNUSED(Param pm))
static char *
get_zle_state(UNUSED(Param pm))
{
- char *zle_state = NULL, *ptr = NULL;
+ char *zle_state = NULL, *ptr = NULL, **arr = NULL;
int itp, istate, len = 0;
/*
- * When additional substrings are added, they should be kept in
- * alphabetical order, so the user can easily match against this
- * parameter: if [[ $ZLE_STATE == *bar*foo*zonk* ]]; then ...; fi
+ * Substrings are sorted at the end, so the user can
+ * easily match against this parameter:
+ * if [[ $ZLE_STATE == *bar*foo*zonk* ]]; then ...; fi
*/
for (itp = 0; itp < 2; itp++) {
char *str;
- /*
- * Currently there is only one state: insert or overwrite.
- * This loop is to make it easy to add others.
- */
- for (istate = 0; istate < 1; istate++) {
+ for (istate = 0; istate < 2; istate++) {
int slen;
switch (istate) {
case 0:
@@ -729,6 +729,13 @@ get_zle_state(UNUSED(Param pm))
str = "overwrite";
}
break;
+ case 1:
+ if (hist_skip_flags & HIST_FOREIGN) {
+ str = "localhistory";
+ } else {
+ str = "globalhistory";
+ }
+ break;
default:
str = "";
@@ -742,7 +749,7 @@ get_zle_state(UNUSED(Param pm))
} else {
/* Accumulating string */
if (istate)
- *ptr++ = ' ';
+ *ptr++ = ':';
memcpy(ptr, str, slen);
ptr += slen;
}
@@ -755,5 +762,10 @@ get_zle_state(UNUSED(Param pm))
}
}
+ arr = colonsplit(zle_state, 0);
+ strmetasort(arr, SORTIT_ANYOLDHOW, NULL);
+ zle_state = zjoin(arr, ' ', 1);
+ freearray(arr);
+
return zle_state;
}
diff --git a/Src/Zle/zle_utils.c b/Src/Zle/zle_utils.c
index 45e30445e..cf6787f3a 100644
--- a/Src/Zle/zle_utils.c
+++ b/Src/Zle/zle_utils.c
@@ -1359,6 +1359,10 @@ static struct change *changes, *curchange;
static struct change *nextchanges, *endnextchanges;
+/* incremented to provide a unique change number */
+
+static zlong undo_changeno;
+
/**/
void
initundo(void)
@@ -1368,6 +1372,7 @@ initundo(void)
curchange->prev = curchange->next = NULL;
curchange->del = curchange->ins = NULL;
curchange->dell = curchange->insl = 0;
+ curchange->changeno = undo_changeno = 0;
lastline = zalloc((lastlinesz = linesz) * ZLE_CHAR_SIZE);
ZS_memcpy(lastline, zleline, (lastll = zlell));
lastcs = zlecs;
@@ -1492,6 +1497,7 @@ mkundoent(void)
ch->flags = 0;
ch->prev = NULL;
}
+ ch->changeno = ++undo_changeno;
endnextchanges = ch;
}
@@ -1512,8 +1518,15 @@ setlastline(void)
/**/
int
-undo(UNUSED(char **args))
+undo(char **args)
{
+ zlong last_change = (zlong)0;
+
+ if (*args)
+ {
+ last_change = zstrtol(*args, NULL, 0);
+ }
+
handleundo();
do {
if(!curchange->prev)
@@ -1522,7 +1535,8 @@ undo(UNUSED(char **args))
curchange = curchange->prev;
else
break;
- } while(curchange->flags & CH_PREV);
+ } while (*args ? curchange->changeno != last_change :
+ (curchange->flags & CH_PREV));
setlastline();
return 0;
}
@@ -1637,3 +1651,15 @@ zlecallhook(char *name, char *arg)
errflag = saverrflag;
retflag = savretflag;
}
+
+/*
+ * Return the number corresponding to the last change made.
+ */
+
+/**/
+zlong
+get_undo_current_change(UNUSED(Param pm))
+{
+ return undo_changeno;
+}
+
diff --git a/Src/builtin.c b/Src/builtin.c
index b43c08235..b5a98cbd2 100644
--- a/Src/builtin.c
+++ b/Src/builtin.c
@@ -58,7 +58,7 @@ static struct builtin builtins[] =
BUILTIN("disable", 0, bin_enable, 0, -1, BIN_DISABLE, "afmrs", NULL),
BUILTIN("disown", 0, bin_fg, 0, -1, BIN_DISOWN, NULL, NULL),
BUILTIN("echo", BINF_SKIPINVALID, bin_print, 0, -1, BIN_ECHO, "neE", "-"),
- BUILTIN("emulate", 0, bin_emulate, 0, 3, 0, "LR", NULL),
+ BUILTIN("emulate", 0, bin_emulate, 0, -1, 0, "LR", NULL),
BUILTIN("enable", 0, bin_enable, 0, -1, BIN_ENABLE, "afmrs", NULL),
BUILTIN("eval", BINF_PSPECIAL, bin_eval, 0, -1, BIN_EVAL, NULL, NULL),
BUILTIN("exit", BINF_PSPECIAL, bin_break, 0, 1, BIN_EXIT, NULL, NULL),
@@ -1498,7 +1498,7 @@ bin_fc(char *nam, char **argv, Options ops, int func)
}
if (OPT_ISSET(ops,'l')) {
/* list the required part of the history */
- retval = fclist(stdout, ops, first, last, asgf, pprog);
+ retval = fclist(stdout, ops, first, last, asgf, pprog, 0);
unqueue_signals();
}
else {
@@ -1530,7 +1530,7 @@ bin_fc(char *nam, char **argv, Options ops, int func)
}
}
ops->ind['n'] = 1; /* No line numbers here. */
- if (!fclist(out, ops, first, last, asgf, pprog)) {
+ if (!fclist(out, ops, first, last, asgf, pprog, 1)) {
char *editor;
if (func == BIN_R)
@@ -1639,7 +1639,7 @@ fcsubs(char **sp, struct asgment *sub)
/**/
static int
fclist(FILE *f, Options ops, zlong first, zlong last,
- struct asgment *subs, Patprog pprog)
+ struct asgment *subs, Patprog pprog, int is_command)
{
int fclistdone = 0;
zlong tmp;
@@ -1652,8 +1652,8 @@ fclist(FILE *f, Options ops, zlong first, zlong last,
last = first;
first = tmp;
}
- if (first > last) {
- zwarnnam("fc", "history events are in wrong order, aborted");
+ if (is_command && first > last) {
+ zwarnnam("fc", "history events can't be executed backwards, aborted");
if (f != stdout)
fclose(f);
return 1;
@@ -1976,9 +1976,10 @@ typeset_single(char *cname, char *pname, Param pm, UNUSED(int func),
tc = 0; /* but don't do a normal conversion */
}
} else if (!setsecondstype(pm, on, off)) {
- if (value && !setsparam(pname, ztrdup(value)))
+ if (value && !(pm = setsparam(pname, ztrdup(value))))
return NULL;
- return pm;
+ usepm = 1;
+ err = 0;
}
}
if (err)
@@ -3054,6 +3055,34 @@ bin_unset(char *name, char **argv, Options ops, int func)
*sse = ']';
}
paramtab = tht;
+ } else if (PM_TYPE(pm->node.flags) == PM_SCALAR ||
+ PM_TYPE(pm->node.flags) == PM_ARRAY) {
+ struct value vbuf;
+ vbuf.isarr = (PM_TYPE(pm->node.flags) == PM_ARRAY ?
+ SCANPM_ARRONLY : 0);
+ vbuf.pm = pm;
+ vbuf.flags = 0;
+ vbuf.start = 0;
+ vbuf.end = -1;
+ vbuf.arr = 0;
+ *ss = '[';
+ if (getindex(&ss, &vbuf, SCANPM_ASSIGNING) == 0 &&
+ vbuf.pm && !(vbuf.pm->node.flags & PM_UNSET)) {
+ if (PM_TYPE(pm->node.flags) == PM_SCALAR) {
+ setstrvalue(&vbuf, ztrdup(""));
+ } else {
+ /* start is after the element for reverse index */
+ int start = vbuf.start - !!(vbuf.flags & VALFLAG_INV);
+ if (start < arrlen(vbuf.pm->u.arr)) {
+ char *arr[2];
+ arr[0] = "";
+ arr[1] = 0;
+ setarrvalue(&vbuf, zarrdup(arr));
+ }
+ }
+ }
+ returnval = errflag;
+ errflag = 0;
} else {
zerrnam(name, "%s: invalid element for unset", s);
returnval = 1;
@@ -4958,14 +4987,14 @@ bin_emulate(UNUSED(char *nam), char **argv, Options ops, UNUSED(int func))
{
int opt_L = OPT_ISSET(ops, 'L');
int opt_R = OPT_ISSET(ops, 'R');
- int saveemulation, savesticky_emulation;
- int ret;
+ int saveemulation, savesticky_emulation, savehackchar;
+ int ret = 1;
char saveopts[OPT_SIZE];
+ char *cmd = 0;
+ const char *shname = *argv;
/* without arguments just print current emulation */
- if (!*argv) {
- const char *shname;
-
+ if (!shname) {
if (opt_L || opt_R) {
zwarnnam("emulate", "not enough arguments");
return 1;
@@ -4995,39 +5024,46 @@ bin_emulate(UNUSED(char *nam), char **argv, Options ops, UNUSED(int func))
/* with single argument set current emulation */
if (!argv[1]) {
- emulate(*argv, OPT_ISSET(ops,'R'));
+ emulate(shname, OPT_ISSET(ops,'R'));
if (OPT_ISSET(ops,'L'))
opts[LOCALOPTIONS] = opts[LOCALTRAPS] = 1;
return 0;
}
- /* If "-c command" is given, evaluate command using specified
- * emulation mode.
- */
- if (strcmp(argv[1], "-c")) {
- zwarnnam("emulate", "unknown argument %s", argv[1]);
- return 1;
- }
+ argv++;
+ memcpy(saveopts, opts, sizeof(opts));
+ savehackchar = keyboardhackchar;
+ cmd = parseopts("emulate", &argv);
- if (!argv[2]) {
- zwarnnam("emulate", "not enough arguments");
- return 1;
+ /* parseopts() has consumed anything that looks like an option */
+ if (*argv) {
+ zwarnnam("emulate", "unknown argument %s", *argv);
+ goto restore;
}
- if (opt_L) {
- zwarnnam("emulate", "option -L incompatible with -c");
- return 1;
- }
+ /* If "-c command" is given, evaluate command using specified
+ * emulation mode.
+ */
+ if (cmd) {
+ if (opt_L) {
+ zwarnnam("emulate", "option -L incompatible with -c");
+ goto restore;
+ }
+ *--argv = cmd; /* on stack, never free()d, see execbuiltin() */
+ } else
+ return 0;
- memcpy(saveopts, opts, sizeof(opts));
saveemulation = emulation;
savesticky_emulation = sticky_emulation;
- emulate(*argv, OPT_ISSET(ops,'R'));
+ emulate(shname, OPT_ISSET(ops,'R'));
sticky_emulation = emulation;
- ret = eval(argv+2);
- memcpy(opts, saveopts, sizeof(opts));
+ ret = eval(argv);
sticky_emulation = savesticky_emulation;
emulation = saveemulation;
+ restore:
+ memcpy(opts, saveopts, sizeof(opts));
+ keyboardhackchar = savehackchar;
+ inittyptab(); /* restore banghist */
return ret;
}
diff --git a/Src/exec.c b/Src/exec.c
index 503e0843d..6ebc9c014 100644
--- a/Src/exec.c
+++ b/Src/exec.c
@@ -1617,9 +1617,8 @@ execpline(Estate state, wordcode slcode, int how, int last1)
(list_pipe || (pline_level && !(jn->stat & STAT_SUBJOB)))))
deletejob(jn, 0);
thisjob = pj;
-
}
- if (slflags & WC_SUBLIST_NOT)
+ if ((slflags & WC_SUBLIST_NOT) && !errflag)
lastval = !lastval;
}
if (!pline_level)
@@ -1679,9 +1678,13 @@ execpline2(Estate state, wordcode pcode,
if (pipe(synch) < 0) {
zerr("pipe failed: %e", errno);
+ lastval = errflag = 1;
+ return;
} else if ((pid = zfork(&bgtime)) == -1) {
close(synch[0]);
close(synch[1]);
+ lastval = errflag = 1;
+ return;
} else if (pid) {
char dummy, *text;
@@ -2490,7 +2493,7 @@ execcmd(Estate state, int input, int output, int how, int last1)
if (!firstnode(args)) {
zerr("exec requires a command to execute");
errflag = lastval = 1;
- return;
+ goto done;
}
uremnode(args, firstnode(args));
if (!strcmp(next, "--"))
@@ -2507,12 +2510,12 @@ execcmd(Estate state, int input, int output, int how, int last1)
if (!firstnode(args)) {
zerr("exec requires a command to execute");
errflag = lastval = 1;
- return;
+ goto done;
}
if (!nextnode(firstnode(args))) {
zerr("exec flag -a requires a parameter");
errflag = lastval = 1;
- return;
+ goto done;
}
exec_argv0 = (char *)
getdata(nextnode(firstnode(args)));
@@ -2813,15 +2816,12 @@ execcmd(Estate state, int input, int output, int how, int last1)
if (pipe(synch) < 0) {
zerr("pipe failed: %e", errno);
- if (oautocont >= 0)
- opts[AUTOCONTINUE] = oautocont;
- return;
+ goto fatal;
} else if ((pid = zfork(&bgtime)) == -1) {
close(synch[0]);
close(synch[1]);
- if (oautocont >= 0)
- opts[AUTOCONTINUE] = oautocont;
- return;
+ lastval = errflag = 1;
+ goto fatal;
}
if (pid) {
@@ -3252,7 +3252,11 @@ execcmd(Estate state, int input, int output, int how, int last1)
}
if (isset(PRINTEXITVALUE) && isset(SHINSTDIN) &&
lastval && !subsh) {
+#if defined(ZLONG_IS_LONG_LONG) && defined(PRINTF_HAS_LLD)
+ fprintf(stderr, "zsh: exit %lld\n", lastval);
+#else
fprintf(stderr, "zsh: exit %ld\n", (long)lastval);
+#endif
fflush(stderr);
}
@@ -3365,6 +3369,7 @@ execcmd(Estate state, int input, int output, int how, int last1)
* classify as a builtin) we treat all errors as fatal.
* The "command" builtin is not special so resets this behaviour.
*/
+ fatal:
if (redir_err || errflag) {
if (!isset(INTERACTIVE)) {
if (forked)
diff --git a/Src/glob.c b/Src/glob.c
index d003d95da..ca2ffaf51 100644
--- a/Src/glob.c
+++ b/Src/glob.c
@@ -997,7 +997,9 @@ gmatchcmp(Gmatch a, Gmatch b)
break;
}
if (r)
- return (int) ((s->tp & GS_DESC) ? -r : r);
+ return (s->tp & GS_DESC) ?
+ (r < 0L ? 1 : -1) :
+ (r > 0L ? 1 : -1);
}
return 0;
}
@@ -2089,7 +2091,8 @@ xpandbraces(LinkList list, LinkNode *np)
char *dots, *p, *dots2 = NULL;
LinkNode olast = last;
/* Get the first number of the range */
- int rstart = zstrtol(str+1,&dots,10), rend = 0, err = 0, rev = 0, rincr = 1;
+ zlong rstart = zstrtol(str+1,&dots,10), rend = 0;
+ int err = 0, rev = 0, rincr = 1;
int wid1 = (dots - str) - 1, wid2 = (str2 - dots) - 2, wid3 = 0;
int strp = str - str3;
@@ -2134,7 +2137,7 @@ xpandbraces(LinkList list, LinkNode *np)
}
if (rstart > rend) {
/* Handle decreasing ranges correctly. */
- int rt = rend;
+ zlong rt = rend;
rend = rstart;
rstart = rt;
rev = !rev;
@@ -2147,7 +2150,11 @@ xpandbraces(LinkList list, LinkNode *np)
for (; rend >= rstart; rend -= rincr) {
/* Node added in at end, so do highest first */
p = dupstring(str3);
- sprintf(p + strp, "%0*d", minw, rend);
+#if defined(ZLONG_IS_LONG_LONG) && defined(PRINTF_HAS_LLD)
+ sprintf(p + strp, "%0*lld", minw, rend);
+#else
+ sprintf(p + strp, "%0*ld", minw, (long)rend);
+#endif
strcat(p + strp, str2 + 1);
insertlinknode(list, last, p);
if (rev) /* decreasing: add in reverse order. */
diff --git a/Src/hashtable.c b/Src/hashtable.c
index 775b6a277..be71a1cc9 100644
--- a/Src/hashtable.c
+++ b/Src/hashtable.c
@@ -664,7 +664,8 @@ hashdir(char **dirp)
* executable plain files.
*/
if (unset(HASHEXECUTABLESONLY) ||
- (stat(pathbuf, &statbuf) == 0 &&
+ (access(pathbuf, X_OK) == 0 &&
+ stat(pathbuf, &statbuf) == 0 &&
S_ISREG(statbuf.st_mode) && (statbuf.st_mode & S_IXUGO)))
add = 1;
}
diff --git a/Src/hist.c b/Src/hist.c
index 4d522dddb..0e63dca37 100644
--- a/Src/hist.c
+++ b/Src/hist.c
@@ -2225,7 +2225,8 @@ readhistline(int start, char **bufp, int *bufsiz, FILE *in)
}
else {
buf[len - 1] = '\0';
- if (len > 1 && buf[len - 2] == '\\') {
+ if (len > 1 && buf[len - 2] == '\\' &&
+ (len < 3 || buf[len - 3] != '\\')) {
buf[--len - 1] = '\n';
if (!feof(in))
return readhistline(len, bufp, bufsiz, in);
diff --git a/Src/init.c b/Src/init.c
index 9820070fb..6f14943e1 100644
--- a/Src/init.c
+++ b/Src/init.c
@@ -215,6 +215,7 @@ loop(int toplevel, int justonce)
return LOOP_OK;
}
+/* Shared among parseargs(), parseopts(), init_io(), and init_misc() */
static char *cmd;
static int restricted;
@@ -222,9 +223,7 @@ static int restricted;
static void
parseargs(char **argv, char **runscript)
{
- int optionbreak = 0;
char **x;
- int action, optno;
LinkList paramlist;
argzero = *argv++;
@@ -247,6 +246,49 @@ parseargs(char **argv, char **runscript)
opts[SHINSTDIN] = 0;
opts[SINGLECOMMAND] = 0;
+ cmd = parseopts(NULL, &argv);
+
+ paramlist = znewlinklist();
+ if (*argv) {
+ if (unset(SHINSTDIN)) {
+ if (cmd)
+ argzero = *argv;
+ else
+ *runscript = *argv;
+ opts[INTERACTIVE] &= 1;
+ argv++;
+ }
+ while (*argv)
+ zaddlinknode(paramlist, ztrdup(*argv++));
+ } else if (!cmd)
+ opts[SHINSTDIN] = 1;
+ if(isset(SINGLECOMMAND))
+ opts[INTERACTIVE] &= 1;
+ opts[INTERACTIVE] = !!opts[INTERACTIVE];
+ if (opts[MONITOR] == 2)
+ opts[MONITOR] = opts[INTERACTIVE];
+ if (opts[HASHDIRS] == 2)
+ opts[HASHDIRS] = opts[INTERACTIVE];
+ pparams = x = (char **) zshcalloc((countlinknodes(paramlist) + 1) * sizeof(char *));
+
+ while ((*x++ = (char *)getlinknode(paramlist)));
+ free(paramlist);
+ argzero = ztrdup(argzero);
+}
+
+/**/
+mod_export char *
+parseopts(char *nam, char ***argvp)
+{
+ int optionbreak = 0;
+ int action, optno;
+ char *cmd = 0; /* deliberately hides static */
+ char **argv = *argvp;
+
+#define WARN_OPTION(F, S) if (nam) zwarnnam(nam, F, S); else zerr(F, S)
+#define LAST_OPTION(N) \
+ if (nam) { if (*argv) argv++; goto doneargv; } else exit(N)
+
/* loop through command line options (begins with "-" or "+") */
while (!optionbreak && *argv && (**argv == '-' || **argv == '+')) {
char *args = *argv;
@@ -267,11 +309,11 @@ parseargs(char **argv, char **runscript)
if (!strcmp(*argv, "version")) {
printf("zsh %s (%s-%s-%s)\n",
ZSH_VERSION, MACHTYPE, VENDOR, OSTYPE);
- exit(0);
+ LAST_OPTION(0);
}
if (!strcmp(*argv, "help")) {
printhelp();
- exit(0);
+ LAST_OPTION(0);
}
/* `-' characters are allowed in long options */
for(args = *argv; *args; args++)
@@ -292,75 +334,58 @@ parseargs(char **argv, char **runscript)
if (!*++*argv)
argv++;
if (!*argv) {
- zerr("string expected after -o");
- exit(1);
+ WARN_OPTION("string expected after -o", NULL);
+ LAST_OPTION(1);
}
longoptions:
if (!(optno = optlookup(*argv))) {
- zerr("no such option: %s", *argv);
- exit(1);
- } else if (optno == RESTRICTED)
+ WARN_OPTION("no such option: %s", *argv);
+ LAST_OPTION(1);
+ } else if (optno == RESTRICTED && !nam) {
restricted = action;
- else
- dosetopt(optno, action, 1);
+ } else if ((optno == EMACSMODE || optno == VIMODE) && nam) {
+ WARN_OPTION("can't change option: %s", *argv);
+ } else if (dosetopt(optno, action, !nam) && nam) {
+ WARN_OPTION("can't change option: %s", *argv);
+ }
break;
} else if (isspace(STOUC(**argv))) {
/* zsh's typtab not yet set, have to use ctype */
while (*++*argv)
if (!isspace(STOUC(**argv))) {
- badoptionstring:
- zerr("bad option string: `%s'", args);
- exit(1);
+ badoptionstring:
+ WARN_OPTION("bad option string: '%s'", args);
+ LAST_OPTION(1);
}
break;
} else {
if (!(optno = optlookupc(**argv))) {
- zerr("bad option: -%c", **argv);
- exit(1);
- } else if (optno == RESTRICTED)
+ WARN_OPTION("bad option: -%c", **argv);
+ LAST_OPTION(1);
+ } else if (optno == RESTRICTED && !nam) {
restricted = action;
- else
- dosetopt(optno, action, 1);
+ } else if ((optno == EMACSMODE || optno == VIMODE) && nam) {
+ WARN_OPTION("can't change option: %s", *argv);
+ } else if (dosetopt(optno, action, !nam) && nam) {
+ WARN_OPTION("can't change option: -%c", **argv);
+ }
}
}
argv++;
}
- doneoptions:
- paramlist = znewlinklist();
+ doneoptions:
if (cmd) {
if (!*argv) {
- zerr("string expected after -%s", cmd);
- exit(1);
+ WARN_OPTION("string expected after -%s", cmd);
+ LAST_OPTION(1);
}
cmd = *argv++;
}
- if (*argv) {
- if (unset(SHINSTDIN)) {
- if (cmd)
- argzero = *argv;
- else
- *runscript = *argv;
- opts[INTERACTIVE] &= 1;
- argv++;
- }
- while (*argv)
- zaddlinknode(paramlist, ztrdup(*argv++));
- } else if (!cmd)
- opts[SHINSTDIN] = 1;
- if(isset(SINGLECOMMAND))
- opts[INTERACTIVE] &= 1;
- opts[INTERACTIVE] = !!opts[INTERACTIVE];
- if (opts[MONITOR] == 2)
- opts[MONITOR] = opts[INTERACTIVE];
- if (opts[HASHDIRS] == 2)
- opts[HASHDIRS] = opts[INTERACTIVE];
- pparams = x = (char **) zshcalloc((countlinknodes(paramlist) + 1) * sizeof(char *));
-
- while ((*x++ = (char *)getlinknode(paramlist)));
- free(paramlist);
- argzero = ztrdup(argzero);
+ doneargv:
+ *argvp = argv;
+ return cmd;
}
-
+
/**/
static void
printhelp(void)
diff --git a/Src/jobs.c b/Src/jobs.c
index 94d25bb85..c9c549e1e 100644
--- a/Src/jobs.c
+++ b/Src/jobs.c
@@ -716,17 +716,22 @@ printtime(struct timeval *real, child_times_t *ti, char *desc)
#endif
#ifdef HAVE_STRUCT_RUSAGE_RU_IXRSS
case 'X':
- fprintf(stderr, "%ld", (long)(ti->ru_ixrss / total_time));
+ fprintf(stderr, "%ld",
+ total_time ?
+ (long)(ti->ru_ixrss / total_time) :
+ (long)0);
break;
#endif
#ifdef HAVE_STRUCT_RUSAGE_RU_IDRSS
case 'D':
fprintf(stderr, "%ld",
+ total_time ?
(long) ((ti->ru_idrss
#ifdef HAVE_STRUCT_RUSAGE_RU_ISRSS
+ ti->ru_isrss
#endif
- ) / total_time));
+ ) / total_time) :
+ (long)0);
break;
#endif
#if defined(HAVE_STRUCT_RUSAGE_RU_IDRSS) || \
@@ -735,6 +740,7 @@ printtime(struct timeval *real, child_times_t *ti, char *desc)
case 'K':
/* treat as D if X not available */
fprintf(stderr, "%ld",
+ total_time ?
(long) ((
#ifdef HAVE_STRUCT_RUSAGE_RU_IXRSS
ti->ru_ixrss
@@ -747,7 +753,8 @@ printtime(struct timeval *real, child_times_t *ti, char *desc)
#ifdef HAVE_STRUCT_RUSAGE_RU_ISRSS
+ ti->ru_isrss
#endif
- ) / total_time));
+ ) / total_time) :
+ (long)0);
break;
#endif
#ifdef HAVE_STRUCT_RUSAGE_RU_MAXRSS
@@ -2157,10 +2164,15 @@ bin_kill(char *nam, char **argv, UNUSED(Options ops), UNUSED(int func))
/* check for, and interpret, a signal specifier */
if (*argv && **argv == '-') {
- if (idigit((*argv)[1]))
+ if (idigit((*argv)[1])) {
+ char *endp;
/* signal specified by number */
- sig = atoi(*argv + 1);
- else if ((*argv)[1] != '-' || (*argv)[2]) {
+ sig = zstrtol(*argv + 1, &endp, 10);
+ if (*endp) {
+ zwarnnam(nam, "invalid signal number: %s", *argv);
+ return 1;
+ }
+ } else if ((*argv)[1] != '-' || (*argv)[2]) {
char *signame;
/* with argument "-l" display the list of signal names */
diff --git a/Src/options.c b/Src/options.c
index 5fbb06b11..c6db75372 100644
--- a/Src/options.c
+++ b/Src/options.c
@@ -523,6 +523,20 @@ emulate(const char *zsh_name, int fully)
if (fully)
emulation |= EMULATE_FULLY;
installemulation();
+
+ if (funcstack && funcstack->tp == FS_FUNC) {
+ /*
+ * We are inside a function. Decide if it's traced.
+ * Pedantic note: the function in the function table isn't
+ * guaranteed to be what we're executing, but it's
+ * close enough.
+ */
+ Shfunc shf = (Shfunc)shfunctab->getnode(shfunctab, funcstack->name);
+ if (shf && (shf->node.flags & PM_TAGGED)) {
+ /* Tracing is on, so set xtrace */
+ opts[XTRACE] = 1;
+ }
+ }
}
/* setopt, unsetopt */
@@ -753,6 +767,8 @@ dosetopt(int optno, int value, int force)
return -1;
#endif /* GETPWNAM_FAKED */
} else if ((optno == EMACSMODE || optno == VIMODE) && value) {
+ if (sticky_emulation)
+ return -1;
zleentry(ZLE_CMD_SET_KEYMAP, optno);
opts[(optno == EMACSMODE) ? VIMODE : EMACSMODE] = 0;
} else if (optno == SUNKEYBOARDHACK) {
diff --git a/Src/params.c b/Src/params.c
index 59d5daf2f..8649178ef 100644
--- a/Src/params.c
+++ b/Src/params.c
@@ -315,7 +315,7 @@ IPDEF4("LINENO", &lineno),
IPDEF4("PPID", &ppid),
IPDEF4("ZSH_SUBSHELL", &zsh_subshell),
-#define IPDEF5(A,B,F) {{NULL,A,PM_INTEGER|PM_SPECIAL},BR((void *)B),GSU(varinteger_gsu),10,0,NULL,NULL,NULL,0}
+#define IPDEF5(A,B,F) {{NULL,A,PM_INTEGER|PM_SPECIAL},BR((void *)B),GSU(F),10,0,NULL,NULL,NULL,0}
IPDEF5("COLUMNS", &zterm_columns, zlevar_gsu),
IPDEF5("LINES", &zterm_lines, zlevar_gsu),
IPDEF5("OPTIND", &zoptind, varinteger_gsu),
@@ -698,16 +698,18 @@ createparamtable(void)
* So allow the user to set it in the special cases where it's
* useful.
*/
- setsparam("TMPPREFIX", ztrdup(DEFAULT_TMPPREFIX));
- setsparam("TIMEFMT", ztrdup(DEFAULT_TIMEFMT));
- setsparam("WATCHFMT", ztrdup(default_watchfmt));
+ setsparam("TMPPREFIX", ztrdup_metafy(DEFAULT_TMPPREFIX));
+ setsparam("TIMEFMT", ztrdup_metafy(DEFAULT_TIMEFMT));
+ setsparam("WATCHFMT", ztrdup_metafy(default_watchfmt));
hostnam = (char *)zalloc(256);
gethostname(hostnam, 256);
- setsparam("HOST", ztrdup(hostnam));
+ setsparam("HOST", ztrdup_metafy(hostnam));
zfree(hostnam, 256);
- setsparam("LOGNAME", ztrdup((str = getlogin()) && *str ? str : cached_username));
+ setsparam("LOGNAME",
+ ztrdup_metafy((str = getlogin()) && *str ?
+ str : cached_username));
#if !defined(HAVE_PUTENV) && !defined(USE_SET_UNSET_ENV)
/* Copy the environment variables we are inheriting to dynamic *
@@ -778,22 +780,22 @@ createparamtable(void)
if(uname(&unamebuf)) setsparam("CPUTYPE", ztrdup("unknown"));
else
{
- machinebuf = ztrdup(unamebuf.machine);
+ machinebuf = ztrdup_metafy(unamebuf.machine);
setsparam("CPUTYPE", machinebuf);
}
-
+
#else
- setsparam("CPUTYPE", ztrdup("unknown"));
+ setsparam("CPUTYPE", ztrdup_metafy("unknown"));
#endif
- setsparam("MACHTYPE", ztrdup(MACHTYPE));
- setsparam("OSTYPE", ztrdup(OSTYPE));
- setsparam("TTY", ztrdup(ttystrname));
- setsparam("VENDOR", ztrdup(VENDOR));
- setsparam("ZSH_NAME", ztrdup(zsh_name));
- setsparam("ZSH_VERSION", ztrdup(ZSH_VERSION));
- setsparam("ZSH_PATCHLEVEL", ztrdup(ZSH_PATCHLEVEL));
+ setsparam("MACHTYPE", ztrdup_metafy(MACHTYPE));
+ setsparam("OSTYPE", ztrdup_metafy(OSTYPE));
+ setsparam("TTY", ztrdup_metafy(ttystrname));
+ setsparam("VENDOR", ztrdup_metafy(VENDOR));
+ setsparam("ZSH_NAME", ztrdup_metafy(zsh_name));
+ setsparam("ZSH_VERSION", ztrdup_metafy(ZSH_VERSION));
+ setsparam("ZSH_PATCHLEVEL", ztrdup_metafy(ZSH_PATCHLEVEL));
setaparam("signals", sigptr = zalloc((SIGCOUNT+4) * sizeof(char *)));
- for (t = sigs; (*sigptr++ = ztrdup(*t++)); );
+ for (t = sigs; (*sigptr++ = ztrdup_metafy(*t++)); );
noerrs = 0;
}
@@ -1903,6 +1905,18 @@ fetchvalue(Value v, char **pptr, int bracks, int flags)
if (!bracks && *s)
return NULL;
*pptr = s;
+#if 0
+ /*
+ * Check for large subscripts that might be erroneous.
+ * This code is too gross in several ways:
+ * - the limit is completely arbitrary
+ * - the test vetoes operations on existing arrays
+ * - it's not at all clear a general test on large arrays of
+ * this kind is any use.
+ *
+ * Until someone comes up with workable replacement code it's
+ * therefore commented out.
+ */
if (v->start > MAX_ARRLEN) {
zerr("subscript too %s: %d", "big", v->start + !isset(KSHARRAYS));
return NULL;
@@ -1919,6 +1933,7 @@ fetchvalue(Value v, char **pptr, int bracks, int flags)
zerr("subscript too %s: %d", "small", v->end);
return NULL;
}
+#endif
return v;
}
@@ -3454,18 +3469,104 @@ tiedarrunsetfn(Param pm, UNUSED(int exp))
/**/
static void
-arrayuniq(char **x, int freeok)
+simple_arrayuniq(char **x, int freeok)
{
char **t, **p = x;
+ char *hole = "";
+ /* Find duplicates and replace them with holes */
while (*++p)
for (t = x; t < p; t++)
- if (!strcmp(*p, *t)) {
+ if (*t != hole && !strcmp(*p, *t)) {
if (freeok)
zsfree(*p);
- for (t = p--; (*t = t[1]) != NULL; t++);
+ *p = hole;
break;
}
+ /* Swap non-holes into holes in optimal jumps */
+ for (p = t = x; *t != NULL; t++) {
+ if (*t == hole) {
+ while (*p == hole)
+ ++p;
+ if ((*t = *p) != NULL)
+ *p++ = hole;
+ } else if (p == t)
+ p++;
+ }
+ /* Erase all the remaining holes, just in case */
+ while (++t < p)
+ *t = NULL;
+}
+
+/**/
+static void
+arrayuniq_freenode(HashNode hn)
+{
+ (void)hn;
+}
+
+/**/
+HashTable
+newuniqtable(zlong size)
+{
+ HashTable ht = newhashtable((int)size, "arrayuniq", NULL);
+ /* ??? error checking */
+
+ ht->hash = hasher;
+ ht->emptytable = emptyhashtable;
+ ht->filltable = NULL;
+ ht->cmpnodes = strcmp;
+ ht->addnode = addhashnode;
+ ht->getnode = gethashnode2;
+ ht->getnode2 = gethashnode2;
+ ht->removenode = removehashnode;
+ ht->disablenode = disablehashnode;
+ ht->enablenode = enablehashnode;
+ ht->freenode = arrayuniq_freenode;
+ ht->printnode = NULL;
+
+ return ht;
+}
+
+/**/
+static void
+arrayuniq(char **x, int freeok)
+{
+ char **it, **write_it;
+ zlong array_size = arrlen(x);
+ HashTable ht;
+
+ if (array_size == 0)
+ return;
+ if (array_size < 10 || !(ht = newuniqtable(array_size + 1))) {
+ /* fallback to simpler routine */
+ simple_arrayuniq(x, freeok);
+ return;
+ }
+
+ for (it = x, write_it = x; *it;) {
+ if (! gethashnode2(ht, *it)) {
+ HashNode new_node = zhalloc(sizeof(struct hashnode));
+ if (!new_node) {
+ /* Oops, out of heap memory, no way to recover */
+ zerr("out of memory in arrayuniq");
+ break;
+ }
+ (void) addhashnode2(ht, *it, new_node);
+ *write_it = *it;
+ if (it != write_it)
+ *it = NULL;
+ ++write_it;
+ }
+ else {
+ if (freeok)
+ zsfree(*it);
+ *it = NULL;
+ }
+ ++it;
+ }
+
+ deletehashtable(ht);
}
/**/
diff --git a/Src/prompt.c b/Src/prompt.c
index d15b7c0d4..e51ce2451 100644
--- a/Src/prompt.c
+++ b/Src/prompt.c
@@ -663,12 +663,20 @@ putpromptchar(int doprint, int endchar, unsigned int *txtchangep)
break;
case 'L':
addbufspc(DIGBUFSIZE);
+#if defined(ZLONG_IS_LONG_LONG) && defined(PRINTF_HAS_LLD)
+ sprintf(bv->bp, "%lld", shlvl);
+#else
sprintf(bv->bp, "%ld", (long)shlvl);
+#endif
bv->bp += strlen(bv->bp);
break;
case '?':
addbufspc(DIGBUFSIZE);
+#if defined(ZLONG_IS_LONG_LONG) && defined(PRINTF_HAS_LLD)
+ sprintf(bv->bp, "%lld", lastval);
+#else
sprintf(bv->bp, "%ld", (long)lastval);
+#endif
bv->bp += strlen(bv->bp);
break;
case '%':
@@ -764,7 +772,11 @@ putpromptchar(int doprint, int endchar, unsigned int *txtchangep)
if (funcstack->tp == FS_EVAL)
lineno--;
addbufspc(DIGBUFSIZE);
+#if defined(ZLONG_IS_LONG_LONG) && defined(PRINTF_HAS_LLD)
+ sprintf(bv->bp, "%lld", flineno);
+#else
sprintf(bv->bp, "%ld", (long)flineno);
+#endif
bv->bp += strlen(bv->bp);
break;
}
@@ -772,7 +784,11 @@ putpromptchar(int doprint, int endchar, unsigned int *txtchangep)
/* FALLTHROUGH */
case 'i':
addbufspc(DIGBUFSIZE);
+#if defined(ZLONG_IS_LONG_LONG) && defined(PRINTF_HAS_LLD)
+ sprintf(bv->bp, "%lld", lineno);
+#else
sprintf(bv->bp, "%ld", (long)lineno);
+#endif
bv->bp += strlen(bv->bp);
break;
case 'x':
diff --git a/Src/subst.c b/Src/subst.c
index b9229861b..932f41287 100644
--- a/Src/subst.c
+++ b/Src/subst.c
@@ -1649,7 +1649,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags)
* This is one of the things that decides whether multsub
* will produce an array, but in an extremely indirect fashion.
*/
- int nojoin = (pf_flags & PREFORK_SHWORDSPLIT) ? !(ifs && *ifs) : 0;
+ int nojoin = (pf_flags & PREFORK_SHWORDSPLIT) ? !(ifs && *ifs) && !qt : 0;
/*
* != 0 means ${...}, otherwise $... What works without braces
* is largely a historical artefact (everything works with braces,
@@ -1828,6 +1828,10 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags)
quotemod = 1;
quotetype = QT_SINGLE_OPTIONAL;
} else {
+ if (quotetype == QT_SINGLE_OPTIONAL) {
+ /* extra q's after '-' not allowed */
+ goto flagerr;
+ }
quotemod++, quotetype++;
}
break;
@@ -2872,6 +2876,69 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags)
}
break;
}
+ } else if (inbrace && (*s == '|' || *s == Bar ||
+ *s == '*' || *s == Star)) {
+ int intersect = (*s == '*' || *s == Star);
+ char **compare, **ap, **apsrc;
+ ++s;
+ if (*itype_end(s, IIDENT, 0)) {
+ untokenize(s);
+ zerr("not an identifier: %s", s);
+ return NULL;
+ }
+ compare = getaparam(s);
+ if (compare) {
+ HashTable ht = newuniqtable(arrlen(compare)+1);
+ int present;
+ for (ap = compare; *ap; ap++)
+ (void)addhashnode2(ht, *ap, (HashNode)
+ zhalloc(sizeof(struct hashnode)));
+ if (!vunset && isarr) {
+ if (!copied) {
+ aval = arrdup(aval);
+ copied = 1;
+ }
+ for (ap = apsrc = aval; *apsrc; apsrc++) {
+ untokenize(*apsrc);
+ present = (gethashnode2(ht, *apsrc) != NULL);
+ if (intersect ? present : !present) {
+ if (ap != apsrc) {
+ *ap = *apsrc;
+ }
+ ap++;
+ }
+ }
+ *ap = NULL;
+ } else {
+ if (vunset) {
+ if (unset(UNSET)) {
+ *idend = '\0';
+ zerr("%s: parameter not set", idbeg);
+ deletehashtable(ht);
+ return NULL;
+ }
+ val = dupstring("");
+ } else {
+ present = (gethashnode2(ht, val) != NULL);
+ if (intersect ? !present : present)
+ val = dupstring("");
+ }
+ }
+ deletehashtable(ht);
+ } else if (intersect) {
+ /*
+ * The intersection with nothing is nothing...
+ * Seems a bit pointless complaining that the first
+ * expression is unset here if the second is, too.
+ */
+ if (!vunset) {
+ if (isarr) {
+ aval = mkarray(NULL);
+ } else {
+ val = dupstring("");
+ }
+ }
+ }
} else { /* no ${...=...} or anything, but possible modifiers. */
/*
* Handler ${+...}. TODO: strange, why do we handle this only
diff --git a/Src/utils.c b/Src/utils.c
index 014cb2fa2..d35ca1dfd 100644
--- a/Src/utils.c
+++ b/Src/utils.c
@@ -275,9 +275,13 @@ zerrmsg(FILE *file, const char *fmt, va_list ap)
#endif
char *errmsg;
- if ((unset(SHINSTDIN) || locallevel) && lineno)
+ if ((unset(SHINSTDIN) || locallevel) && lineno) {
+#if defined(ZLONG_IS_LONG_LONG) && defined(PRINTF_HAS_LLD)
+ fprintf(file, "%lld: ", lineno);
+#else
fprintf(file, "%ld: ", (long)lineno);
- else
+#endif
+ } else
fputc((unsigned char)' ', file);
while (*fmt)
@@ -1682,7 +1686,7 @@ adjustwinsize(int from)
(shttyinfo.winsize.ws_row != ttyrows ||
shttyinfo.winsize.ws_col != ttycols)) {
/* shttyinfo.winsize is already set up correctly */
- ioctl(SHTTY, TIOCSWINSZ, (char *)&shttyinfo.winsize);
+ /* ioctl(SHTTY, TIOCSWINSZ, (char *)&shttyinfo.winsize); */
}
#endif /* TIOCGWINSZ */
@@ -3110,7 +3114,7 @@ wordcount(char *s, char *sep, int mul)
r = 1;
sl = strlen(sep);
for (; (c = findsep(&s, sep, 0)) >= 0; s += sl)
- if ((c && *(s + sl)) || mul)
+ if ((c || mul) && (sl || *(s + sl)))
r++;
} else {
char *t = s;
@@ -4009,6 +4013,28 @@ metafy(char *buf, int len, int heap)
/*
+ * Duplicate a string, metafying it as we go.
+ *
+ * Typically, this is used only for strings imported from outside
+ * zsh, as strings internally are either already metafied or passed
+ * around with an associated length.
+ */
+/**/
+mod_export char *
+ztrdup_metafy(const char *s)
+{
+ /* To mimic ztrdup() behaviour */
+ if (!s)
+ return NULL;
+ /*
+ * metafy() does lots of different things, so the pointer
+ * isn't const. Using it with META_DUP should be safe.
+ */
+ return metafy((char *)s, -1, META_DUP);
+}
+
+
+/*
* Take a null-terminated, metafied string in s into a literal
* representation by converting in place. The length is in *len
* len is non-NULL; if len is NULL, you don't know the length of
@@ -4709,7 +4735,7 @@ quotestring(const char *s, char **e, int instring)
char *v;
int alloclen;
char *buf;
- int sf = 0, shownull;
+ int sf = 0, shownull = 0;
/*
* quotesub is used with QT_SINGLE_OPTIONAL.
* quotesub = 0: mechanism not active
@@ -4724,14 +4750,12 @@ quotestring(const char *s, char **e, int instring)
const char *uend;
slen = strlen(s);
- if (instring == QT_BACKSLASH_SHOWNULL) {
- shownull = 1;
- instring = QT_BACKSLASH;
- } else {
- shownull = 0;
- }
switch (instring)
{
+ case QT_BACKSLASH_SHOWNULL:
+ shownull = 1;
+ instring = QT_BACKSLASH;
+ /*FALLTHROUGH*/
case QT_BACKSLASH:
/*
* With QT_BACKSLASH we may need to use $'\300' stuff.
@@ -4739,22 +4763,23 @@ quotestring(const char *s, char **e, int instring)
* storage and using heap for correct size at end.
*/
alloclen = slen * 7 + 1;
- if (!*s && shownull)
- alloclen += 2; /* for '' */
break;
case QT_SINGLE_OPTIONAL:
/*
* Here, we may need to add single quotes.
+ * Always show empty strings.
*/
alloclen = slen * 4 + 3;
- quotesub = 1;
+ quotesub = shownull = 1;
break;
default:
alloclen = slen * 4 + 1;
break;
}
+ if (!*s && shownull)
+ alloclen += 2; /* for '' */
quotestart = v = buf = zshcalloc(alloclen);
diff --git a/Src/zsh_system.h b/Src/zsh_system.h
index f38533023..f20a7bb90 100644
--- a/Src/zsh_system.h
+++ b/Src/zsh_system.h
@@ -874,3 +874,7 @@ extern short ospeed;
# endif
# endif
#endif
+
+#ifdef TGOTO_PROTO_MISSING
+char *tgoto(const char *cap, int col, int row);
+#endif