From 10c5f95f52e449242170b17cd053c3ff8447e64a Mon Sep 17 00:00:00 2001 From: "Barton E. Schaefer" Date: Tue, 26 Jan 2016 18:17:24 -0800 Subject: 37785: skip autoload parameters for "typeset -p" --- Src/params.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'Src/params.c') diff --git a/Src/params.c b/Src/params.c index b2e889738..a1f0292cc 100644 --- a/Src/params.c +++ b/Src/params.c @@ -5258,7 +5258,8 @@ printparamnode(HashNode hn, int printflags) if (printflags & PRINT_TYPESET) { if ((p->node.flags & (PM_READONLY|PM_SPECIAL)) == - (PM_READONLY|PM_SPECIAL)) { + (PM_READONLY|PM_SPECIAL) || + (p->node.flags & PM_AUTOLOAD)) { /* * It's not possible to restore the state of * these, so don't output. -- cgit v1.2.3 From a4020e10a33f3f78681a2e18fb7add56338d4e81 Mon Sep 17 00:00:00 2001 From: Jun-ichi Takimoto Date: Wed, 3 Feb 2016 01:24:56 +0900 Subject: 37868: add 'static' to file local variables --- ChangeLog | 8 ++++++++ Src/Modules/curses.c | 2 +- Src/Modules/param_private.c | 10 +++++----- Src/Modules/tcp.c | 2 +- Src/Modules/termcap.c | 2 +- Src/Modules/zftp.c | 8 ++++---- Src/Zle/complist.c | 2 +- Src/Zle/zle_misc.c | 2 +- Src/Zle/zle_utils.c | 4 ++-- Src/cond.c | 3 ++- Src/exec.c | 2 -- Src/glob.c | 2 +- Src/jobs.c | 6 +++--- Src/params.c | 2 +- Src/prompt.c | 2 +- Src/utils.c | 4 ++-- 16 files changed, 34 insertions(+), 27 deletions(-) (limited to 'Src/params.c') diff --git a/ChangeLog b/ChangeLog index d4adbe886..a8e76e238 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2016-02-03 Jun-ichi Takimoto + + * 37868: Src/Modules/curses.c, Src/Modules/param_private.c, + Src/Modules/tcp.c, Src/Modules/termcap.c, Src/Modules/zftp.c, + Src/Zle/complist.c, Src/Zle/zle_misc.c, Src/Zle/zle_utils.c, + Src/cond.c, Src/exec.c, Src/glob.c, Src/jobs.c, Src/params.c, + Src/prompt.c, Src/utils.c: add 'static' to file local variables. + 2016-01-31 Barton E. Schaefer * 37859: Src/text.c: NULL-terminate cond_binary_ops static array. diff --git a/Src/Modules/curses.c b/Src/Modules/curses.c index b8a79ed11..a04841a85 100644 --- a/Src/Modules/curses.c +++ b/Src/Modules/curses.c @@ -202,7 +202,7 @@ static const struct zcurses_mouse_event zcurses_mouse_map[] = { { 0, 0, 0 } }; -mmask_t zcurses_mouse_mask = ALL_MOUSE_EVENTS; +static mmask_t zcurses_mouse_mask = ALL_MOUSE_EVENTS; #endif diff --git a/Src/Modules/param_private.c b/Src/Modules/param_private.c index 2f51cb099..86416c5c5 100644 --- a/Src/Modules/param_private.c +++ b/Src/Modules/param_private.c @@ -42,19 +42,19 @@ struct gsu_closure { void *g; }; -const struct gsu_scalar scalar_private_gsu = +static const struct gsu_scalar scalar_private_gsu = { pps_getfn, pps_setfn, pps_unsetfn }; -const struct gsu_integer integer_private_gsu = +static const struct gsu_integer integer_private_gsu = { ppi_getfn, ppi_setfn, ppi_unsetfn }; -const struct gsu_float float_private_gsu = +static const struct gsu_float float_private_gsu = { ppf_getfn, ppf_setfn, ppf_unsetfn }; -const struct gsu_array array_private_gsu = +static const struct gsu_array array_private_gsu = { ppa_getfn, ppa_setfn, ppa_unsetfn }; -const struct gsu_hash hash_private_gsu = +static const struct gsu_hash hash_private_gsu = { pph_getfn, pph_setfn, pph_unsetfn }; /* diff --git a/Src/Modules/tcp.c b/Src/Modules/tcp.c index 5af68834f..dec12142b 100644 --- a/Src/Modules/tcp.c +++ b/Src/Modules/tcp.c @@ -208,7 +208,7 @@ freehostent(UNUSED(struct hostent *ptr)) /**/ #endif /* !HAVE_GETIPNODEBYNAME */ -LinkList ztcp_sessions; +static LinkList ztcp_sessions; /* "allocate" a tcp_session */ static Tcp_session diff --git a/Src/Modules/termcap.c b/Src/Modules/termcap.c index 29c28360c..60a6e138a 100644 --- a/Src/Modules/termcap.c +++ b/Src/Modules/termcap.c @@ -295,7 +295,7 @@ scantermcap(UNUSED(HashTable ht), ScanFunc func, int flags) } } -struct paramdef partab[] = { +static struct paramdef partab[] = { SPECIALPMDEF("termcap", PM_READONLY, NULL, gettermcap, scantermcap) }; diff --git a/Src/Modules/zftp.c b/Src/Modules/zftp.c index b4081df5f..deed35e2f 100644 --- a/Src/Modules/zftp.c +++ b/Src/Modules/zftp.c @@ -344,10 +344,10 @@ static int zfsesscnt; */ /* flags for alarm set, alarm gone off */ -int zfalarmed, zfdrrrring; +static int zfalarmed, zfdrrrring; /* remember old alarm status */ -time_t oaltime; -unsigned int oalremain; +static time_t oaltime; +static unsigned int oalremain; /* * Where to jump to when the alarm goes off. This is much @@ -357,7 +357,7 @@ unsigned int oalremain; * * gcc -O gives apparently spurious `may be clobbered by longjmp' warnings. */ -jmp_buf zfalrmbuf; +static jmp_buf zfalrmbuf; /* The signal handler itself */ diff --git a/Src/Zle/complist.c b/Src/Zle/complist.c index 0ccb88505..06a07a4e8 100644 --- a/Src/Zle/complist.c +++ b/Src/Zle/complist.c @@ -113,7 +113,7 @@ static Cmgroup *mgtab, *mgtabp; * Allow us to keep track of pointer arithmetic for mgtab; could * just as well have been for mtab but wasn't. */ -int mgtabsize; +static int mgtabsize; #endif /* diff --git a/Src/Zle/zle_misc.c b/Src/Zle/zle_misc.c index 0483f758d..25f65b39c 100644 --- a/Src/Zle/zle_misc.c +++ b/Src/Zle/zle_misc.c @@ -1497,7 +1497,7 @@ struct suffixset { }; /* The list of suffix structures */ -struct suffixset *suffixlist; +static struct suffixset *suffixlist; /* Shell function to call to remove the suffix. */ diff --git a/Src/Zle/zle_utils.c b/Src/Zle/zle_utils.c index a2c88102a..68794c66a 100644 --- a/Src/Zle/zle_utils.c +++ b/Src/Zle/zle_utils.c @@ -587,7 +587,7 @@ struct zle_position { }; /* LIFO stack of positions */ -struct zle_position *zle_positions; +static struct zle_position *zle_positions; /* * Save positions including cursor, end-of-line and @@ -1412,7 +1412,7 @@ zlong undo_changeno; /* If positive, don't undo beyond this point */ -zlong undo_limitno; +static zlong undo_limitno; /**/ void diff --git a/Src/cond.c b/Src/cond.c index c5ab65eea..0381fe94b 100644 --- a/Src/cond.c +++ b/Src/cond.c @@ -30,7 +30,8 @@ #include "zsh.mdh" #include "cond.pro" -int tracingcond; +/**/ +int tracingcond; /* updated by execcond() in exec.c */ static char *condstr[COND_MOD] = { "!", "&&", "||", "==", "!=", "<", ">", "-nt", "-ot", "-ef", "-eq", diff --git a/Src/exec.c b/Src/exec.c index 352615c83..b60fc90bd 100644 --- a/Src/exec.c +++ b/Src/exec.c @@ -4518,8 +4518,6 @@ spawnpipes(LinkList l, int nullexec) } } -extern int tracingcond; - /* evaluate a [[ ... ]] */ /**/ diff --git a/Src/glob.c b/Src/glob.c index 69de15544..2051016ec 100644 --- a/Src/glob.c +++ b/Src/glob.c @@ -306,7 +306,7 @@ statfullpath(const char *s, struct stat *st, int l) /* This may be set by qualifier functions to an array of strings to insert * into the list instead of the original string. */ -char **inserts; +static char **inserts; /* add a match to the list */ diff --git a/Src/jobs.c b/Src/jobs.c index b47ba8c60..2a9dbe7d6 100644 --- a/Src/jobs.c +++ b/Src/jobs.c @@ -1970,9 +1970,9 @@ struct bgstatus { }; typedef struct bgstatus *Bgstatus; /* The list of those entries */ -LinkList bgstatus_list; +static LinkList bgstatus_list; /* Count of entries. Reaches value of _SC_CHILD_MAX and stops. */ -long bgstatus_count; +static long bgstatus_count; /* * Remove and free a bgstatus entry. @@ -2372,7 +2372,7 @@ bin_fg(char *name, char **argv, Options ops, int func) return retval; } -const struct { +static const struct { const char *name; int num; } alt_sigs[] = { diff --git a/Src/params.c b/Src/params.c index a1f0292cc..76ed61c39 100644 --- a/Src/params.c +++ b/Src/params.c @@ -416,7 +416,7 @@ IPDEF10("pipestatus", pipestatus_gsu), * and $@, this is not readonly. This parameter is not directly * visible in user space. */ -initparam argvparam_pm = IPDEF9F("", &pparams, NULL, \ +static initparam argvparam_pm = IPDEF9F("", &pparams, NULL, \ PM_ARRAY|PM_SPECIAL|PM_DONTIMPORT); #undef BR diff --git a/Src/prompt.c b/Src/prompt.c index be067ee7e..831c4f948 100644 --- a/Src/prompt.c +++ b/Src/prompt.c @@ -1831,7 +1831,7 @@ struct colour_sequences { char *end; /* Escape sequence terminator */ char *def; /* Code to reset default colour */ }; -struct colour_sequences fg_bg_sequences[2]; +static struct colour_sequences fg_bg_sequences[2]; /* * We need a buffer for colour sequence composition. It may diff --git a/Src/utils.c b/Src/utils.c index 053731cfa..de4af5a51 100644 --- a/Src/utils.c +++ b/Src/utils.c @@ -56,12 +56,12 @@ typedef struct widechar_array *Widechar_array; * The wordchars variable turned into a wide character array. * This is much more convenient for testing. */ -struct widechar_array wordchars_wide; +static struct widechar_array wordchars_wide; /* * The same for the separators (IFS) array. */ -struct widechar_array ifs_wide; +static struct widechar_array ifs_wide; /* Function to set one of the above from the multibyte array */ -- cgit v1.2.3 From 1ab316c9b8bcf60db091ed0cabe3930a52a0d965 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Sun, 7 Feb 2016 21:01:08 +0000 Subject: 37895: $ZSH_SCRIPT is POSIX $0 but always availble --- Doc/Zsh/params.yo | 7 +++++++ Src/params.c | 1 + 2 files changed, 8 insertions(+) (limited to 'Src/params.c') diff --git a/Doc/Zsh/params.yo b/Doc/Zsh/params.yo index 672209267..ae859ce6c 100644 --- a/Doc/Zsh/params.yo +++ b/Doc/Zsh/params.yo @@ -951,6 +951,13 @@ track of versions of the shell during development between releases; hence most users should not use it and should instead rely on tt($ZSH_VERSION). ) +vindex(ZSH_SCRIPT) +item(tt(ZSH_SCRIPT))( +If zsh was invoked to run a script, this is the name of the script. +Otherwise, it is the name used to invoke the current shell. This is +the same as the value of tt($0) when the tt(POSIX_ARGZERO) option is +set, but is always available. +) item(tt(zsh_scheduled_events))( See ifzman(the section `The zsh/sched Module' in zmanref(zshmodules))\ ifnzman(noderef(The zsh/sched Module)). diff --git a/Src/params.c b/Src/params.c index 76ed61c39..0233e2b00 100644 --- a/Src/params.c +++ b/Src/params.c @@ -813,6 +813,7 @@ createparamtable(void) setsparam("TTY", ztrdup_metafy(ttystrname)); setsparam("VENDOR", ztrdup_metafy(VENDOR)); setsparam("ZSH_NAME", ztrdup_metafy(zsh_name)); + setsparam("ZSH_SCRIPT", ztrdup(posixzero)); setsparam("ZSH_VERSION", ztrdup_metafy(ZSH_VERSION)); setsparam("ZSH_PATCHLEVEL", ztrdup_metafy(ZSH_PATCHLEVEL)); setaparam("signals", sigptr = zalloc((SIGCOUNT+4) * sizeof(char *))); -- cgit v1.2.3 From b7b3ae311db08cc2fc8cda52ac3a1ac8e06d2a89 Mon Sep 17 00:00:00 2001 From: "Barton E. Schaefer" Date: Tue, 16 Feb 2016 18:18:39 -0800 Subject: 37988: $0 becomes read-only under POSIXARGZERO --- ChangeLog | 4 ++++ Src/params.c | 4 +++- 2 files changed, 7 insertions(+), 1 deletion(-) (limited to 'Src/params.c') diff --git a/ChangeLog b/ChangeLog index fe1156f70..d0170bae2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -11,6 +11,10 @@ min(), max(), sum(), provided by a new autoloadable function 'zmathfunc'. +2016-02-16 Barton E. Schaefer + + * 37988: Src/params.c: $0 becomes read-only under POSIXARGZERO + 2016-02-15 Eric Cook * 37975: Completion/Unix/Command/_php: allow completion after diff --git a/Src/params.c b/Src/params.c index 0233e2b00..8bd8a8eee 100644 --- a/Src/params.c +++ b/Src/params.c @@ -4158,7 +4158,9 @@ static void argzerosetfn(UNUSED(Param pm), char *x) { if (x) { - if (!isset(POSIXARGZERO)) { + if (isset(POSIXARGZERO)) + zerr("read-only variable: 0"); + else { zsfree(argzero); argzero = ztrdup(x); } -- cgit v1.2.3 From f7d5ff31ce8d354dd69de619e703b9c0e49f0977 Mon Sep 17 00:00:00 2001 From: Stephane Chazelas Date: Wed, 24 Feb 2016 17:09:04 +0000 Subject: 38020: fix problems with $SECONDS. Fractions of a second were not handled correctly. --- ChangeLog | 5 +++++ Src/params.c | 6 +++--- 2 files changed, 8 insertions(+), 3 deletions(-) (limited to 'Src/params.c') diff --git a/ChangeLog b/ChangeLog index 5e3162f21..8498c5954 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2016-02-26 Peter Stephenson + + * Stephane: 38020: fix problems with fractions of a second in + $SECONDS. + 2016-02-25 Peter Stephenson * 38024: Src/signals.c, Test/C03traps.ztst: improve 37999 to diff --git a/Src/params.c b/Src/params.c index 8bd8a8eee..7c5f79fff 100644 --- a/Src/params.c +++ b/Src/params.c @@ -3804,8 +3804,8 @@ intsecondsgetfn(UNUSED(Param pm)) gettimeofday(&now, &dummy_tz); - return (zlong)(now.tv_sec - shtimer.tv_sec) + - (zlong)(now.tv_usec - shtimer.tv_usec) / (zlong)1000000; + return (zlong)(now.tv_sec - shtimer.tv_sec - + (now.tv_usec < shtimer.tv_usec ? 1 : 0)); } /* Function to set value of special parameter `SECONDS' */ @@ -3823,7 +3823,7 @@ intsecondssetfn(UNUSED(Param pm), zlong x) shtimer.tv_sec = diff; if ((zlong)shtimer.tv_sec != diff) zwarn("SECONDS truncated on assignment"); - shtimer.tv_usec = 0; + shtimer.tv_usec = now.tv_usec; } /**/ -- cgit v1.2.3 From 440c6beec09b3b4ba68955d807d48acef0d4360a Mon Sep 17 00:00:00 2001 From: Greg Klanderman Date: Sun, 6 Mar 2016 09:53:40 -0800 Subject: 38086: shuffle init code to localize a global, add $ZSH_ARGZERO, refine $ZSH_SCRIPT (also a couple of ChangeLog typos corrected -- Bart) --- ChangeLog | 10 ++++++++-- Doc/Zsh/params.yo | 19 ++++++++++++------- Src/init.c | 13 ++++++++----- Src/params.c | 6 ++---- 4 files changed, 30 insertions(+), 18 deletions(-) (limited to 'Src/params.c') diff --git a/ChangeLog b/ChangeLog index 28ac59bd9..734d685fa 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2016-03-06 Barton E. Schaefer + + * Greg Klanderman: 38086: Doc/Zsh/params.yo, Src/init.c, + Src/params.c: shuffle init code to localize a global, add + $ZSH_ARGZERO, refine $ZSH_SCRIPT + 2016-03-04 Peter Stephenson * 38084: Baruch Siach: configure.ac: use the pcre-config we @@ -124,7 +130,7 @@ 2016-02-07 Peter Stephenson * 37895: Src/params.c, Doc/Zsh/parmas.yo: add ZSH_SCRIPT as - always available form of POISX $0. + always available form of POSIX $0. 2016-02-07 Dominik Ritter @@ -5516,7 +5522,7 @@ 2014-08-01 Peter Stephenson - * 32932: Src/glob.c, Src/utils.c: add hmkarray() and + * 32932: Src/subst.c, Src/utils.c: add hmkarray() and use to fix leak. 2014-07-31 Barton E. Schaefer diff --git a/Doc/Zsh/params.yo b/Doc/Zsh/params.yo index ae859ce6c..d23c459a0 100644 --- a/Doc/Zsh/params.yo +++ b/Doc/Zsh/params.yo @@ -933,6 +933,13 @@ tt(zsh/zutil) module. ) enditem() ) +vindex(ZSH_ARGZERO) +item(tt(ZSH_ARGZERO))( +If zsh was invoked to run a script, this is the name of the script. +Otherwise, it is the name used to invoke the current shell. This is +the same as the value of tt($0) when the tt(POSIX_ARGZERO) option is +set, but is always available. +) vindex(ZSH_EXECUTION_STRING) item(tt(ZSH_EXECUTION_STRING))( If the shell was started with the option tt(-c), this contains @@ -951,17 +958,15 @@ track of versions of the shell during development between releases; hence most users should not use it and should instead rely on tt($ZSH_VERSION). ) -vindex(ZSH_SCRIPT) -item(tt(ZSH_SCRIPT))( -If zsh was invoked to run a script, this is the name of the script. -Otherwise, it is the name used to invoke the current shell. This is -the same as the value of tt($0) when the tt(POSIX_ARGZERO) option is -set, but is always available. -) item(tt(zsh_scheduled_events))( See ifzman(the section `The zsh/sched Module' in zmanref(zshmodules))\ ifnzman(noderef(The zsh/sched Module)). ) +vindex(ZSH_SCRIPT) +item(tt(ZSH_SCRIPT))( +If zsh was invoked to run a script, this is the name of the script, +otherwise it is unset. +) vindex(ZSH_SUBSHELL ) item(tt(ZSH_SUBSHELL))( Readonly integer. Initially zero, incremented each time the shell forks diff --git a/Src/init.c b/Src/init.c index 4097327ee..20a07eb0a 100644 --- a/Src/init.c +++ b/Src/init.c @@ -802,7 +802,7 @@ init_term(void) /**/ void -setupvals(char *cmd) +setupvals(char *cmd, char *runscript, char *zsh_name) { #ifdef USE_GETPWUID struct passwd *pswd; @@ -1089,6 +1089,9 @@ setupvals(char *cmd) if (cmd) setsparam("ZSH_EXECUTION_STRING", ztrdup(cmd)); + if (runscript) + setsparam("ZSH_SCRIPT", ztrdup(runscript)); + setsparam("ZSH_NAME", ztrdup(zsh_name)); /* NOTE: already metafied early in zsh_main() */ } /* @@ -1270,7 +1273,7 @@ run_init_scripts(void) /**/ void -init_misc(char *cmd) +init_misc(char *cmd, char *zsh_name) { #ifndef RESTRICTED_R if ( restricted ) @@ -1606,7 +1609,7 @@ mod_export int use_exit_printed; mod_export int zsh_main(UNUSED(int argc), char **argv) { - char **t, *runscript = NULL; + char **t, *runscript = NULL, *zsh_name; char *cmd; /* argument to -c */ int t0; #ifdef USE_LOCALE @@ -1660,14 +1663,14 @@ zsh_main(UNUSED(int argc), char **argv) SHTTY = -1; init_io(cmd); - setupvals(cmd); + setupvals(cmd, runscript, zsh_name); init_signals(); init_bltinmods(); init_builtins(); run_init_scripts(); setupshin(runscript); - init_misc(cmd); + init_misc(cmd, zsh_name); for (;;) { /* diff --git a/Src/params.c b/Src/params.c index 7c5f79fff..c6172e018 100644 --- a/Src/params.c +++ b/Src/params.c @@ -80,8 +80,7 @@ char *argzero, /* $0 */ *rprompt, /* $RPROMPT */ *rprompt2, /* $RPROMPT2 */ *sprompt, /* $SPROMPT */ - *wordchars, /* $WORDCHARS */ - *zsh_name; /* $ZSH_NAME */ + *wordchars; /* $WORDCHARS */ /**/ mod_export char *ifs, /* $IFS */ @@ -812,8 +811,7 @@ createparamtable(void) setsparam("OSTYPE", ztrdup_metafy(OSTYPE)); setsparam("TTY", ztrdup_metafy(ttystrname)); setsparam("VENDOR", ztrdup_metafy(VENDOR)); - setsparam("ZSH_NAME", ztrdup_metafy(zsh_name)); - setsparam("ZSH_SCRIPT", ztrdup(posixzero)); + setsparam("ZSH_ARGZERO", ztrdup(posixzero)); setsparam("ZSH_VERSION", ztrdup_metafy(ZSH_VERSION)); setsparam("ZSH_PATCHLEVEL", ztrdup_metafy(ZSH_PATCHLEVEL)); setaparam("signals", sigptr = zalloc((SIGCOUNT+4) * sizeof(char *))); -- cgit v1.2.3 From 3a6a6fda8a7034151a888cb09ff38ebd2dc2dad2 Mon Sep 17 00:00:00 2001 From: "Barton E. Schaefer" Date: Sat, 4 Jun 2016 22:21:29 -0700 Subject: unposted (cf. 38612): remove overeager DPUTS() --- ChangeLog | 2 ++ Src/params.c | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'Src/params.c') diff --git a/ChangeLog b/ChangeLog index af433876c..5f64b6c91 100644 --- a/ChangeLog +++ b/ChangeLog @@ -5,6 +5,8 @@ 2016-06-04 Barton E. Schaefer + * unposted (cf. 38612): Src/params.c: remove overeager DPUTS() + * 38599: Src/subst.c: skip the "no such named directory" warning when NO_EXEC is in effect diff --git a/Src/params.c b/Src/params.c index c6172e018..ae958abc4 100644 --- a/Src/params.c +++ b/Src/params.c @@ -2982,7 +2982,6 @@ sethparam(char *s, char **val) return NULL; queue_signals(); if (!(v = fetchvalue(&vbuf, &s, 1, SCANPM_ASSIGNING))) { - DPUTS(!v, "BUG: assigning to undeclared associative array"); createparam(t, PM_HASHED); checkcreate = isset(WARNCREATEGLOBAL) && locallevel > forklevel; } else if (!(PM_TYPE(v->pm->node.flags) & PM_HASHED) && -- cgit v1.2.3 From d309d9addc114d22175f5feb0ab2e5fdf290dc02 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Tue, 21 Jun 2016 12:31:32 +0100 Subject: 38692: IFS can't be changed in restricted mode --- ChangeLog | 5 +++++ Doc/Zsh/restricted.yo | 10 +++++----- Src/params.c | 2 +- 3 files changed, 11 insertions(+), 6 deletions(-) (limited to 'Src/params.c') diff --git a/ChangeLog b/ChangeLog index 52a655069..a65ba2970 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2016-06-21 Peter Stephenson + + * 38692: Doc/Zsh/restricted.yo, Src/params.c: IFS can't be + changed in restricted mode. + 2016-06-19 Barton E. Schaefer * 38715: Doc/Zsh/contrib.yo, Functions/Zle/add-zle-hook-widget: diff --git a/Doc/Zsh/restricted.yo b/Doc/Zsh/restricted.yo index b56b50c6f..6cf9b36b5 100644 --- a/Doc/Zsh/restricted.yo +++ b/Doc/Zsh/restricted.yo @@ -10,11 +10,11 @@ restricted mode: startitemize() itemiz(changing directories with the tt(cd) builtin) -itemiz(changing or unsetting the tt(PATH), tt(path), tt(MODULE_PATH), -tt(module_path), tt(SHELL), tt(HISTFILE), tt(HISTSIZE), tt(GID), tt(EGID), -tt(UID), tt(EUID), tt(USERNAME), tt(LD_LIBRARY_PATH), -tt(LD_AOUT_LIBRARY_PATH), tt(LD_PRELOAD) and tt(LD_AOUT_PRELOAD) -parameters) +itemiz(changing or unsetting the tt(EGID), tt(EUID), tt(GID), +tt(HISTFILE), tt(HISTSIZE), tt(IFS), tt(LD_AOUT_LIBRARY_PATH), +tt(LD_AOUT_PRELOAD), tt(LD_LIBRARY_PATH), tt(LD_PRELOAD), +tt(MODULE_PATH), tt(module_path), tt(PATH), tt(path), tt(SHELL), +tt(UID) and tt(USERNAME) parameters) itemiz(specifying command names containing tt(/)) itemiz(specifying command pathnames using tt(hash)) itemiz(redirecting output to files) diff --git a/Src/params.c b/Src/params.c index ae958abc4..e7a73657b 100644 --- a/Src/params.c +++ b/Src/params.c @@ -284,7 +284,7 @@ IPDEF2("HOME", home_gsu, PM_UNSET), IPDEF2("TERM", term_gsu, PM_UNSET), IPDEF2("TERMINFO", terminfo_gsu, PM_UNSET), IPDEF2("WORDCHARS", wordchars_gsu, 0), -IPDEF2("IFS", ifs_gsu, PM_DONTIMPORT), +IPDEF2("IFS", ifs_gsu, PM_DONTIMPORT | PM_RESTRICTED), IPDEF2("_", underscore_gsu, PM_DONTIMPORT), IPDEF2("KEYBOARD_HACK", keyboard_hack_gsu, PM_DONTIMPORT), IPDEF2("0", argzero_gsu, 0), -- cgit v1.2.3 From 1a368bf31f2b2e6e96290a4803bdcd81e9f17393 Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Sat, 30 Jul 2016 10:14:35 +0000 Subject: 38973: Optimize indexing array parameters. % () { for 1 in $prefix/zsh/bin/zsh Src/zsh; do $1 -f -c 'a=( {1..1000000} ); repeat 3 time ( repeat 300 : $a[1] )'; done } ( repeat 300; do; : $a[1]; done; ) 1.68s user 0.01s system 98% cpu 1.718 total ( repeat 300; do; : $a[1]; done; ) 1.69s user 0.01s system 99% cpu 1.710 total ( repeat 300; do; : $a[1]; done; ) 1.69s user 0.01s system 99% cpu 1.714 total ( repeat 300; do; : $a[1]; done; ) 0.00s user 0.01s system 72% cpu 0.022 total ( repeat 300; do; : $a[1]; done; ) 0.00s user 0.01s system 72% cpu 0.022 total ( repeat 300; do; : $a[1]; done; ) 0.01s user 0.01s system 69% cpu 0.023 total --- ChangeLog | 3 +++ Src/params.c | 2 +- Src/subst.c | 15 +++++++++++---- Src/utils.c | 40 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 55 insertions(+), 5 deletions(-) (limited to 'Src/params.c') diff --git a/ChangeLog b/ChangeLog index 7752ce68b..bcc9d09bb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2016-08-01 Daniel Shahaf + * 38973: Src/params.c, Src/subst.c, Src/utils.c: Optimize + indexing array parameters. + * 38964: Completion/Unix/Command/_git: _git-config: Complete option names present in the config file. diff --git a/Src/params.c b/Src/params.c index e7a73657b..33f177ecc 100644 --- a/Src/params.c +++ b/Src/params.c @@ -2026,7 +2026,7 @@ getstrvalue(Value v) else { if (v->start < 0) v->start += arrlen(ss); - s = (v->start >= arrlen(ss) || v->start < 0) ? + s = (arrlen_le(ss, v->start) || v->start < 0) ? (char *) hcalloc(1) : ss[v->start]; } return s; diff --git a/Src/subst.c b/Src/subst.c index 8e704b1c1..e3af15694 100644 --- a/Src/subst.c +++ b/Src/subst.c @@ -2548,12 +2548,19 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags, * necessary joining of arrays until this point * to avoid the multsub() horror. */ - int tmplen = arrlen(v->pm->gsu.a->getfn(v->pm)); - if (v->start < 0) + /* arrlen() is expensive, so only compute it if needed. */ + int tmplen = -1; + + if (v->start < 0) { + tmplen = arrlen(v->pm->gsu.a->getfn(v->pm)); v->start += tmplen + ((v->flags & VALFLAG_INV) ? 1 : 0); - if (!(v->flags & VALFLAG_INV) && - (v->start >= tmplen || v->start < 0)) + } + if (!(v->flags & VALFLAG_INV)) + if (v->start < 0 || + (tmplen != -1 + ? v->start >= tmplen + : arrlen_le(v->pm->gsu.a->getfn(v->pm), v->start))) vunset = 1; } if (!vunset) { diff --git a/Src/utils.c b/Src/utils.c index 95be1fb98..95da96058 100644 --- a/Src/utils.c +++ b/Src/utils.c @@ -2280,6 +2280,46 @@ arrlen(char **s) return count; } +/* Return TRUE iff arrlen(s) >= lower_bound, but more efficiently. */ + +/**/ +mod_export char +arrlen_ge(char **s, unsigned lower_bound) +{ + while (lower_bound--) + if (!*s++) + return 0 /* FALSE */; + + return 1 /* TRUE */; +} + +/* Return TRUE iff arrlen(s) > lower_bound, but more efficiently. */ + +/**/ +mod_export char +arrlen_gt(char **s, unsigned lower_bound) +{ + return arrlen_ge(s, 1+lower_bound); +} + +/* Return TRUE iff arrlen(s) <= upper_bound, but more efficiently. */ + +/**/ +mod_export char +arrlen_le(char **s, unsigned upper_bound) +{ + return arrlen_lt(s, 1+upper_bound); +} + +/* Return TRUE iff arrlen(s) < upper_bound, but more efficiently. */ + +/**/ +mod_export char +arrlen_lt(char **s, unsigned upper_bound) +{ + return !arrlen_ge(s, upper_bound); +} + /* Skip over a balanced pair of parenthesis. */ /**/ -- cgit v1.2.3 From f9b170351136e7e2e04cecf4f1f6c686b0c1324d Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Sat, 30 Jul 2016 10:50:48 +0000 Subject: 38971: Start using the new arrlen_ge() / arrlen_le() helpers. --- ChangeLog | 4 ++++ Src/Modules/terminfo.c | 2 +- Src/Modules/zutil.c | 4 ++-- Src/builtin.c | 6 +++--- Src/params.c | 4 ++-- Src/prompt.c | 6 +++--- Src/utils.c | 2 +- 7 files changed, 16 insertions(+), 12 deletions(-) (limited to 'Src/params.c') diff --git a/ChangeLog b/ChangeLog index bcc9d09bb..28ce9bb71 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2016-08-01 Daniel Shahaf + * 38971: Src/Modules/terminfo.c, Src/Modules/zutil.c, + Src/builtin.c, Src/params.c, Src/prompt.c, Src/utils.c: Start + using the new arrlen_ge() / arrlen_le() helpers. + * 38973: Src/params.c, Src/subst.c, Src/utils.c: Optimize indexing array parameters. diff --git a/Src/Modules/terminfo.c b/Src/Modules/terminfo.c index e0439afca..bbd325899 100644 --- a/Src/Modules/terminfo.c +++ b/Src/Modules/terminfo.c @@ -99,7 +99,7 @@ bin_echoti(char *name, char **argv, UNUSED(Options ops), UNUSED(int func)) return 1; } /* check that the number of arguments provided is not too high */ - if (arrlen(argv) > 9) { + if (arrlen_gt(argv, 9)) { zwarnnam(name, "too many arguments"); return 1; } diff --git a/Src/Modules/zutil.c b/Src/Modules/zutil.c index 477575ccd..d95c0c254 100644 --- a/Src/Modules/zutil.c +++ b/Src/Modules/zutil.c @@ -472,7 +472,7 @@ bin_zstyle(char *nam, char **args, UNUSED(Options ops), UNUSED(int func)) Patprog prog; char *pat; - if (arrlen(args) < 2) { + if (arrlen_lt(args, 2)) { zwarnnam(nam, "not enough arguments"); return 1; } @@ -491,7 +491,7 @@ bin_zstyle(char *nam, char **args, UNUSED(Options ops), UNUSED(int func)) Style s; char *context, *stylename; - switch (arrlen(args)) { + switch (arrlen_ge(args, 3) ? 3 : arrlen(args)) { case 2: context = args[0]; stylename = args[1]; diff --git a/Src/builtin.c b/Src/builtin.c index bfb9e6929..fb14b2e33 100644 --- a/Src/builtin.c +++ b/Src/builtin.c @@ -3406,7 +3406,7 @@ bin_unset(char *name, char **argv, Options ops, int func) } else { /* start is after the element for reverse index */ int start = vbuf.start - !!(vbuf.flags & VALFLAG_INV); - if (start < arrlen(vbuf.pm->u.arr)) { + if (arrlen_gt(vbuf.pm->u.arr, start)) { char *arr[2]; arr[0] = ""; arr[1] = 0; @@ -5026,7 +5026,7 @@ bin_shift(char *name, char **argv, Options ops, UNUSED(int func)) if (*argv) { for (; *argv; argv++) if ((s = getaparam(*argv))) { - if (num > arrlen(s)) { + if (arrlen_lt(s, num)) { zwarnnam(name, "shift count must be <= $#"); ret++; continue; @@ -5095,7 +5095,7 @@ bin_getopts(UNUSED(char *name), char **argv, UNUSED(Options ops), UNUSED(int fun zoptind = 1; optcind = 0; } - if(zoptind > arrlen(args)) + if (arrlen_lt(args, zoptind)) /* no more options */ return 1; diff --git a/Src/params.c b/Src/params.c index 33f177ecc..0eda7848f 100644 --- a/Src/params.c +++ b/Src/params.c @@ -2225,13 +2225,13 @@ getarrvalue(Value v) v->start += arrlen(s); if (v->end < 0) v->end += arrlen(s) + 1; - if (v->start > arrlen(s) || v->start < 0) + if (arrlen_lt(s, v->start) || v->start < 0) s = arrdup(nular); else s = arrdup(s + v->start); if (v->end <= v->start) s[0] = NULL; - else if (v->end - v->start <= arrlen(s)) + else if (arrlen_ge(s, v->end - v->start)) s[v->end - v->start] = NULL; return s; } diff --git a/Src/prompt.c b/Src/prompt.c index bb2745358..d4f389809 100644 --- a/Src/prompt.c +++ b/Src/prompt.c @@ -395,11 +395,11 @@ putpromptchar(int doprint, int endchar, unsigned int *txtchangep) test = 1; break; case 'v': - if (arrlen(psvar) >= arg) + if (arrlen_ge(psvar, arg)) test = 1; break; case 'V': - if (arrlen(psvar) >= arg) { + if (arrlen_ge(psvar, arg)) { if (*psvar[(arg ? arg : 1) - 1]) test = 1; } @@ -736,7 +736,7 @@ putpromptchar(int doprint, int endchar, unsigned int *txtchangep) arg = 1; else if (arg < 0) arg += arrlen(psvar) + 1; - if (arg > 0 && arrlen(psvar) >= arg) + if (arg > 0 && arrlen_ge(psvar, arg)) stradd(psvar[arg - 1]); break; case 'E': diff --git a/Src/utils.c b/Src/utils.c index 95da96058..0a5954f65 100644 --- a/Src/utils.c +++ b/Src/utils.c @@ -1157,7 +1157,7 @@ finddir(char *s) scanhashtable(nameddirtab, 0, 0, 0, finddir_scan, 0); ares = subst_string_by_hook("zsh_directory_name", "d", finddir_full); - if (ares && arrlen(ares) >= 2 && + if (ares && arrlen_ge(ares, 2) && (len = (int)zstrtol(ares[1], NULL, 10)) > finddir_best) { /* better duplicate this string since it's come from REPLY */ finddir_last = (Nameddir)hcalloc(sizeof(struct nameddir)); -- cgit v1.2.3 From 7154052ebe3d810390164a05c39ff83f98a1d858 Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Sat, 30 Jul 2016 16:16:22 +0000 Subject: 39046 + 39061: New :P history modifier. --- ChangeLog | 10 ++++++++++ Completion/Base/Completer/_external_pwds | 2 +- Completion/Zsh/Type/_history_modifiers | 5 +++-- Doc/Zsh/contrib.yo | 2 +- Doc/Zsh/expn.yo | 9 +++++++++ Functions/MIME/zsh-mime-handler | 2 +- Functions/VCS_Info/VCS_INFO_quilt | 2 +- Functions/Zle/expand-absolute-path | 2 +- NEWS | 11 +++++++++++ Src/params.c | 2 +- Src/subst.c | 13 +++++++++++++ Src/utils.c | 14 ++++++++------ Test/D02glob.ztst | 8 ++++++++ 13 files changed, 68 insertions(+), 14 deletions(-) (limited to 'Src/params.c') diff --git a/ChangeLog b/ChangeLog index 65263033a..d3a7d3356 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2016-08-22 Daniel Shahaf + + * 39046 + 39061: Completion/Base/Completer/_external_pwds, + Completion/Zsh/Type/_history_modifiers, Doc/Zsh/contrib.yo, + Doc/Zsh/expn.yo, Functions/MIME/zsh-mime-handler, + Functions/VCS_Info/VCS_INFO_quilt, + Functions/Zle/expand-absolute-path, NEWS, Src/params.c, + Src/subst.c, Src/utils.c, Test/D02glob.ztst: New :P history + modifier. + 2016-08-20 Jun-ichi Takimoto * 39064: configure.ac, Src/Modules/mathfuc.c: use scalbn() instead diff --git a/Completion/Base/Completer/_external_pwds b/Completion/Base/Completer/_external_pwds index 4ad50f02b..79e3ba0eb 100644 --- a/Completion/Base/Completer/_external_pwds +++ b/Completion/Base/Completer/_external_pwds @@ -22,7 +22,7 @@ case $OSTYPE in ) ;; linux*) - dirs=( /proc/${^$(pidof zsh):#$$}/cwd(N:A) ) + dirs=( /proc/${^$(pidof zsh):#$$}/cwd(N:P) ) dirs=( $^dirs(N^@) ) ;; *) diff --git a/Completion/Zsh/Type/_history_modifiers b/Completion/Zsh/Type/_history_modifiers index 658f9f346..1a049d6cb 100644 --- a/Completion/Zsh/Type/_history_modifiers +++ b/Completion/Zsh/Type/_history_modifiers @@ -64,8 +64,8 @@ while true; do ) if (( ! global )); then list+=( - "a:absolute path" - "A:absolute path resolving symbolic links" + "a:absolute path, resolve '..' lexically" + "A:as ':a', then resolve symlinks" "c:PATH search for command" "g:globally apply s or &" "h:head - strip trailing path element" @@ -73,6 +73,7 @@ while true; do "r:root - strip suffix" "e:leave only extension" "Q:strip quotes" + "P:realpath, resolve '..' physically" "l:lower case all words" "u:upper case all words" ) diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo index 00ed08029..63df292ac 100644 --- a/Doc/Zsh/contrib.yo +++ b/Doc/Zsh/contrib.yo @@ -3477,7 +3477,7 @@ will ensure that any files found in that area will be executed as MIME types even if they are executable. As this example shows, the complete file name is matched against the pattern, regardless of how the file was passed to the handler. The file is resolved to a full path using -the tt(:A) modifier described in +the tt(:P) modifier described in ifzman(the subsection Modifiers in zmanref(zshexpn))\ ifnzman(noderef(Modifiers)); this means that symbolic links are resolved where possible, so that diff --git a/Doc/Zsh/expn.yo b/Doc/Zsh/expn.yo index ca4b94f5e..ecb1877a2 100644 --- a/Doc/Zsh/expn.yo +++ b/Doc/Zsh/expn.yo @@ -240,6 +240,7 @@ function, symbolic links are not resolved, so on those systems `tt(a)' and `tt(A)' are equivalent. Note: tt(foo:A) and tt(realpath+LPAR()foo+RPAR()) are different on some inputs. +For tt(realpath+LPAR()foo+RPAR()) semantics, see the `tt(P)` modifier. ) item(tt(c))( Resolve a command name into an absolute path by searching the command @@ -265,6 +266,14 @@ item(tt(p))( Print the new command but do not execute it. Only works with history expansion. ) +item(tt(P))( +Turn a file name into an absolute path, like tt(realpath+LPAR()3+RPAR()). +The resulting path will be absolute, have neither `tt(.)' nor `tt(..)' components, +and refer to the same directory entry as the input filename. + +Unlike tt(realpath+LPAR()3+RPAR()), non-existent trailing components are +permitted and preserved. +) item(tt(q))( Quote the substituted words, escaping further substitutions. Works with history expansion and parameter expansion, though for parameters diff --git a/Functions/MIME/zsh-mime-handler b/Functions/MIME/zsh-mime-handler index 24e5184fc..288a0796d 100644 --- a/Functions/MIME/zsh-mime-handler +++ b/Functions/MIME/zsh-mime-handler @@ -127,7 +127,7 @@ for pattern in $exec_asis; do files=(${dirpref}${~pattern}) if [[ -n ${files[(r)$1]} ]]; then for pattern in $exec_never; do - [[ ${1:A} = ${~pattern} ]] && break 2 + [[ ${1:P} = ${~pattern} ]] && break 2 done if (( list )); then for (( i = 1; i <= $#; i++ )); do diff --git a/Functions/VCS_Info/VCS_INFO_quilt b/Functions/VCS_Info/VCS_INFO_quilt index e7cd89f78..6adf0a358 100644 --- a/Functions/VCS_Info/VCS_INFO_quilt +++ b/Functions/VCS_Info/VCS_INFO_quilt @@ -170,7 +170,7 @@ function VCS_INFO_quilt() { applied=() fi patches=$(<$pc/.quilt_patches) - patches=`builtin cd -q "${pc:h}" && print -r - ${patches:A}` + patches=`builtin cd -q "${pc:h}" && print -r - ${patches:P}` fi if zstyle -t "${context}" get-unapplied; then # This zstyle call needs to be moved further up if `quilt' needs diff --git a/Functions/Zle/expand-absolute-path b/Functions/Zle/expand-absolute-path index b85757600..4887f3c60 100644 --- a/Functions/Zle/expand-absolute-path +++ b/Functions/Zle/expand-absolute-path @@ -10,7 +10,7 @@ autoload -Uz modify-current-argument if (( ! ${+functions[glob-expand-absolute-path]} )); then glob-expand-absolute-path() { local -a files - files=(${~1}(N:A)) + files=(${~1}(N:P)) (( ${#files} )) || return REPLY=${(D)files[1]} } diff --git a/NEWS b/NEWS index 15822ad34..65b246d33 100644 --- a/NEWS +++ b/NEWS @@ -4,6 +4,17 @@ CHANGES FROM PREVIOUS VERSIONS OF ZSH Note also the list of incompatibilities in the README file. +Changes from 5.2 to 5.3 +----------------------- + +The new word modifier ':P' computes the physical path of the argument. +It is different from the existing ':a' modifier which always resolves +'/before/here/../after' to '/before/after', and differs from the +existing ':A' modifier which resolves symlinks only after 'here/..' is +removed, even when /before/here is itself a symbolic link. It is +recommended to review uses of ':A' and, if appropriate, convert them +to ':P' as soon as compatibility with 5.2 is no longer a requirement. + Changes from 5.1.1 to 5.2 ------------------------- diff --git a/Src/params.c b/Src/params.c index 0eda7848f..842b2f0d1 100644 --- a/Src/params.c +++ b/Src/params.c @@ -4336,7 +4336,7 @@ void homesetfn(UNUSED(Param pm), char *x) { zsfree(home); - if (x && isset(CHASELINKS) && (home = xsymlink(x))) + if (x && isset(CHASELINKS) && (home = xsymlink(x, 0))) zsfree(x); else home = x ? x : ztrdup(""); diff --git a/Src/subst.c b/Src/subst.c index c61551bf6..15eb59b64 100644 --- a/Src/subst.c +++ b/Src/subst.c @@ -4081,6 +4081,7 @@ modify(char **str, char **ptr) case 'u': case 'q': case 'Q': + case 'P': c = **ptr; break; @@ -4287,6 +4288,12 @@ modify(char **str, char **ptr) untokenize(copy); } break; + case 'P': + if (*copy != '/') { + copy = zhtricat(metafy(zgetcwd(), -1, META_HEAPDUP), "/", copy); + } + copy = xsymlink(copy, 1); + break; } tc = *tt; *tt = '\0'; @@ -4363,6 +4370,12 @@ modify(char **str, char **ptr) untokenize(*str); } break; + case 'P': + if (**str != '/') { + *str = zhtricat(metafy(zgetcwd(), -1, META_HEAPDUP), "/", *str); + } + *str = xsymlink(*str, 1); + break; } } if (rec < 0) { diff --git a/Src/utils.c b/Src/utils.c index 0a5954f65..45fd19286 100644 --- a/Src/utils.c +++ b/Src/utils.c @@ -801,9 +801,9 @@ findpwd(char *s) char *t; if (*s == '/') - return xsymlink(s); + return xsymlink(s, 0); s = tricat((pwd[1]) ? pwd : "", "/", s); - t = xsymlink(s); + t = xsymlink(s, 0); zsfree(s); return t; } @@ -969,11 +969,13 @@ xsymlinks(char *s, int full) /* * expand symlinks in s, and remove other weird things: * note that this always expands symlinks. + * + * 'heap' indicates whether to malloc() or allocate on the heap. */ /**/ char * -xsymlink(char *s) +xsymlink(char *s, int heap) { if (*s != '/') return NULL; @@ -981,8 +983,8 @@ xsymlink(char *s) if (xsymlinks(s + 1, 1) < 0) zwarn("path expansion failed, using root directory"); if (!*xbuf) - return ztrdup("/"); - return ztrdup(xbuf); + return heap ? dupstring("/") : ztrdup("/"); + return heap ? dupstring(xbuf) : ztrdup(xbuf); } /**/ @@ -1260,7 +1262,7 @@ getnameddir(char *name) /* Retrieve an entry from the password table/database for this user. */ struct passwd *pw; if ((pw = getpwnam(name))) { - char *dir = isset(CHASELINKS) ? xsymlink(pw->pw_dir) + char *dir = isset(CHASELINKS) ? xsymlink(pw->pw_dir, 0) : ztrdup(pw->pw_dir); if (dir) { adduserdir(name, dir, ND_USERNAME, 1); diff --git a/Test/D02glob.ztst b/Test/D02glob.ztst index 7befbc21f..1385d57d9 100644 --- a/Test/D02glob.ztst +++ b/Test/D02glob.ztst @@ -678,3 +678,11 @@ rm glob.tmp/link 0:modifier ':A' resolves '..' components before symlinks # There should be no output + + ln -s dir3/subdir glob.tmp/link + () { + print ${1:P} + } glob.tmp/link/../../hello/world + rm glob.tmp/link +0:modifier ':P' resolves symlinks before '..' components +*>*glob.tmp/hello/world -- cgit v1.2.3 From fbafc5b509e311efee064bbd12396a2e207f3393 Mon Sep 17 00:00:00 2001 From: Oliver Kiddle Date: Fri, 16 Sep 2016 00:00:28 +0200 Subject: 39332: support ksh's [[ -v varname ]] condition for checking if variables are set --- ChangeLog | 4 ++++ Completion/Zsh/Context/_condition | 3 +++ Doc/Zsh/cond.yo | 3 +++ Src/cond.c | 2 ++ Src/params.c | 30 ++++++++++++++++++++++++++++++ Src/parse.c | 4 ++-- Test/C02cond.ztst | 19 +++++++++++++++++++ 7 files changed, 63 insertions(+), 2 deletions(-) (limited to 'Src/params.c') diff --git a/ChangeLog b/ChangeLog index 1c749ae64..f54d78ca3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2016-09-15 Oliver Kiddle + * 39332: Doc/Zsh/cond.yo, Src/cond.c, Src/params.c, Src/parse.c, + Completion/Zsh/Context/_condition, Test/C02cond.ztst: support + ksh's [[ -v varname ]] condition for checking if variables are set + * unposted: Src/parse.c: remove duplicated assignment 2016-09-14 Peter Stephenson diff --git a/Completion/Zsh/Context/_condition b/Completion/Zsh/Context/_condition index 6f5e601f0..0285911ac 100644 --- a/Completion/Zsh/Context/_condition +++ b/Completion/Zsh/Context/_condition @@ -8,6 +8,8 @@ elif [[ "$prev" = -([a-hkprsuwxLOGSN]|[no]t|ef) ]]; then _tags -C "$prev" files && _files elif [[ "$prev" = -t ]]; then _file_descriptors +elif [[ "$prev" = -v ]]; then + _parameters -r "\= \t\n\[\-" else if [[ "$PREFIX" = -* ]] || ! zstyle -T ":completion:${curcontext}:options" prefix-needed; then @@ -30,6 +32,7 @@ else -s:non-empty\ file -t:terminal\ file\ descriptor -u:setuid\ bit + -v:set\ variable -w:writable\ file -x:executable\ file -z:empty\ string diff --git a/Doc/Zsh/cond.yo b/Doc/Zsh/cond.yo index 474baa1ec..e08fc0d36 100644 --- a/Doc/Zsh/cond.yo +++ b/Doc/Zsh/cond.yo @@ -63,6 +63,9 @@ is open and associated with a terminal device. item(tt(-u) var(file))( true if var(file) exists and has its setuid bit set. ) +item(tt(-v) var(varname))( +true if shell variable var(varname) is set. +) item(tt(-w) var(file))( true if var(file) exists and is writable by current process. ) diff --git a/Src/cond.c b/Src/cond.c index f25ebd4a3..42e9de30f 100644 --- a/Src/cond.c +++ b/Src/cond.c @@ -351,6 +351,8 @@ evalcond(Estate state, char *fromtest) return (!S_ISSOCK(dostat(left))); case 'u': return (!(dostat(left) & S_ISUID)); + case 'v': + return (!issetvar(left)); case 'w': return (!doaccess(left, W_OK)); case 'x': diff --git a/Src/params.c b/Src/params.c index 842b2f0d1..384c30a1a 100644 --- a/Src/params.c +++ b/Src/params.c @@ -626,6 +626,36 @@ getvaluearr(Value v) return NULL; } +/* Return whether the variable is set * + * checks that array slices are within range * + * used for [[ -v ... ]] condition test */ + +/**/ +int +issetvar(char *name) +{ + struct value vbuf; + Value v; + int slice; + char **arr; + + if (!(v = getvalue(&vbuf, &name, 1)) || *name) + return 0; /* no value or more chars after the variable name */ + if (v->isarr & ~SCANPM_ARRONLY) + return v->end > 1; /* for extracted elements, end gives us a count */ + + slice = v->start != 0 || v->end != -1; + if (PM_TYPE(v->pm->node.flags) != PM_ARRAY || !slice) + return !slice && !(v->pm->node.flags & PM_UNSET); + + if (!v->end) /* empty array slice */ + return 0; + /* get the array and check end is within range */ + if (!(arr = getvaluearr(v))) + return 0; + return arrlen_ge(arr, v->end < 0 ? - v->end : v->end); +} + /* * Split environment string into (name, value) pair. * this is used to avoid in-place editing of environment table diff --git a/Src/parse.c b/Src/parse.c index d3c418184..24b8cd97f 100644 --- a/Src/parse.c +++ b/Src/parse.c @@ -2385,7 +2385,7 @@ par_cond_2(void) s1 = tokstr; dble = (s1 && *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 */ @@ -2464,7 +2464,7 @@ par_cond_double(char *a, char *b) { if (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 { diff --git a/Test/C02cond.ztst b/Test/C02cond.ztst index 78e644a72..40e4dfb0b 100644 --- a/Test/C02cond.ztst +++ b/Test/C02cond.ztst @@ -269,6 +269,25 @@ F:Failures in these cases do not indicate a problem in the shell. 0:-nt shouldn't abort on non-existent files >status = 1 + str='string' empty='' + [[ -v IFS && -v str && -v empty && ! -v str[3] && ! -v not_a_variable ]] +0:-v cond + + arr=( 1 2 3 4 ) empty=() + [[ -v arr && -v arr[1,4] && -v arr[1] && -v arr[4] && -v arr[-4] && + -v arr[(i)3] && ! -v arr[(i)x] && + ! -v arr[0] && ! -v arr[5] && ! -v arr[-5] && ! -v arr[2][1] && + ! -v arr[3]extra && -v empty && ! -v empty[1] ]] +0:-v cond with array + + typeset -A assoc=( key val num 4 ) + [[ -v assoc && -v assoc[key] && -v assoc[(i)*] && -v assoc[(I)*] && + ! -v assoc[x] && ! -v assoc[key][1] ]] +0:-v cond with association + + () { [[ -v 0 && -v 1 && -v 2 && ! -v 3 ]] } arg '' +0:-v cond with positional parameters + # core dumps on failure if zmodload zsh/regex 2>/dev/null; then echo >regex_test.sh 'if [[ $# = 1 ]]; then -- cgit v1.2.3 From b32d974000295a5fa0b0c981b3198f987d3177c4 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Wed, 28 Sep 2016 09:50:58 +0100 Subject: 39460: Don't import PS4 if running as root. There was an exploit in bash using SHELLOPTS to turn on xtrace, however this can't happen in zsh, so this is simply a precaution. --- ChangeLog | 6 ++++++ Src/params.c | 33 ++++++++++++++++++++++++++++++--- Src/zsh.h | 1 + 3 files changed, 37 insertions(+), 3 deletions(-) (limited to 'Src/params.c') diff --git a/ChangeLog b/ChangeLog index 6674be512..9c50f15f9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2016-09-28 Peter Stephenson + + * 39460: Src/params.c, Src/zsh.h: don't import PS4 if running as + root. Currently no known exploit with this in zsh as xtrace + needs an explicit option setting, so this is just precautionary. + 2016-09-27 Oliver Kiddle * Marko Myllynen: 39453: Completion/Unix/Command/_openstack: diff --git a/Src/params.c b/Src/params.c index 384c30a1a..a85e5a51e 100644 --- a/Src/params.c +++ b/Src/params.c @@ -333,6 +333,7 @@ IPDEF6("TRY_BLOCK_ERROR", &try_errflag, varinteger_gsu), IPDEF6("TRY_BLOCK_INTERRUPT", &try_interrupt, varinteger_gsu), #define IPDEF7(A,B) {{NULL,A,PM_SCALAR|PM_SPECIAL},BR((void *)B),GSU(varscalar_gsu),0,0,NULL,NULL,NULL,0} +#define IPDEF7R(A,B) {{NULL,A,PM_SCALAR|PM_SPECIAL|PM_DONTIMPORT_ROOT},BR((void *)B),GSU(varscalar_gsu),0,0,NULL,NULL,NULL,0} #define IPDEF7U(A,B) {{NULL,A,PM_SCALAR|PM_SPECIAL|PM_UNSET},BR((void *)B),GSU(varscalar_gsu),0,0,NULL,NULL,NULL,0} IPDEF7("OPTARG", &zoptarg), IPDEF7("NULLCMD", &nullcmd), @@ -345,7 +346,7 @@ IPDEF7("PS2", &prompt2), IPDEF7U("RPS2", &rprompt2), IPDEF7U("RPROMPT2", &rprompt2), IPDEF7("PS3", &prompt3), -IPDEF7("PS4", &prompt4), +IPDEF7R("PS4", &prompt4), IPDEF7("SPROMPT", &sprompt), #define IPDEF8(A,B,C,D) {{NULL,A,D|PM_SCALAR|PM_SPECIAL},BR((void *)B),GSU(colonarr_gsu),0,0,NULL,C,NULL,0} @@ -689,7 +690,28 @@ split_env_string(char *env, char **name, char **value) } else return 0; } - + +/** + * Check parameter flags to see if parameter shouldn't be imported + * from environment at start. + * + * return 1: don't import: 0: ok to import. + */ +static int dontimport(int flags) +{ + /* If explicitly marked as don't export */ + if (flags & PM_DONTIMPORT) + return 1; + /* If value already exported */ + if (flags & PM_EXPORTED) + return 1; + /* If security issue when exporting as root */ + if ((flags & PM_DONTIMPORT_ROOT) && (!getuid() || !geteuid())) + return 1; + /* OK to import */ + return 0; +} + /* Set up parameter hash table. This will add predefined * * parameter entries as well as setting up parameter table * * entries for environment variables we inherit. */ @@ -781,8 +803,13 @@ createparamtable(void) envp2 = environ; *envp2; envp2++) { if (split_env_string(*envp2, &iname, &ivalue)) { if (!idigit(*iname) && isident(iname) && !strchr(iname, '[')) { + /* + * Parameters that aren't already in the parameter table + * aren't special to the shell, so it's always OK to + * import. Otherwise, check parameter flags. + */ if ((!(pm = (Param) paramtab->getnode(paramtab, iname)) || - !(pm->node.flags & PM_DONTIMPORT || pm->node.flags & PM_EXPORTED)) && + !dontimport(pm->node.flags)) && (pm = assignsparam(iname, metafy(ivalue, -1, META_DUP), ASSPM_ENV_IMPORT))) { pm->node.flags |= PM_EXPORTED; diff --git a/Src/zsh.h b/Src/zsh.h index bb8ce130c..052d754c9 100644 --- a/Src/zsh.h +++ b/Src/zsh.h @@ -1802,6 +1802,7 @@ struct tieddata { #define PM_ZSHSTORED (1<<18) /* function stored in zsh form */ /* Remaining flags do not correspond directly to command line arguments */ +#define PM_DONTIMPORT_ROOT (1<<19) /* do not import if running as root */ #define PM_SINGLE (1<<20) /* special can only have a single instance */ #define PM_LOCAL (1<<21) /* this parameter will be made local */ #define PM_SPECIAL (1<<22) /* special builtin parameter */ -- cgit v1.2.3 From d44d23c7578285375f4ded759f7d8412320c3319 Mon Sep 17 00:00:00 2001 From: Bart Schaefer Date: Wed, 28 Sep 2016 10:58:46 -0700 Subject: unposted: change '\0' to NULL to silence spurious compile warning. params.c:830:13: warning: expression which evaluates to zero treated as a null pointer constant of type 'char *' [-Wnon-literal-null-conversion] *envp = '\0'; --- Src/params.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Src/params.c') diff --git a/Src/params.c b/Src/params.c index a85e5a51e..87586a209 100644 --- a/Src/params.c +++ b/Src/params.c @@ -827,7 +827,7 @@ createparamtable(void) } popheap(); #ifndef USE_SET_UNSET_ENV - *envp = '\0'; + *envp = NULL; #endif opts[ALLEXPORT] = oae; -- cgit v1.2.3 From d08674ef8c8e4920c2ebfa02f0bef86812f051ee Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Fri, 30 Sep 2016 10:40:27 +0100 Subject: 39498: use PRIVILEGED option to decide on problematic parameter imports --- ChangeLog | 5 +++++ Src/params.c | 6 +++--- Src/zsh.h | 2 +- 3 files changed, 9 insertions(+), 4 deletions(-) (limited to 'Src/params.c') diff --git a/ChangeLog b/ChangeLog index b49289b63..d6db9d982 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2016-09-30 Peter Stephenson + + * 39498: Src/parmas.c,Src/zsh.h: use PRIVILEGED option to + decide on problematic parameter imports. + 2016-09-30 Mikael Magnusson * 39452 + comment from 39432: Src/Zle/zle_main.c: Call the diff --git a/Src/params.c b/Src/params.c index 87586a209..8271a8b53 100644 --- a/Src/params.c +++ b/Src/params.c @@ -333,7 +333,7 @@ IPDEF6("TRY_BLOCK_ERROR", &try_errflag, varinteger_gsu), IPDEF6("TRY_BLOCK_INTERRUPT", &try_interrupt, varinteger_gsu), #define IPDEF7(A,B) {{NULL,A,PM_SCALAR|PM_SPECIAL},BR((void *)B),GSU(varscalar_gsu),0,0,NULL,NULL,NULL,0} -#define IPDEF7R(A,B) {{NULL,A,PM_SCALAR|PM_SPECIAL|PM_DONTIMPORT_ROOT},BR((void *)B),GSU(varscalar_gsu),0,0,NULL,NULL,NULL,0} +#define IPDEF7R(A,B) {{NULL,A,PM_SCALAR|PM_SPECIAL|PM_DONTIMPORT_SUID},BR((void *)B),GSU(varscalar_gsu),0,0,NULL,NULL,NULL,0} #define IPDEF7U(A,B) {{NULL,A,PM_SCALAR|PM_SPECIAL|PM_UNSET},BR((void *)B),GSU(varscalar_gsu),0,0,NULL,NULL,NULL,0} IPDEF7("OPTARG", &zoptarg), IPDEF7("NULLCMD", &nullcmd), @@ -705,8 +705,8 @@ static int dontimport(int flags) /* If value already exported */ if (flags & PM_EXPORTED) return 1; - /* If security issue when exporting as root */ - if ((flags & PM_DONTIMPORT_ROOT) && (!getuid() || !geteuid())) + /* If security issue when importing and running with some privilege */ + if ((flags & PM_DONTIMPORT_SUID) && isset(PRIVILEGED)) return 1; /* OK to import */ return 0; diff --git a/Src/zsh.h b/Src/zsh.h index 052d754c9..79747d624 100644 --- a/Src/zsh.h +++ b/Src/zsh.h @@ -1802,7 +1802,7 @@ struct tieddata { #define PM_ZSHSTORED (1<<18) /* function stored in zsh form */ /* Remaining flags do not correspond directly to command line arguments */ -#define PM_DONTIMPORT_ROOT (1<<19) /* do not import if running as root */ +#define PM_DONTIMPORT_SUID (1<<19) /* do not import if running setuid */ #define PM_SINGLE (1<<20) /* special can only have a single instance */ #define PM_LOCAL (1<<21) /* this parameter will be made local */ #define PM_SPECIAL (1<<22) /* special builtin parameter */ -- cgit v1.2.3 From c942c7e8b6b217d6dcfeb9bf7ff544449e01f89e Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Fri, 30 Sep 2016 11:35:50 +0100 Subject: 39519: restore missing PM_EXPORT flags. This was missing when exporting using USE_SET_UNSET_ENV coce variant. --- ChangeLog | 3 +++ Src/params.c | 1 + 2 files changed, 4 insertions(+) (limited to 'Src/params.c') diff --git a/ChangeLog b/ChangeLog index ce891fc6b..3b6b86fe2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2016-09-30 Peter Stephenson + * 39519: Src/params.c: setting PM_EXPORT was missing in + USE_SET_UNSET_ENV case. + * 39517: back off 39502, this isn't a robust fix. * 39498: Src/parmas.c,Src/zsh.h: use PRIVILEGED option to diff --git a/Src/params.c b/Src/params.c index 8271a8b53..e11510246 100644 --- a/Src/params.c +++ b/Src/params.c @@ -4727,6 +4727,7 @@ addenv(Param pm, char *value) if (pm->env) zsfree(pm->env); pm->env = newenv; + pm->node.flags |= PM_EXPORTED; #else /* * Under Cygwin we must use putenv() to maintain consistency. -- cgit v1.2.3 From 4ab3fcc90d928d200f9e70c81189079c3316b42d Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Mon, 3 Oct 2016 13:43:20 +0100 Subject: 39545: Add some missing unqueue_signals(). All of these are added simply to fit existing logic in other branches. --- ChangeLog | 5 +++++ Src/Zle/computil.c | 1 + Src/Zle/zle_main.c | 1 + Src/builtin.c | 3 +++ Src/exec.c | 3 +++ Src/hist.c | 1 + Src/init.c | 4 +++- Src/mem.c | 8 ++++++-- Src/module.c | 1 + Src/params.c | 2 ++ Src/prompt.c | 4 +++- 11 files changed, 29 insertions(+), 4 deletions(-) (limited to 'Src/params.c') diff --git a/ChangeLog b/ChangeLog index a1c4e60e3..a68dfaf59 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,10 @@ 2016-10-03 Peter Stephenson + * 39545: Src/builtin.c, Src/exec.c, Src/hist.c, Src/init.c, + Src/mem.c, Src/module.c, Src/params.c, Src/prompt.c, + Src/Zle/computil.c, Src/Zle/zle_main.c: Add some missing + unqueue_signals(). + * 39521: Src/exec.c, Src/zsh.h, Test/A01grammar.ztst: Refactor start of execcmd(). This allows execpline2() easier access to the state at the start of execuation. diff --git a/Src/Zle/computil.c b/Src/Zle/computil.c index 27b78cd61..e9bad1cab 100644 --- a/Src/Zle/computil.c +++ b/Src/Zle/computil.c @@ -4865,6 +4865,7 @@ bin_compfiles(char *nam, char **args, UNUSED(Options ops), UNUSED(int func)) } queue_signals(); if (!(tmp = getaparam(args[1]))) { + unqueue_signals(); zwarnnam(nam, "unknown parameter: %s", args[1]); return 0; } diff --git a/Src/Zle/zle_main.c b/Src/Zle/zle_main.c index 0bdd82ba4..0b3b1fcf4 100644 --- a/Src/Zle/zle_main.c +++ b/Src/Zle/zle_main.c @@ -1631,6 +1631,7 @@ bin_vared(char *name, char **args, Options ops, UNUSED(int func)) return 1; } else if (v) { if (*s) { + unqueue_signals(); zwarnnam(name, "not an identifier: `%s'", args[0]); return 1; } diff --git a/Src/builtin.c b/Src/builtin.c index 60dc07f25..a274ff791 100644 --- a/Src/builtin.c +++ b/Src/builtin.c @@ -1489,6 +1489,7 @@ bin_fc(char *nam, char **argv, Options ops, int func) } if (zleactive) { + unqueue_signals(); zwarnnam(nam, "no interactive history within ZLE"); return 1; } @@ -2808,6 +2809,7 @@ bin_typeset(char *name, char **argv, LinkList assigns, Options ops, int func) return 0; } if (off & PM_TIED) { + unqueue_signals(); zerrnam(name, "use unset to remove tied variables"); return 1; } @@ -3138,6 +3140,7 @@ bin_functions(char *name, char **argv, Options ops, int func) queue_signals(); for (q = mathfuncs; q; q = q->next) { if (!strcmp(q->name, funcname)) { + unqueue_signals(); zwarnnam(name, "-M %s: function already exists", funcname); zsfree(p->name); diff --git a/Src/exec.c b/Src/exec.c index a4294288b..9890286b2 100644 --- a/Src/exec.c +++ b/Src/exec.c @@ -1795,6 +1795,8 @@ execpline(Estate state, wordcode slcode, int how, int last1) deletejob(jn, 0); thisjob = pj; } + else + unqueue_signals(); if ((slflags & WC_SUBLIST_NOT) && !errflag) lastval = !lastval; } @@ -5556,6 +5558,7 @@ runshfunc(Eprog prog, FuncWrap wrap, char *name) if (!cont) { if (ou) zfree(ou, ouu); + unqueue_signals(); return; } wrap = wrap->next; diff --git a/Src/hist.c b/Src/hist.c index 5fc40bd67..eebd7dcde 100644 --- a/Src/hist.c +++ b/Src/hist.c @@ -653,6 +653,7 @@ histsubchar(int c) (c == '}' || c == ';' || c == '\'' || c == '"' || c == '`')) { /* Neither event nor word designator, no expansion */ safeinungetc(c); + unqueue_signals(); return bangchar; } *ptr = 0; diff --git a/Src/init.c b/Src/init.c index 3dea179b9..c12043b88 100644 --- a/Src/init.c +++ b/Src/init.c @@ -1442,8 +1442,10 @@ sourcehome(char *s) queue_signals(); if (EMULATION(EMULATE_SH|EMULATE_KSH) || !(h = getsparam_u("ZDOTDIR"))) { h = home; - if (!h) + if (!h) { + unqueue_signals(); return; + } } { diff --git a/Src/mem.c b/Src/mem.c index 021dad573..db311efbd 100644 --- a/Src/mem.c +++ b/Src/mem.c @@ -903,11 +903,15 @@ memory_validate(Heapid heap_id) queue_signals(); for (h = heaps; h; h = h->next) { - if (h->heap_id == heap_id) + if (h->heap_id == heap_id) { + unqueue_signals(); return 0; + } for (hs = heaps->sp; hs; hs = hs->next) { - if (hs->heap_id == heap_id) + if (hs->heap_id == heap_id) { + unqueue_signals(); return 0; + } } } diff --git a/Src/module.c b/Src/module.c index 46a7d7746..41f142adb 100644 --- a/Src/module.c +++ b/Src/module.c @@ -2242,6 +2242,7 @@ load_module(char const *name, Feature_enables enablesarr, int silent) return 0; } if (m->node.flags & MOD_BUSY) { + unqueue_signals(); zerr("circular dependencies for module ;%s", name); return 1; } diff --git a/Src/params.c b/Src/params.c index e11510246..1418021aa 100644 --- a/Src/params.c +++ b/Src/params.c @@ -2803,6 +2803,7 @@ assignsparam(char *s, char *val, int flags) zerr("read-only variable: %s", v->pm->node.nam); *ss = '['; zsfree(val); + unqueue_signals(); return NULL; } flags &= ~ASSPM_WARN_CREATE; @@ -3117,6 +3118,7 @@ setnparam(char *s, mnumber val) if (!(v = getvalue(&vbuf, &t, 1))) { DPUTS(!v, "BUG: value not found for new parameter"); /* errflag |= ERRFLAG_ERROR; */ + unqueue_signals(); return NULL; } if (!was_unset && isset(WARNCREATEGLOBAL) && locallevel > forklevel) diff --git a/Src/prompt.c b/Src/prompt.c index d4f389809..ee77c8bc8 100644 --- a/Src/prompt.c +++ b/Src/prompt.c @@ -491,8 +491,10 @@ putpromptchar(int doprint, int endchar, unsigned int *txtchangep) if (!arg) arg++; queue_signals(); - if (!(hostnam = getsparam("HOST"))) + if (!(hostnam = getsparam("HOST"))) { + unqueue_signals(); break; + } if (arg < 0) { for (ss = hostnam + strlen(hostnam); ss > hostnam; ss--) if (ss[-1] == '.' && !++arg) -- cgit v1.2.3 From 0f5e670cde5f844680a20f986786249dfe983584 Mon Sep 17 00:00:00 2001 From: "Barton E. Schaefer" Date: Mon, 24 Oct 2016 07:14:39 -0700 Subject: "typeset -p" uses "export" commands or the "-g" option for parameters that are not local to the current scope --- ChangeLog | 9 +++++++++ NEWS | 3 +++ README | 5 +++++ Src/params.c | 22 +++++++++++++++++----- Test/B02typeset.ztst | 4 ++-- Test/B03print.ztst | 4 ++-- Test/V10private.ztst | 2 +- 7 files changed, 39 insertions(+), 10 deletions(-) (limited to 'Src/params.c') diff --git a/ChangeLog b/ChangeLog index 717f25e76..ee1fd94dc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2016-10-24 Barton E. Schaefer + + * unposted: NEWS, README: update for 39704. + + * 39704: Src/params.c, Test/B02typeset.ztst, Test/B03print.ztst, + Test/V10private.ztst: the output of "typeset -p" uses "export" + commands or the "-g" option for parameters that are not local to + the current scope. + 2016-10-24 Daniel Shahaf * 39706: Completion/Unix/Type/_tilde_files, Doc/Zsh/compsys.yo: diff --git a/NEWS b/NEWS index 65b246d33..35e0e2e5d 100644 --- a/NEWS +++ b/NEWS @@ -15,6 +15,9 @@ removed, even when /before/here is itself a symbolic link. It is recommended to review uses of ':A' and, if appropriate, convert them to ':P' as soon as compatibility with 5.2 is no longer a requirement. +The output of "typeset -p" uses "export" commands or the "-g" option +for parameters that are not local to the current scope. + Changes from 5.1.1 to 5.2 ------------------------- diff --git a/README b/README index ed2183d8d..1a2e73936 100644 --- a/README +++ b/README @@ -110,6 +110,11 @@ possible to return a non-zero status to the parent shell from a command executed as a replacement, and the new implementation is more consistent with other shells. +7) The output of "typeset -p" (and synonyms) now takes into account the +function scope and export state of each parameter. Exported parameters +are output as "export" commands unless the parameter is also local, and +other parameters not local to the scope are output with the "-g" option. + Incompatibilities between 5.0.8 and 5.2 --------------------------------------- diff --git a/Src/params.c b/Src/params.c index 1418021aa..3084b1ffe 100644 --- a/Src/params.c +++ b/Src/params.c @@ -5225,7 +5225,7 @@ printparamvalue(Param p, int printflags) { char *t, **u; - if (p->node.flags & PM_AUTOLOAD) { + if ((p->node.flags & PM_EXPORTED) && !p->env) { putchar('\n'); return; } @@ -5312,9 +5312,13 @@ printparamnode(HashNode hn, int printflags) */ printflags |= PRINT_NAMEONLY; } + else if (p->node.flags & PM_EXPORTED) + printflags |= PRINT_NAMEONLY; else return; } + if (p->node.flags & PM_AUTOLOAD) + printflags |= PRINT_NAMEONLY; if (printflags & PRINT_TYPESET) { if ((p->node.flags & (PM_READONLY|PM_SPECIAL)) == @@ -5326,7 +5330,14 @@ printparamnode(HashNode hn, int printflags) */ return; } - printf("typeset "); + if (locallevel && p->level >= locallevel) { + printf("typeset "); /* printf("local "); */ + } else if (p->node.flags & PM_EXPORTED) { + printf("export "); + } else if (locallevel) { + printf("typeset -g "); + } else + printf("typeset "); } /* Print the attributes of the parameter */ @@ -5339,7 +5350,9 @@ printparamnode(HashNode hn, int printflags) if (pmptr->flags & PMTF_TEST_LEVEL) { if (p->level) doprint = 1; - } else if (p->node.flags & pmptr->binflag) + } else if ((pmptr->binflag != PM_EXPORTED || + ((p->node.flags & PM_LOCAL) || p->level)) && + (p->node.flags & pmptr->binflag)) doprint = 1; if (doprint) { @@ -5351,9 +5364,8 @@ printparamnode(HashNode hn, int printflags) } putchar(pmptr->typeflag); } - } else { + } else printf("%s ", pmptr->string); - } if ((pmptr->flags & PMTF_USE_BASE) && p->base) { printf("%d ", p->base); doneminus = 0; diff --git a/Test/B02typeset.ztst b/Test/B02typeset.ztst index d6d24210b..6d85a63fe 100644 --- a/Test/B02typeset.ztst +++ b/Test/B02typeset.ztst @@ -454,7 +454,7 @@ fn() { typeset -p array nonexistent; } fn 1:declare -p shouldn't create scoped values ->typeset -a array=( foo bar ) +>typeset -g -a array=( foo bar ) ?fn:typeset: no such variable: nonexistent unsetopt typesetsilent @@ -490,7 +490,7 @@ ?0 ?(eval):5: read-only variable: pbro ?(eval):6: read-only variable: pbro -?typeset -r pbro +?typeset -g -r pbro ?0 ?(eval):10: read-only variable: pbro diff --git a/Test/B03print.ztst b/Test/B03print.ztst index befe2f2dd..a4431cbc8 100644 --- a/Test/B03print.ztst +++ b/Test/B03print.ztst @@ -308,5 +308,5 @@ printf -v foo "%s\0%s-" into the breach typeset -p foo 0:print and printf into a variable ->typeset foo='once more' ->typeset foo=$'into\C-@the-breach\C-@-' +>typeset -g foo='once more' +>typeset -g foo=$'into\C-@the-breach\C-@-' diff --git a/Test/V10private.ztst b/Test/V10private.ztst index 320e35764..7ebf5a87f 100644 --- a/Test/V10private.ztst +++ b/Test/V10private.ztst @@ -129,7 +129,7 @@ 0:private hides value from surrounding scope in nested scope >typeset -a hash_test=( top level ) >typeset -A hash_test=( in function ) ->typeset -a hash_test=( top level ) +>typeset -g -a hash_test=( top level ) >array-local top level >top level F:note "typeset" rather than "private" in output from outer -- cgit v1.2.3 From ab81b98c49ace618f5a1607faf718e0b2e43948d Mon Sep 17 00:00:00 2001 From: "Barton E. Schaefer" Date: Sat, 29 Oct 2016 11:56:50 -0700 Subject: 39758: revise 39704 for array and hash parameters; more POSIXBUITINS tweaks for export 39704 was commit 0f5e670, forgot to reference article number in that log. "typeset -p" outputs "typeset" for array and hash parameters, even when exported, because those types can be marked export but are never pushed to the enviroment. For POSIXBUILTINS, "export var" does not implicitly set $var, and its export state is preserved when assigned (but not when explicitly unset). --- ChangeLog | 8 ++++++++ Src/builtin.c | 14 ++++++++++---- Src/params.c | 16 ++++++++-------- 3 files changed, 26 insertions(+), 12 deletions(-) (limited to 'Src/params.c') diff --git a/ChangeLog b/ChangeLog index f7487f01a..c453aee84 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2016-10-29 Barton E. Schaefer + + * 39758: Src/builtin.c, Src/params.c: revise 39704 to output + "typeset" for array and hash parameters, even when exported; for + POSIXBUILTINS, "export var" does not implicitly set $var, and its + export state is preserved when assigned (but not when explicitly + unset). + 2016-10-28 Daniel Shahaf * users/22036: Doc/Zsh/zle.yo: bracketed-paste: Document diff --git a/Src/builtin.c b/Src/builtin.c index 2db739ffc..986ace238 100644 --- a/Src/builtin.c +++ b/Src/builtin.c @@ -2008,11 +2008,12 @@ typeset_single(char *cname, char *pname, Param pm, UNUSED(int func), * handled in createparam(). Here we just avoid using it for the * present tests if it's unset. * - * POSIXBUILTINS horror: we need to retain the 'readonly' flag - * of an unset parameter. + * POSIXBUILTINS horror: we need to retain the 'readonly' or 'export' + * flags of an unset parameter. */ usepm = pm && (!(pm->node.flags & PM_UNSET) || - (isset(POSIXBUILTINS) && (pm->node.flags & PM_READONLY))); + (isset(POSIXBUILTINS) && + (pm->node.flags & (PM_READONLY|PM_EXPORTED)))); /* * We need to compare types with an existing pm if special, @@ -2135,7 +2136,8 @@ typeset_single(char *cname, char *pname, Param pm, UNUSED(int func), /* * Stricter rules about retaining readonly attribute in this case. */ - if ((on & PM_READONLY) && (!usepm || (pm->node.flags & PM_UNSET)) && + if ((on & (PM_READONLY|PM_EXPORTED)) && + (!usepm || (pm->node.flags & PM_UNSET)) && !ASG_VALUEP(asg)) on |= PM_UNSET; else if (usepm && (pm->node.flags & PM_READONLY) && @@ -2143,6 +2145,10 @@ typeset_single(char *cname, char *pname, Param pm, UNUSED(int func), zerr("read-only variable: %s", pm->node.nam); return NULL; } + /* This is handled by createparam(): + if (usepm && (pm->node.flags & PM_EXPORTED) && !(off & PM_EXPORTED)) + on |= PM_EXPORTED; + */ } /* diff --git a/Src/params.c b/Src/params.c index 3084b1ffe..330f22bb2 100644 --- a/Src/params.c +++ b/Src/params.c @@ -940,7 +940,10 @@ createparam(char *name, int flags) zerr("%s: restricted", name); return NULL; } - if (!(oldpm->node.flags & PM_UNSET) || (oldpm->node.flags & PM_SPECIAL)) { + if (!(oldpm->node.flags & PM_UNSET) || + (oldpm->node.flags & PM_SPECIAL) || + /* POSIXBUILTINS horror: we need to retain 'export' flags */ + (isset(POSIXBUILTINS) && (oldpm->node.flags & PM_EXPORTED))) { oldpm->node.flags &= ~PM_UNSET; if ((oldpm->node.flags & PM_SPECIAL) && oldpm->ename) { Param altpm = @@ -5225,10 +5228,6 @@ printparamvalue(Param p, int printflags) { char *t, **u; - if ((p->node.flags & PM_EXPORTED) && !p->env) { - putchar('\n'); - return; - } if (printflags & PRINT_KV_PAIR) putchar(' '); else @@ -5332,7 +5331,8 @@ printparamnode(HashNode hn, int printflags) } if (locallevel && p->level >= locallevel) { printf("typeset "); /* printf("local "); */ - } else if (p->node.flags & PM_EXPORTED) { + } else if ((p->node.flags & PM_EXPORTED) && + !(p->node.flags & (PM_ARRAY|PM_HASHED))) { printf("export "); } else if (locallevel) { printf("typeset -g "); @@ -5350,8 +5350,8 @@ printparamnode(HashNode hn, int printflags) if (pmptr->flags & PMTF_TEST_LEVEL) { if (p->level) doprint = 1; - } else if ((pmptr->binflag != PM_EXPORTED || - ((p->node.flags & PM_LOCAL) || p->level)) && + } else if ((pmptr->binflag != PM_EXPORTED || p->level || + (p->node.flags & (PM_LOCAL|PM_ARRAY|PM_HASHED))) && (p->node.flags & pmptr->binflag)) doprint = 1; -- cgit v1.2.3 From 68a576bc552af1a5484fda9d5e28eff7ca5a2364 Mon Sep 17 00:00:00 2001 From: Sebastian Gniazdowski Date: Tue, 8 Nov 2016 02:27:04 -0800 Subject: 39869: can transfer ownership of core of array when assigning --- ChangeLog | 3 +++ Src/params.c | 11 ++++++++--- 2 files changed, 11 insertions(+), 3 deletions(-) (limited to 'Src/params.c') diff --git a/ChangeLog b/ChangeLog index 39ff8c7ec..4409e6ea2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2016-11-08 Peter Stephenson + * Sebastian: 39869: can transfer ownership of core of array when + assigning. + * 39867: Src/utils.c: cast to unsigned char to compare against 0x7f. diff --git a/Src/params.c b/Src/params.c index 330f22bb2..0894241b9 100644 --- a/Src/params.c +++ b/Src/params.c @@ -2647,15 +2647,20 @@ setarrvalue(Value v, char **val) for (i = 0; i < v->start; i++) *p++ = i < pre_assignment_length ? ztrdup(*q++) : ztrdup(""); - for (r = val; *r;) - *p++ = ztrdup(*r++); + for (r = val; *r;) { + /* Give away ownership of the string */ + *p++ = *r++; + } if (v->end < pre_assignment_length) for (q = old + v->end; *q;) *p++ = ztrdup(*q++); *p = NULL; v->pm->gsu.a->setfn(v->pm, new); - freearray(val); + + /* Ownership of all strings has been + * given away, can plainly free */ + free(val); } } -- cgit v1.2.3 From 06e4ec853a2ee0bde0efb8ed6c0fad2ac4162942 Mon Sep 17 00:00:00 2001 From: Sebastian Gniazdowski Date: Tue, 8 Nov 2016 05:37:53 -0800 Subject: 39871: cut down number of strlen()s in getstrvalue() --- ChangeLog | 8 ++++++-- Src/params.c | 17 +++++++++++++---- Src/string.c | 13 +++++++++++++ 3 files changed, 32 insertions(+), 6 deletions(-) (limited to 'Src/params.c') diff --git a/ChangeLog b/ChangeLog index e89b0c616..629a7a5b7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2016-11-08 Peter Stephenson + + * Sebastian: 39871: cut down number of strlen()s in getstrvalue(). + 2016-11-08 Jun-ichi Takimoto * 39857: Completion/Unix/Command/_top: add support for darwin, @@ -5,8 +9,8 @@ 2016-11-08 Peter Stephenson - * Src/builtin.c, Test/C03traps.ztst: ensure exit trap can always - run. + * 39870: Src/builtin.c, Test/C03traps.ztst: ensure exit trap can + always run. * unposted: Src/utils.c: follow up to 39867: don't need test against zero any more. diff --git a/Src/params.c b/Src/params.c index 0894241b9..19a8c291d 100644 --- a/Src/params.c +++ b/Src/params.c @@ -2060,6 +2060,7 @@ getstrvalue(Value v) { char *s, **ss; char buf[BDIGBUFSIZE]; + int len = -1; if (!v) return hcalloc(1); @@ -2237,22 +2238,30 @@ getstrvalue(Value v) return s; if (v->start < 0) { - v->start += strlen(s); + len = strlen(s); + v->start += len; if (v->start < 0) v->start = 0; } if (v->end < 0) { - v->end += strlen(s); + if (len < 0) + len = strlen(s); + v->end += len; if (v->end >= 0) { char *eptr = s + v->end; if (*eptr) v->end += MB_METACHARLEN(eptr); } } - s = (v->start > (int)strlen(s)) ? dupstring("") : dupstring(s + v->start); + + if (len < 0) + len = strlen(s); + s = (v->start > len) ? dupstring("") : + dupstring_wlen(s + v->start, len - v->start); + if (v->end <= v->start) s[0] = '\0'; - else if (v->end - v->start <= (int)strlen(s)) + else if (v->end - v->start <= len - v->start) s[v->end - v->start] = '\0'; return s; diff --git a/Src/string.c b/Src/string.c index 04e7446c9..b46ea60cf 100644 --- a/Src/string.c +++ b/Src/string.c @@ -41,6 +41,19 @@ dupstring(const char *s) return t; } +/**/ +mod_export char * +dupstring_wlen(const char *s, unsigned len) +{ + char *t; + + if (!s) + return NULL; + t = (char *) zhalloc(len + 1); + strcpy(t, s); + return t; +} + /**/ mod_export char * ztrdup(const char *s) -- cgit v1.2.3 From 49407686b47fed0e4810e0ba6127a9589c05b68b Mon Sep 17 00:00:00 2001 From: Sebastian Gniazdowski Date: Tue, 8 Nov 2016 08:05:05 -0800 Subject: 39875: add dupstring_glen to avoid redundant strlen calls --- ChangeLog | 5 +++++ Src/params.c | 4 ++-- Src/string.c | 17 +++++++++++++++++ 3 files changed, 24 insertions(+), 2 deletions(-) (limited to 'Src/params.c') diff --git a/ChangeLog b/ChangeLog index 272264163..416ecf114 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2016-11-09 Peter Stephenson + + * Sebastian: 39875: Src/params.c, Src/string.c: add + dupstring_glen() to avoid redundant strlen() calls. + 2016-11-09 Daniel Shahaf * 39853: Completion/Unix/Command/_subversion: Accept long diff --git a/Src/params.c b/Src/params.c index 19a8c291d..3f0179267 100644 --- a/Src/params.c +++ b/Src/params.c @@ -2432,8 +2432,8 @@ assignstrvalue(Value v, char *val, int flags) char *z, *x; int zlen; - z = dupstring(v->pm->gsu.s->getfn(v->pm)); - zlen = strlen(z); + z = dupstring_glen(v->pm->gsu.s->getfn(v->pm), (unsigned*) &zlen); + if ((v->flags & VALFLAG_INV) && unset(KSHARRAYS)) v->start--, v->end--; if (v->start < 0) { diff --git a/Src/string.c b/Src/string.c index b46ea60cf..a8da14fe0 100644 --- a/Src/string.c +++ b/Src/string.c @@ -41,6 +41,8 @@ dupstring(const char *s) return t; } +/* Duplicate string on heap when length is known */ + /**/ mod_export char * dupstring_wlen(const char *s, unsigned len) @@ -54,6 +56,21 @@ dupstring_wlen(const char *s, unsigned len) return t; } +/* Duplicate string on heap, returning length of string */ + +/**/ +mod_export char * +dupstring_glen(const char *s, unsigned *len_ret) +{ + char *t; + + if (!s) + return NULL; + t = (char *) zhalloc((*len_ret = strlen((char *)s)) + 1); + strcpy(t, s); + return t; +} + /**/ mod_export char * ztrdup(const char *s) -- cgit v1.2.3 From a1633e09a761b9135a0a7084d2489d359a004e5a Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Wed, 9 Nov 2016 11:54:57 +0000 Subject: 39886 based on 39877: Optimise arrdup to arrdup_max. Only duplicate as much of the array as is needed. --- ChangeLog | 3 +++ Src/params.c | 24 +++++++++++++++++------- Src/utils.c | 25 +++++++++++++++++++++++++ 3 files changed, 45 insertions(+), 7 deletions(-) (limited to 'Src/params.c') diff --git a/ChangeLog b/ChangeLog index 416ecf114..8d2f472b8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2016-11-09 Peter Stephenson + * 39886 based on 39877 (Sebastian): Src/params.c, Src/utils.c: + add arrdup_max() so as not to duplicate entire arrays unnecessarily. + * Sebastian: 39875: Src/params.c, Src/string.c: add dupstring_glen() to avoid redundant strlen() calls. diff --git a/Src/params.c b/Src/params.c index 3f0179267..772345bd1 100644 --- a/Src/params.c +++ b/Src/params.c @@ -2294,14 +2294,24 @@ getarrvalue(Value v) v->start += arrlen(s); if (v->end < 0) v->end += arrlen(s) + 1; - if (arrlen_lt(s, v->start) || v->start < 0) + + /* Null if 1) array too short, 2) index still negative */ + if (arrlen_lt(s, v->start) || v->start < 0) { s = arrdup(nular); - else - s = arrdup(s + v->start); - if (v->end <= v->start) - s[0] = NULL; - else if (arrlen_ge(s, v->end - v->start)) - s[v->end - v->start] = NULL; + } else if (v->end <= v->start) { + s = arrdup_max(s, 1); + s[0] = NULL; + } else { + /* Copy to a point before the end of the source array: + * arrdup_max will copy at most v->end - v->start elements, + * starting from v->start element. Original code said: + * s[v->end - v->start] = NULL + * which means that there are exactly the same number of + * elements as the value of the above *0-based* index. + */ + s = arrdup_max(s + v->start, v->end - v->start); + } + return s; } diff --git a/Src/utils.c b/Src/utils.c index 93e757ce8..3d535b85c 100644 --- a/Src/utils.c +++ b/Src/utils.c @@ -4229,6 +4229,31 @@ arrdup(char **s) return y; } +/* Duplicate at most max elements of the array s with heap memory */ + +/**/ +mod_export char ** +arrdup_max(char **s, unsigned max) +{ + char **x, **y, **send; + int len; + + len = arrlen(s); + + /* Limit has sense only if not equal to len */ + if (max > len) + max = len; + + y = x = (char **) zhalloc(sizeof(char *) * (max + 1)); + + send = s + max; + while (s < send) + *x++ = dupstring(*s++); + *x = NULL; + + return y; +} + /**/ mod_export char ** zarrdup(char **s) -- cgit v1.2.3 From 65ea1a033b1feeea30d9ad6deca93d6e771904ea Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Wed, 9 Nov 2016 13:45:11 +0000 Subject: 39887: no need to conditionalise assignment of strlen() --- ChangeLog | 3 +++ Src/params.c | 8 ++------ 2 files changed, 5 insertions(+), 6 deletions(-) (limited to 'Src/params.c') diff --git a/ChangeLog b/ChangeLog index 8d2f472b8..320ee3fca 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2016-11-09 Peter Stephenson + * 39887: Src/params.c: no need to conditionalise assignment of + strlen in getstrvalue(). + * 39886 based on 39877 (Sebastian): Src/params.c, Src/utils.c: add arrdup_max() so as not to duplicate entire arrays unnecessarily. diff --git a/Src/params.c b/Src/params.c index 772345bd1..ef72cba44 100644 --- a/Src/params.c +++ b/Src/params.c @@ -2060,7 +2060,7 @@ getstrvalue(Value v) { char *s, **ss; char buf[BDIGBUFSIZE]; - int len = -1; + int len; if (!v) return hcalloc(1); @@ -2237,15 +2237,13 @@ getstrvalue(Value v) if (v->start == 0 && v->end == -1) return s; + len = strlen(s); if (v->start < 0) { - len = strlen(s); v->start += len; if (v->start < 0) v->start = 0; } if (v->end < 0) { - if (len < 0) - len = strlen(s); v->end += len; if (v->end >= 0) { char *eptr = s + v->end; @@ -2254,8 +2252,6 @@ getstrvalue(Value v) } } - if (len < 0) - len = strlen(s); s = (v->start > len) ? dupstring("") : dupstring_wlen(s + v->start, len - v->start); -- cgit v1.2.3 From 7139b737246a75b8c08ab10124a0131bddc0ca04 Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Tue, 8 Nov 2016 15:46:40 +0000 Subject: 39874/0001: setarrvalue: Remove needless initialization. --- ChangeLog | 5 +++++ Src/params.c | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'Src/params.c') diff --git a/ChangeLog b/ChangeLog index a9c47878b..893b16e2c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2016-11-11 Daniel Shahaf + + * 39874/0001: Src/params.c: setarrvalue: Remove needless + initialization. + 2016-11-10 Peter Stephenson * 39901: Src/exec.c, Test/C03traps.ztst: Exiting the left hand diff --git a/Src/params.c b/Src/params.c index ef72cba44..86a094b1f 100644 --- a/Src/params.c +++ b/Src/params.c @@ -2657,8 +2657,8 @@ setarrvalue(Value v, char **val) if (v->end <= pre_assignment_length) post_assignment_length += pre_assignment_length - v->end + 1; - p = new = (char **) zshcalloc(sizeof(char *) - * (post_assignment_length + 1)); + p = new = (char **) zalloc(sizeof(char *) + * (post_assignment_length + 1)); for (i = 0; i < v->start; i++) *p++ = i < pre_assignment_length ? ztrdup(*q++) : ztrdup(""); -- cgit v1.2.3 From d676d1bf4bb4ca2bf7d4bcc3a824940f6648f6ff Mon Sep 17 00:00:00 2001 From: "Barton E. Schaefer" Date: Thu, 10 Nov 2016 21:01:32 -0800 Subject: 39893: use arrdup_max() to show explicitly the difference in two code branches no functional change --- ChangeLog | 5 +++++ Src/params.c | 5 ++--- 2 files changed, 7 insertions(+), 3 deletions(-) (limited to 'Src/params.c') diff --git a/ChangeLog b/ChangeLog index ee314487c..839548045 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2016-11-10 Barton E. Schaefer + + * 39893: Src/params.c: use arrdup_max() to show explicitly the + difference in two code branches; no functional change + 2016-11-11 Daniel Shahaf * 39874/0002 plus size=0 handling: Src/mem.c: zshcalloc: Remove diff --git a/Src/params.c b/Src/params.c index 86a094b1f..6f587a30a 100644 --- a/Src/params.c +++ b/Src/params.c @@ -2293,10 +2293,9 @@ getarrvalue(Value v) /* Null if 1) array too short, 2) index still negative */ if (arrlen_lt(s, v->start) || v->start < 0) { - s = arrdup(nular); + s = arrdup_max(nular, 1); } else if (v->end <= v->start) { - s = arrdup_max(s, 1); - s[0] = NULL; + s = arrdup_max(nular, 0); } else { /* Copy to a point before the end of the source array: * arrdup_max will copy at most v->end - v->start elements, -- cgit v1.2.3 From 3fd50d06a12da8b4a9b4201272ca1f08fabd415e Mon Sep 17 00:00:00 2001 From: Jun-ichi Takimoto Date: Tue, 15 Nov 2016 00:17:35 +0900 Subject: 39937: fix a problem introduced by 39886. $a[i,j] should become an empty array if i>j. --- ChangeLog | 5 +++++ Src/params.c | 7 ++++--- 2 files changed, 9 insertions(+), 3 deletions(-) (limited to 'Src/params.c') diff --git a/ChangeLog b/ChangeLog index 27e01c232..150430113 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2016-11-15 Jun-ichi Takimoto + + * 39937: Src/params.c: fix a problem introduced by 39886. + $a[i,j] should become an empty array if i>j. + 2016-11-14 Peter Stephenson * 39906: Src/utils.c: More optimisation of multibyte handling diff --git a/Src/params.c b/Src/params.c index 6f587a30a..3c8658cc3 100644 --- a/Src/params.c +++ b/Src/params.c @@ -2292,10 +2292,11 @@ getarrvalue(Value v) v->end += arrlen(s) + 1; /* Null if 1) array too short, 2) index still negative */ - if (arrlen_lt(s, v->start) || v->start < 0) { + if (v->end <= v->start) { + s = arrdup_max(nular, 0); + } + else if (arrlen_lt(s, v->start) || v->start < 0) { s = arrdup_max(nular, 1); - } else if (v->end <= v->start) { - s = arrdup_max(nular, 0); } else { /* Copy to a point before the end of the source array: * arrdup_max will copy at most v->end - v->start elements, -- cgit v1.2.3 From f35198d8379303f47c935d8fdd18bc1a76a111aa Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Sun, 20 Nov 2016 11:46:48 +0000 Subject: 39992: setarrvalue: Allocate a correctly-sized array. No memory was lost; the array was allocated with room for one (char *) element more than was required. --- ChangeLog | 3 +++ Src/params.c | 12 ++++++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) (limited to 'Src/params.c') diff --git a/ChangeLog b/ChangeLog index cdaa0c1fe..13e52e51b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2016-11-20 Daniel Shahaf + * 39992: Src/params.c: setarrvalue: Allocate a correctly-sized + array. + * unposted (after 39952): Src/Zle/zle_params.c: Restore C89 compatibility. diff --git a/Src/params.c b/Src/params.c index 3c8658cc3..9d741cb7b 100644 --- a/Src/params.c +++ b/Src/params.c @@ -2654,8 +2654,13 @@ setarrvalue(Value v, char **val) v->end = v->start; post_assignment_length = v->start + arrlen(val); - if (v->end <= pre_assignment_length) - post_assignment_length += pre_assignment_length - v->end + 1; + if (v->end < pre_assignment_length) { + /* + * Allocate room for array elements between the end of the slice `v' + * and the original array's end. + */ + post_assignment_length += pre_assignment_length - v->end; + } p = new = (char **) zalloc(sizeof(char *) * (post_assignment_length + 1)); @@ -2671,6 +2676,9 @@ setarrvalue(Value v, char **val) *p++ = ztrdup(*q++); *p = NULL; + DPUTS2(p - new != post_assignment_length, "setarrvalue: wrong allocation: %d 1= %lu", + post_assignment_length, (unsigned long)(p - new)); + v->pm->gsu.a->setfn(v->pm, new); /* Ownership of all strings has been -- cgit v1.2.3 From 368884a3aacd9852ae1310346695dbf2240e863b Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Sun, 20 Nov 2016 19:41:52 +0000 Subject: 39995 (from 39977): Optimise string parameter assignment. If setter is the standard one and string length is unchnaged we can copy into place. --- ChangeLog | 3 ++ Src/params.c | 39 ++++++++++++--- Test/A06assign.ztst | 140 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 174 insertions(+), 8 deletions(-) (limited to 'Src/params.c') diff --git a/ChangeLog b/ChangeLog index 3a917f59c..7b05d39d3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2016-11-20 Peter Stephenson + * 39995 (from 39977): Src/params.c, Test/A06assign.ztst: + optimisation of string assignment if length is unchanged. + * Mikel Ward: 39978: Doc/Zsh/jobs.yo: more accurate documentation of searching for job by string. diff --git a/Src/params.c b/Src/params.c index 9d741cb7b..a79debc93 100644 --- a/Src/params.c +++ b/Src/params.c @@ -2436,9 +2436,10 @@ assignstrvalue(Value v, char *val, int flags) v->pm->width = strlen(val); } else { char *z, *x; - int zlen; + int zlen, vlen, newsize; - z = dupstring_glen(v->pm->gsu.s->getfn(v->pm), (unsigned*) &zlen); + z = v->pm->gsu.s->getfn(v->pm); + zlen = strlen(z); if ((v->flags & VALFLAG_INV) && unset(KSHARRAYS)) v->start--, v->end--; @@ -2469,12 +2470,34 @@ assignstrvalue(Value v, char *val, int flags) } else if (v->end > zlen) v->end = zlen; - x = (char *) zalloc(v->start + strlen(val) + zlen - v->end + 1); - strncpy(x, z, v->start); - strcpy(x + v->start, val); - strcat(x + v->start, z + v->end); - v->pm->gsu.s->setfn(v->pm, x); - zsfree(val); + + vlen = strlen(val); + /* Characters preceding start index + + characters of what is assigned + + characters following end index */ + newsize = v->start + vlen + (zlen - v->end); + + /* Does new size differ? */ + if (newsize != zlen || v->pm->gsu.s->setfn != strsetfn) { + x = (char *) zalloc(newsize + 1); + strncpy(x, z, v->start); + strcpy(x + v->start, val); + strcat(x + v->start, z + v->end); + v->pm->gsu.s->setfn(v->pm, x); + } else { + Param pm = v->pm; + /* Size doesn't change, can limit actions to only + * overwriting bytes in already allocated string */ + strncpy(z + v->start, val, vlen); + /* Implement remainder of strsetfn */ + if (!(pm->node.flags & PM_HASHELEM) && + ((pm->node.flags & PM_NAMEDDIR) || + isset(AUTONAMEDIRS))) { + pm->node.flags |= PM_NAMEDDIR; + adduserdir(pm->node.nam, z, 0, 0); + } + } + zsfree(val); } break; case PM_INTEGER: diff --git a/Test/A06assign.ztst b/Test/A06assign.ztst index da4e3b0fe..bf39aee7f 100644 --- a/Test/A06assign.ztst +++ b/Test/A06assign.ztst @@ -489,3 +489,143 @@ print $array 0:slice beyond length of array >FIRST + +# tests of string assignments + + a="abc" + a[1]=x + print $a +0:overwrite first character in string +>xbc + + a="abc" + a[2]="x" + print $a +0:overwrite middle character in string +>axc + + a="abc" + a[3]="x" + print $a +0:overwrite last character in string +>abx + + a="abc" + a[-1]="x" + print $a +0:overwrite -1 character in string +>abx + + a="abc" + a[-2]="x" + print $a +0:overwrite -2 character (middle) in string +>axc + + a="ab" + a[-2]="x" + print $a +0:overwrite -2 character (first) in string +>xb + + a="abc" + a[-3]="x" + print $a +0:overwrite -3 character (first) in string +>xbc + + a="abc" + a[-4]="x" + print $a +0:overwrite -4 character (before first) in string +>xabc + + a="abc" + a[-5]="x" + print $a +0:overwrite -5 character (before-before first) in string +>xabc + + a="abc" + a[-4,0]="x" + print $a +0:overwrite [-4,0] characters (before first) in string +>xabc + + a="abc" + a[-4,-4]="x" + print $a +0:overwrite [-4,-4] character (before first) in string +>xabc + + a="abc" + a[-40,-30]="x" + print $a +0:overwrite [-40,-30] characters (far before first) in string +>xabc + + a="abc" + a[-40,1]="x" + print $a +0:overwrite [-40,1] characters in short string +>xbc + + a="abc" + a[-40,40]="x" + print $a +0:overwrite [-40,40] characters in short string +>x + + a="abc" + a[2,40]="x" + print $a +0:overwrite [2,40] characters in short string +>ax + + a="abc" + a[2,-1]="x" + print $a +0:overwrite [2,-1] characters in short string +>ax + + a="abc" + a[-2,-1]="x" + print $a +0:overwrite [-2,-1] characters in short string +>ax + + a="a" + a[-1]="xx" + print $a +0:overwrite [-1] character with "xx" +>xx + + a="a" + a[-2]="xx" + print $a +0:overwrite [-2] character (before first) with "xx" +>xxa + + a="a" + a[2]="xx" + print $a +0:overwrite [2] character (after last) with "xx" +>axx + + a="" + a[1]="xx" + print $a +0:overwrite [1] character (string: "") with "xx" +>xx + + a="" + a[-1]="xx" + print $a +0:overwrite [-1] character (string: "") with "xx" +>xx + + a="" + a[2]="xx" + print $a +0:overwrite [2] character (string: "") with "xx" +>xx -- cgit v1.2.3 From dae21874d498ccd3f947f6f47e5ec23feb2bdcb4 Mon Sep 17 00:00:00 2001 From: Guillaume Maudoux Date: Wed, 9 Nov 2016 17:14:33 +0100 Subject: 39900: Add TERMINFO_DIRS special like TERMINFO. Although this is a colon-separated array there is no tied array. --- ChangeLog | 4 ++++ Doc/Zsh/params.yo | 18 ++++++++++++++---- Src/params.c | 31 +++++++++++++++++++++++++++++++ 3 files changed, 49 insertions(+), 4 deletions(-) (limited to 'Src/params.c') diff --git a/ChangeLog b/ChangeLog index 7b05d39d3..e21a269e4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2016-11-20 Peter Stephenson + * Guillaume Maudoux: 39900 (doc slightly tweaked): Src/params.c, + Doc/Zsh/params.yo: Add TERMINFO_DIRS special colon-separated + array, not tied. + * 39995 (from 39977): Src/params.c, Test/A06assign.ztst: optimisation of string assignment if length is unchanged. diff --git a/Doc/Zsh/params.yo b/Doc/Zsh/params.yo index 0db8a1c0e..905e92d22 100644 --- a/Doc/Zsh/params.yo +++ b/Doc/Zsh/params.yo @@ -1493,10 +1493,20 @@ take effect. ) vindex(TERMINFO) item(tt(TERMINFO) )( -A reference to a compiled description of the terminal, used by the -`terminfo' library when the system has it; see manref(terminfo)(5). -If set, this causes the shell to reinitialise the terminal, making -the workaround `tt(TERM=$TERM)' unnecessary. +A reference to your terminfo database, used by the `terminfo' library when the +system has it; see manref(terminfo)(5). +If set, this causes the shell to reinitialise the terminal, making the +workaround `tt(TERM=$TERM)' unnecessary. +) +vindex(TERMINFO_DIRS) +item(tt(TERMINFO_DIRS) )( +A colon-seprarated list of terminfo databases, used by the `terminfo' library +when the system has it; see manref(terminfo)(5). This variable is only +used by certain terminal libraries, in particular ncurses; see +manref(terminfo)(5) to check support on your system. If set, this +causes the shell to reinitialise the terminal, making the workaround +`tt(TERM=$TERM)' unnecessary. Note that unlike other colon-separated +arrays this is not tied to a zsh array. ) vindex(TIMEFMT) item(tt(TIMEFMT))( diff --git a/Src/params.c b/Src/params.c index a79debc93..45f398a27 100644 --- a/Src/params.c +++ b/Src/params.c @@ -87,6 +87,7 @@ char *ifs, /* $IFS */ *postedit, /* $POSTEDIT */ *term, /* $TERM */ *zsh_terminfo, /* $TERMINFO */ + *zsh_terminfodirs, /* $TERMINFO_DIRS */ *ttystrname, /* $TTY */ *pwd; /* $PWD */ @@ -208,6 +209,8 @@ static const struct gsu_scalar term_gsu = { termgetfn, termsetfn, stdunsetfn }; static const struct gsu_scalar terminfo_gsu = { terminfogetfn, terminfosetfn, stdunsetfn }; +static const struct gsu_scalar terminfodirs_gsu = +{ terminfodirsgetfn, terminfodirssetfn, stdunsetfn }; static const struct gsu_scalar wordchars_gsu = { wordcharsgetfn, wordcharssetfn, stdunsetfn }; static const struct gsu_scalar ifs_gsu = @@ -283,6 +286,7 @@ IPDEF2("histchars", histchars_gsu, PM_DONTIMPORT), IPDEF2("HOME", home_gsu, PM_UNSET), IPDEF2("TERM", term_gsu, PM_UNSET), IPDEF2("TERMINFO", terminfo_gsu, PM_UNSET), +IPDEF2("TERMINFO_DIRS", terminfodirs_gsu, PM_UNSET), IPDEF2("WORDCHARS", wordchars_gsu, 0), IPDEF2("IFS", ifs_gsu, PM_DONTIMPORT | PM_RESTRICTED), IPDEF2("_", underscore_gsu, PM_DONTIMPORT), @@ -4548,6 +4552,33 @@ terminfosetfn(Param pm, char *x) term_reinit_from_pm(); } +/* Function to get value of special parameter `TERMINFO_DIRS' */ + +/**/ +char * +terminfodirsgetfn(UNUSED(Param pm)) +{ + return zsh_terminfodirs ? zsh_terminfodirs : dupstring(""); +} + +/* Function to set value of special parameter `TERMINFO_DIRS' */ + +/**/ +void +terminfodirssetfn(Param pm, char *x) +{ + zsfree(zsh_terminfodirs); + zsh_terminfodirs = x; + + /* + * terminfo relies on the value being exported before + * we reinitialise the terminal. This is a bit inefficient. + */ + if ((pm->node.flags & PM_EXPORTED) && x) + addenv(pm, x); + + term_reinit_from_pm(); +} /* Function to get value for special parameter `pipestatus' */ /**/ -- cgit v1.2.3 From a9fe87e18cbe37d938fb1a02f71f8f905141e0f4 Mon Sep 17 00:00:00 2001 From: "Barton E. Schaefer" Date: Tue, 29 Nov 2016 12:31:33 -0800 Subject: 40032: consistency in handling of subscript slices outside the bounds of an array parameter unposted: README: example describing 40032 --- ChangeLog | 7 +++++++ README | 39 +++++++++++++++++++++++++++++++++++++++ Src/params.c | 11 +++++++++-- 3 files changed, 55 insertions(+), 2 deletions(-) (limited to 'Src/params.c') diff --git a/ChangeLog b/ChangeLog index 27c35849a..6ed44eb4c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2016-11-29 Barton E. Schaefer + + * unposted: README: example describing 40032 + + * 40032: Src/params.c: consistency in handling of subscript + slices outside the bounds of an array parameter + 2016-11-29 Peter Stephenson * 40037: Joshua Rubin: Unicode 9 character width support. diff --git a/README b/README index 568f1ad6c..eed8e4d5b 100644 --- a/README +++ b/README @@ -121,6 +121,45 @@ Previously, only "typeset" commands were output, never using "-g". would be accepted to mean [Y]. Now and are invalid choices: typing either of them remains at the prompt. +9) The $ary[i,j] subscript syntax to take a slice of an array behaves +differently when both i and j are larger than the number of elements in +the array. When i == j, such a slice always yields an empty array, and +when i < j it always yields an array of one empty string element. The +following example illustrates how this differs from past versions. + + nargs() { print $# } + a=(one two) + for i in 1 2 3 4; do + for j in 1 2 3 4 5; do + print -n "$i $j => " + nargs "${(@)a[i,j]}" + done + done + + 5.2 | 5.3 ** + ----------+---------- + 1 1 => 1 | 1 1 => 1 + 1 2 => 2 | 1 2 => 2 + 1 3 => 2 | 1 3 => 2 + 1 4 => 2 | 1 4 => 2 + 1 5 => 2 | 1 5 => 2 + 2 1 => 0 | 2 1 => 0 + 2 2 => 1 | 2 2 => 1 + 2 3 => 1 | 2 3 => 1 + 2 4 => 1 | 2 4 => 1 + 2 5 => 1 | 2 5 => 1 + 3 1 => 0 | 3 1 => 0 + 3 2 => 0 | 3 2 => 0 + 3 3 => 0 | 3 3 => 0 + 3 4 => 0 | 3 4 => 1 ** + 3 5 => 0 | 3 5 => 1 ** + 4 1 => 0 | 4 1 => 0 + 4 2 => 0 | 4 2 => 0 + 4 3 => 0 | 4 3 => 0 + 4 4 => 1 | 4 4 => 0 ** + 4 5 => 1 | 4 5 => 1 + + Incompatibilities between 5.0.8 and 5.2 --------------------------------------- diff --git a/Src/params.c b/Src/params.c index 45f398a27..aa8b196bd 100644 --- a/Src/params.c +++ b/Src/params.c @@ -2299,9 +2299,16 @@ getarrvalue(Value v) if (v->end <= v->start) { s = arrdup_max(nular, 0); } - else if (arrlen_lt(s, v->start) || v->start < 0) { + else if (v->start < 0) { s = arrdup_max(nular, 1); - } else { + } + else if (arrlen_le(s, v->start)) { + /* Handle $ary[i,i] consistently for any $i > $#ary + * and $ary[i,j] consistently for any $j > $i > $#ary + */ + s = arrdup_max(nular, v->end - (v->start + 1)); + } + else { /* Copy to a point before the end of the source array: * arrdup_max will copy at most v->end - v->start elements, * starting from v->start element. Original code said: -- cgit v1.2.3