From 7d3220f2981c81dbd3cbde873c1bb4d540c92574 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Mon, 16 Aug 2004 09:52:56 +0000 Subject: 20251: integer conversion truncation 20258: save command status in prompt substitution update FAQ rename version to 4.2.1-dev-1 --- ChangeLog | 14 +++++++ Config/version.mk | 4 +- Doc/Zsh/options.yo | 3 +- Etc/FAQ.yo | 39 +++++------------ Src/math.c | 120 ++++++++++++++++++++++++++++++++--------------------- Src/prompt.c | 4 +- Src/utils.c | 51 ++++++++++++++++++++--- 7 files changed, 149 insertions(+), 86 deletions(-) diff --git a/ChangeLog b/ChangeLog index c0396eacc..707367ec6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2004-08-16 Peter Stephenson + + * unposted: rename version to 4.2.1-dev-1 so as to avoid + confusion with the released version. + + * unposted: update Etc/FAQ.yo as already sent to ftp.zsh.org + + * 20258: Doc/Zsh/options.yo, Src/prompt.c: save command status + as well as error flag when performing substitutions in prompts. + + * 20251: Src/math.c, Src/utils.c: Warn when an integer converted + from a string is too long and truncate it rather than let it + overflow. + 2004-08-13 Clint Adams * unposted: config.guess, config.sub: update to 2004-07-19 and diff --git a/Config/version.mk b/Config/version.mk index 7a0c1aeb7..590fc1e89 100644 --- a/Config/version.mk +++ b/Config/version.mk @@ -27,5 +27,5 @@ # This must also serve as a shell script, so do not add spaces around the # `=' signs. -VERSION=4.2.1 -VERSION_DATE='August 13, 2004' +VERSION=4.2.1-dev-1 +VERSION_DATE='August 16, 2004' diff --git a/Doc/Zsh/options.yo b/Doc/Zsh/options.yo index 2ef11bf3e..49f65d186 100644 --- a/Doc/Zsh/options.yo +++ b/Doc/Zsh/options.yo @@ -895,7 +895,8 @@ pindex(PROMPT_SUBST) cindex(prompt, parameter expansion) item(tt(PROMPT_SUBST) )( If set, em(parameter expansion), em(command substitution) and -em(arithmetic expansion) are performed in prompts. +em(arithmetic expansion) are performed in prompts. Substitutions +within prompts do not affect the command status. ) pindex(TRANSIENT_RPROMPT) item(tt(TRANSIENT_RPROMPT))( diff --git a/Etc/FAQ.yo b/Etc/FAQ.yo index b89213cc3..2dcde5261 100644 --- a/Etc/FAQ.yo +++ b/Etc/FAQ.yo @@ -43,20 +43,14 @@ whenlatex(report(ARG1)(ARG2)(ARG3))\ whenman(report(ARG1)(ARG2)(ARG3))\ whenms(report(ARG1)(ARG2)(ARG3))\ whensgml(report(ARG1)(ARG2)(ARG3))) -myreport(Z-Shell Frequently-Asked Questions)(Peter Stephenson)(2001/06/25) +myreport(Z-Shell Frequently-Asked Questions)(Peter Stephenson)(2004/08/13) COMMENT(-- the following are for Usenet and must appear first)\ description(\ mydit(Archive-Name:) unix-faq/shell/zsh -mydit(Last-Modified:) 2001/06/25 +mydit(Last-Modified:) 2001/08/13 mydit(Submitted-By:) email(pws@pwstephenson.fsnet.co.uk (Peter Stephenson)) mydit(Posting-Frequency:) Monthly -mydit(Copyright:) (C) P.W. Stephenson, 1995--2001 (see end of document) -) - -bf(Changes since last issue posted:) -description( - mydit(1.6) 4.0.2 nearly released. - mydit(3.1) typeset splitting incompatibility and tt(KSH_TYPESET) option +mydit(Copyright:) (C) P.W. Stephenson, 1995--2004 (see end of document) ) This document contains a list of frequently-asked (or otherwise @@ -299,23 +293,12 @@ sect(On what machines will it run?) sect(What's the latest version?) - Zsh 4.0.2 is the latest production version. - - Zsh 3.0.8 was the previous production version. The major number 3.0 - largely reflected considerable internal changes in zsh to make it more - reliable, consistent and (where possible) compatible. Those planning on - upgrading their zsh installation should take a look at the list of - incompatibilities at the end of link(5.1)(51). This is longer than usual - due to enhanced sh, ksh and POSIX compatibility. + Zsh 4.2.1 is the latest production version. - There will not be any further 3.0 releases now that 4.0 has become - the stable version. However, a few patches to 3.0.8 are available from - the patch manager at Sourceforge, \ -url(http://sourceforge.net/patch/?group_id=4068)\ -(http://www.sourceforge.net/patch/?group_id=4068) - Official patches are posted by Bart Schaefer (user name tt(barts)). + There will not be any further 4.0 releases now that 4.2 has become + the stable version. - A beta of the next version is often available. Development of zsh is + A beta of the next version is sometimes available. Development of zsh is patch by patch, with each intermediate version publicly available. Note that this `open' development system does mean bugs are sometimes introduced into the most recent archived version. These are usually @@ -416,7 +399,7 @@ url(http://www.math.technion.ac.il/pub/zsh/) (ftp://ftp.blarg.net/users/amol/zsh) ) - There is no port of 4.0 for Windows, but newer releases compile under + There is no port of version 4 for Windows, but newer releases compile under Cygwin, a freely available UNIX-style environment for the Win32 API. You can find information about this at url(http://sourceware.cygnus.com/cygwin)\ @@ -543,7 +526,7 @@ label(21) effect of single-letter option flags as if the shell had been invoked with the appropriate name. Including the command `emulate sh; setopt localoptions' in a shell function will - turn on sh emulation for that function only. In 4.0 (and in + turn on sh emulation for that function only. In version 4 (and in 3.0.6 through 8), this can be abbreviated as `emulate -L sh'. ) @@ -887,8 +870,8 @@ mytt(compctl) verb( bindkey '\eq' push-input ) - to save the entire buffer. In 4.0 and recent versions of zsh 3.1, you - have the following more sophisticated option, + to save the entire buffer. In version 4 and recent versions of zsh 3.1, + you have the following more sophisticated option, verb( run-fg-editor() { zle push-input diff --git a/Src/math.c b/Src/math.c index eb3a768ec..ce316414e 100644 --- a/Src/math.c +++ b/Src/math.c @@ -186,6 +186,68 @@ static int type[TOKCOUNT] = /* 50 */ LR|OP_OPF, RL|OP_E2, LR|OP_OPF }; +static int +lexconstant(void) +{ +#ifdef USE_LOCALE + char *prev_locale; +#endif + char *nptr; + + nptr = ptr; + if (*nptr == '-') + nptr++; + + if (*nptr == '0') + { + nptr++; + if (*nptr == 'x' || *nptr == 'X') { + /* Let zstrtol parse number with base */ + yyval.u.l = zstrtol(ptr, &ptr, 0); + /* Should we set lastbase here? */ + lastbase = 16; + return NUM; + } + else if (isset(OCTALZEROES) && + (memchr(nptr, '.', strlen(nptr)) == NULL) && + idigit(*nptr)) { + yyval.u.l = zstrtol(ptr, &ptr, 0); + lastbase = 8; + return NUM; + } + } + + while (idigit(*nptr)) + nptr++; + + if (*nptr == '.' || *nptr == 'e' || *nptr == 'E') { + /* it's a float */ + yyval.type = MN_FLOAT; +#ifdef USE_LOCALE + prev_locale = dupstring(setlocale(LC_NUMERIC, NULL)); + setlocale(LC_NUMERIC, "POSIX"); +#endif + yyval.u.d = strtod(ptr, &nptr); +#ifdef USE_LOCALE + if (prev_locale) setlocale(LC_NUMERIC, prev_locale); +#endif + if (ptr == nptr || *nptr == '.') { + zerr("bad floating point constant", NULL, 0); + return EOI; + } + ptr = nptr; + } else { + /* it's an integer */ + yyval.u.l = zstrtol(ptr, &ptr, 10); + + if (*ptr == '#') { + ptr++; + yyval.u.l = zstrtol(ptr, &ptr, lastbase = yyval.u.l); + } + } + return NUM; +} + /**/ int outputradix; @@ -193,9 +255,6 @@ int outputradix; static int zzlex(void) { -#ifdef USE_LOCALE - char *prev_locale; -#endif int cct = 0; yyval.type = MN_INTEGER; @@ -220,7 +279,14 @@ zzlex(void) ptr++; return MINUSEQ; } - return (unary) ? UMINUS : MINUS; + if (unary) { + if (idigit(*ptr) || *ptr == '.') { + ptr--; + return lexconstant(); + } else + return UMINUS; + } else + return MINUS; case '(': return M_INPAR; case ')': @@ -376,52 +442,10 @@ zzlex(void) case '\t': case '\n': break; - case '0': - if (*ptr == 'x' || *ptr == 'X') { - ptr++; - /* Should we set lastbase here? */ - yyval.u.l = zstrtol(ptr, &ptr, lastbase = 16); - return NUM; - } - else if (isset(OCTALZEROES) && - (memchr(ptr, '.', strlen(ptr)) == NULL) && - idigit(*ptr)) { - yyval.u.l = zstrtol(ptr, &ptr, lastbase = 8); - return NUM; - } /* Fall through! */ default: - if (idigit(*--ptr) || *ptr == '.') { - char *nptr; - for (nptr = ptr; idigit(*nptr); nptr++); - - if (*nptr == '.' || *nptr == 'e' || *nptr == 'E') { - /* it's a float */ - yyval.type = MN_FLOAT; -#ifdef USE_LOCALE - prev_locale = dupstring(setlocale(LC_NUMERIC, NULL)); - setlocale(LC_NUMERIC, "POSIX"); -#endif - yyval.u.d = strtod(ptr, &nptr); -#ifdef USE_LOCALE - if (prev_locale) setlocale(LC_NUMERIC, prev_locale); -#endif - if (ptr == nptr || *nptr == '.') { - zerr("bad floating point constant", NULL, 0); - return EOI; - } - ptr = nptr; - } else { - /* it's an integer */ - yyval.u.l = zstrtol(ptr, &ptr, 10); - - if (*ptr == '#') { - ptr++; - yyval.u.l = zstrtol(ptr, &ptr, lastbase = yyval.u.l); - } - } - return NUM; - } + if (idigit(*--ptr) || *ptr == '.') + return lexconstant(); if (*ptr == '#') { if (*++ptr == '\\' || *ptr == '#') { int v; diff --git a/Src/prompt.c b/Src/prompt.c index b05bbf110..c0e73fb5f 100644 --- a/Src/prompt.c +++ b/Src/prompt.c @@ -163,13 +163,15 @@ promptexpand(char *s, int ns, char *rs, char *Rs) if (isset(PROMPTSUBST)) { int olderr = errflag; + int oldval = lastval; s = dupstring(s); if (!parsestr(s)) singsub(&s); - /* Ignore errors in prompt substitution */ + /* Ignore errors and status change in prompt substitution */ errflag = olderr; + lastval = oldval; } rstring = rs; diff --git a/Src/utils.c b/Src/utils.c index 678376eae..143855160 100644 --- a/Src/utils.c +++ b/Src/utils.c @@ -1261,7 +1261,8 @@ skipparens(char inpar, char outpar, char **s) mod_export zlong zstrtol(const char *s, char **t, int base) { - zlong ret = 0; + const char *inp, *trunc = NULL; + zulong calc = 0, newcalc = 0; int neg; while (inblank(*s)) @@ -1280,16 +1281,54 @@ zstrtol(const char *s, char **t, int base) else base = 8; } + inp = s; if (base <= 10) - for (; *s >= '0' && *s < ('0' + base); s++) - ret = ret * base + *s - '0'; + for (; *s >= '0' && *s < ('0' + base); s++) { + if (trunc) + continue; + newcalc = calc * base + *s - '0'; + if (newcalc < calc) + { + trunc = s; + continue; + } + calc = newcalc; + } else for (; idigit(*s) || (*s >= 'a' && *s < ('a' + base - 10)) - || (*s >= 'A' && *s < ('A' + base - 10)); s++) - ret = ret * base + (idigit(*s) ? (*s - '0') : (*s & 0x1f) + 9); + || (*s >= 'A' && *s < ('A' + base - 10)); s++) { + if (trunc) + continue; + newcalc = calc*base + (idigit(*s) ? (*s - '0') : (*s & 0x1f) + 9); + if (newcalc < calc) + { + trunc = s; + continue; + } + calc = newcalc; + } + + /* + * Special case: check for a number that was just too long for + * signed notation. + * Extra special case: the lowest negative number would trigger + * the first test, but is actually representable correctly. + * This is a 1 in the top bit, all others zero, so test for + * that explicitly. + */ + if (!trunc && (zlong)calc < 0 && + (!neg || calc & ~((zulong)1 << (8*sizeof(zulong)-1)))) + { + trunc = s - 1; + calc /= base; + } + + if (trunc) + zwarn("number truncated after %d digits: %s", inp, trunc - inp); + if (t) *t = (char *)s; - return neg ? -ret : ret; + return neg ? -(zlong)calc : (zlong)calc; } /**/ -- cgit 1.4.1