From 609b311919dba3d07f7af04e85e7970150aed0ae Mon Sep 17 00:00:00 2001 From: tg Date: Wed, 29 Apr 2015 20:07:35 +0000 Subject: [PATCH] more low-hanging fruits for EBCDIC; notes: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit • ord() new, From: Daniel Richard G. ‣ used in some places • (c - '0') → ksh_numdig(c) # may take *x++ argument • (c - 'A') → ksh_numuc(c) # may NOT take *x+= argument ‣ idem for ksh_numlc(c) and 'a' ‣ these need changing for EBCDIC ‣ add testsuite for this • use macros more, they exist already often • use digits_lc[foo] instead of ('0' + foo), especially for letters • caught another ksh_eq case… • also caught a maybe-UB overflow check, but we don’t have TIME_T_MAX ☹ --- check.t | 16 +++++++++++++++- edit.c | 16 ++++++++-------- funcs.c | 9 ++++++--- lex.c | 4 ++-- main.c | 34 +++++++++++++--------------------- misc.c | 34 ++++++++++++++++------------------ sh.h | 12 +++++++++--- shf.c | 20 +++++++++++--------- syn.c | 11 ++++++----- var.c | 8 ++++---- 10 files changed, 90 insertions(+), 74 deletions(-) diff --git a/check.t b/check.t index 77d68a4..4670955 100644 --- a/check.t +++ b/check.t @@ -1,4 +1,4 @@ -# $MirOS: src/bin/mksh/check.t,v 1.690 2015/04/19 19:18:03 tg Exp $ +# $MirOS: src/bin/mksh/check.t,v 1.691 2015/04/29 20:07:30 tg Exp $ # -*- mode: sh -*- #- # Copyright © 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, @@ -4545,6 +4545,20 @@ expected-stdout: 64 64 --- +name: integer-base-8 +description: + Check that base-36 works (full span) +stdin: + echo 1:$((36#109AZ)). + typeset -i36 x=1691675 + echo 2:$x. + typeset -Uui36 x + echo 3:$x. +expected-stdout: + 1:1691675. + 2:36#109az. + 3:36#109AZ. +--- name: integer-base-check-flat description: Check behaviour does not match POSuX (except if set -o posix), diff --git a/edit.c b/edit.c index 96283f6..9166004 100644 --- a/edit.c +++ b/edit.c @@ -28,7 +28,7 @@ #ifndef MKSH_NO_CMDLINE_EDITING -__RCSID("$MirOS: src/bin/mksh/edit.c,v 1.284 2015/04/11 22:09:48 tg Exp $"); +__RCSID("$MirOS: src/bin/mksh/edit.c,v 1.285 2015/04/29 20:07:31 tg Exp $"); /* * in later versions we might use libtermcap for this, but since external @@ -2966,7 +2966,7 @@ x_set_arg(int c) /* strip command prefix */ c &= 255; while (c >= 0 && ksh_isdigit(c)) { - n = n * 10 + (c - '0'); + n = n * 10 + ksh_numdig(c); if (n > LINE) /* upper bound for repeat */ goto x_set_arg_too_big; @@ -3627,8 +3627,8 @@ vi_hook(int ch) return (1); cmdlen = 0; argc1 = 0; - if (ch >= '1' && ch <= '9') { - argc1 = ch - '0'; + if (ch >= ord('1') && ch <= ord('9')) { + argc1 = ksh_numdig(ch); state = VARG1; } else { curcmd[cmdlen++] = ch; @@ -3672,7 +3672,7 @@ vi_hook(int ch) case VARG1: if (ksh_isdigit(ch)) - argc1 = argc1 * 10 + ch - '0'; + argc1 = argc1 * 10 + ksh_numdig(ch); else { curcmd[cmdlen++] = ch; state = nextstate(ch); @@ -3681,8 +3681,8 @@ vi_hook(int ch) case VEXTCMD: argc2 = 0; - if (ch >= '1' && ch <= '9') { - argc2 = ch - '0'; + if (ch >= ord('1') && ch <= ord('9')) { + argc2 = ksh_numdig(ch); state = VARG2; return (0); } else { @@ -3698,7 +3698,7 @@ vi_hook(int ch) case VARG2: if (ksh_isdigit(ch)) - argc2 = argc2 * 10 + ch - '0'; + argc2 = argc2 * 10 + ksh_numdig(ch); else { if (argc1 == 0) argc1 = argc2; diff --git a/funcs.c b/funcs.c index 6fde4fb..dea8fa6 100644 --- a/funcs.c +++ b/funcs.c @@ -38,7 +38,7 @@ #endif #endif -__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.269 2015/04/29 18:32:43 tg Exp $"); +__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.270 2015/04/29 20:07:32 tg Exp $"); #if HAVE_KILLPG /* @@ -1666,8 +1666,11 @@ c_umask(const char **wp) mode_t new_umask; if (ksh_isdigit(*cp)) { - for (new_umask = 0; *cp >= '0' && *cp <= '7'; cp++) - new_umask = new_umask * 8 + (*cp - '0'); + new_umask = 0; + while (*cp >= ord('0') && *cp <= ord('7')) { + new_umask = new_umask * 8 + ksh_numdig(*cp); + ++cp; + } if (*cp) { bi_errorf("bad number"); return (1); diff --git a/lex.c b/lex.c index 8ca64cd..3046e52 100644 --- a/lex.c +++ b/lex.c @@ -23,7 +23,7 @@ #include "sh.h" -__RCSID("$MirOS: src/bin/mksh/lex.c,v 1.200 2015/04/19 18:50:36 tg Exp $"); +__RCSID("$MirOS: src/bin/mksh/lex.c,v 1.201 2015/04/29 20:07:33 tg Exp $"); /* * states while lexing word @@ -920,7 +920,7 @@ yylex(int cf) goto no_iop; if (!ksh_isdigit(dp[c2 + 1])) goto no_iop; - iop->unit = (iop->unit * 10) + dp[c2 + 1] - '0'; + iop->unit = iop->unit * 10 + ksh_numdig(dp[c2 + 1]); if (iop->unit >= FDBASE) goto no_iop; } diff --git a/main.c b/main.c index d39ed4c..8bb4f0d 100644 --- a/main.c +++ b/main.c @@ -34,7 +34,7 @@ #include #endif -__RCSID("$MirOS: src/bin/mksh/main.c,v 1.292 2015/04/19 18:50:37 tg Exp $"); +__RCSID("$MirOS: src/bin/mksh/main.c,v 1.293 2015/04/29 20:07:33 tg Exp $"); extern char **environ; @@ -1459,7 +1459,7 @@ check_fd(const char *name, int mode, const char **emsgp) if (name[0] == 'p' && !name[1]) return (coproc_getfd(mode, emsgp)); while (ksh_isdigit(*name)) { - fd = (fd * 10) + *name - '0'; + fd = fd * 10 + ksh_numdig(*name); if (fd >= FDBASE) { if (emsgp) *emsgp = "file descriptor too large"; @@ -1613,28 +1613,20 @@ maketemp(Area *ap, Temp_type type, struct temp **tlist) memcpy(cp, "/shXXXXXX.tmp", 14); /* point to the first of six Xes */ cp += 3; - /* generate random part of filename */ - len = -1; - do { - i = rndget() % 36; - cp[++len] = i < 26 ? 'a' + i : '0' + i - 26; - } while (len < 5); /* cyclically attempt to open a temporary file */ - while ((i = open(tp->tffn, O_CREAT | O_EXCL | O_RDWR | O_BINARY, - 0600)) < 0) { - if (errno != EEXIST) + do { + /* generate random part of filename */ + len = 0; + do { + cp[len++] = digits_lc[rndget() % 36]; + } while (len < 6); + + /* check if this one works */ + if ((i = open(tp->tffn, O_CREAT | O_EXCL | O_RDWR | O_BINARY, + 0600)) < 0 && errno != EEXIST) goto maketemp_out; - /* count down from z to a then from 9 to 0 */ - while (cp[len] == '0') - if (!len--) - goto maketemp_out; - if (cp[len] == 'a') - cp[len] = '9'; - else - --cp[len]; - /* do another cycle */ - } + } while (i < 0); if (type == TT_FUNSUB) { /* map us high and mark as close-on-exec */ diff --git a/misc.c b/misc.c index 0a13f99..7bb5baa 100644 --- a/misc.c +++ b/misc.c @@ -30,7 +30,7 @@ #include #endif -__RCSID("$MirOS: src/bin/mksh/misc.c,v 1.228 2015/04/29 18:38:52 tg Exp $"); +__RCSID("$MirOS: src/bin/mksh/misc.c,v 1.229 2015/04/29 20:07:34 tg Exp $"); #define KSH_CHVT_FLAG #ifdef MKSH_SMALL @@ -95,10 +95,8 @@ initctypes(void) { int c; - for (c = 'a'; c <= 'z'; c++) - chtypes[c] |= C_ALPHA; - for (c = 'A'; c <= 'Z'; c++) - chtypes[c] |= C_ALPHA; + setctypes(digits_uc, C_ALPHA); + setctypes(digits_lc, C_ALPHA); chtypes['_'] |= C_ALPHA; setctypes("0123456789", C_DIGIT); /* \0 added automatically */ @@ -545,7 +543,7 @@ getn(const char *s, int *ai) if (num.u > 214748364U) /* overflow on multiplication */ return (0); - num.u = num.u * 10U + (unsigned int)(c - '0'); + num.u = num.u * 10U + (unsigned int)ksh_numdig(c); /* now: num.u <= 2147483649U */ } while ((c = *s++)); @@ -2194,8 +2192,8 @@ unbksl(bool cstyle, int (*fg)(void), void (*fp)(int)) wc = 0; i = 3; while (i--) - if ((c = (*fg)()) >= '0' && c <= '7') - wc = (wc << 3) + (c - '0'); + if ((c = (*fg)()) >= ord('0') && c <= ord('7')) + wc = (wc << 3) + ksh_numdig(c); else { (*fp)(c); break; @@ -2204,13 +2202,13 @@ unbksl(bool cstyle, int (*fg)(void), void (*fp)(int)) case 'U': i = 8; if (/* CONSTCOND */ 0) - /* FALLTHROUGH */ + /* FALLTHROUGH */ case 'u': - i = 4; + i = 4; if (/* CONSTCOND */ 0) - /* FALLTHROUGH */ + /* FALLTHROUGH */ case 'x': - i = cstyle ? -1 : 2; + i = cstyle ? -1 : 2; /** * x: look for a hexadecimal number with up to * two (C style: arbitrary) digits; convert @@ -2221,12 +2219,12 @@ unbksl(bool cstyle, int (*fg)(void), void (*fp)(int)) wc = 0; while (i--) { wc <<= 4; - if ((c = (*fg)()) >= '0' && c <= '9') - wc += c - '0'; - else if (c >= 'A' && c <= 'F') - wc += c - 'A' + 10; - else if (c >= 'a' && c <= 'f') - wc += c - 'a' + 10; + if ((c = (*fg)()) >= ord('0') && c <= ord('9')) + wc += ksh_numdig(c); + else if (c >= ord('A') && c <= ord('F')) + wc += ksh_numuc(c) + 10; + else if (c >= ord('a') && c <= ord('f')) + wc += ksh_numlc(c) + 10; else { wc >>= 4; (*fp)(c); diff --git a/sh.h b/sh.h index f48b081..05552a6 100644 --- a/sh.h +++ b/sh.h @@ -169,7 +169,7 @@ #endif #ifdef EXTERN -__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.727 2015/04/29 19:11:57 tg Exp $"); +__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.728 2015/04/29 20:07:34 tg Exp $"); #endif #define MKSH_VERSION "R51 2015/04/19" @@ -466,6 +466,8 @@ EXTERN const char initvsn[] E_INIT("KSH_VERSION=@(#)" KSH_VERSIONNAME \ EXTERN const char digits_uc[] E_INIT("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"); EXTERN const char digits_lc[] E_INIT("0123456789abcdefghijklmnopqrstuvwxyz"); +#define letters_uc (digits_uc + 10) +#define letters_lc (digits_lc + 10) /* * Evil hack for const correctness due to API brokenness @@ -924,16 +926,20 @@ extern unsigned char chtypes[]; #define ctype(c, t) tobool( ((t) == C_SUBOP2) ? \ (((c) == '#' || (c) == '%') ? 1 : 0) : \ (chtypes[(unsigned char)(c)] & (t)) ) +#define ord(c) ((int)(unsigned char)(c)) #define ksh_isalphx(c) ctype((c), C_ALPHA) #define ksh_isalnux(c) ctype((c), C_ALPHA | C_DIGIT) #define ksh_isdigit(c) (((c) >= '0') && ((c) <= '9')) #define ksh_islower(c) (((c) >= 'a') && ((c) <= 'z')) #define ksh_isupper(c) (((c) >= 'A') && ((c) <= 'Z')) -#define ksh_tolower(c) (((c) >= 'A') && ((c) <= 'Z') ? (c) - 'A' + 'a' : (c)) -#define ksh_toupper(c) (((c) >= 'a') && ((c) <= 'z') ? (c) - 'a' + 'A' : (c)) +#define ksh_tolower(c) (ksh_isupper(c) ? (c) - 'A' + 'a' : (c)) +#define ksh_toupper(c) (ksh_islower(c) ? (c) - 'a' + 'A' : (c)) #define ksh_isdash(s) (((s)[0] == '-') && ((s)[1] == '\0')) #define ksh_isspace(c) ((((c) >= 0x09) && ((c) <= 0x0D)) || ((c) == 0x20)) #define ksh_eq(c,u,l) (((c) | 0x20) == (l)) +#define ksh_numdig(c) ((c) - ord('0')) +#define ksh_numuc(c) ((c) - ord('A')) +#define ksh_numlc(c) ((c) - ord('a')) EXTERN int ifs0 E_INIT(' '); /* for "$*" */ diff --git a/shf.c b/shf.c index 5d167d2..9647ce6 100644 --- a/shf.c +++ b/shf.c @@ -25,7 +25,7 @@ #include "sh.h" -__RCSID("$MirOS: src/bin/mksh/shf.c,v 1.64 2015/02/06 10:09:07 tg Exp $"); +__RCSID("$MirOS: src/bin/mksh/shf.c,v 1.65 2015/04/29 20:07:35 tg Exp $"); /* flags to shf_emptybuf() */ #define EB_READSW 0x01 /* about to switch to reading */ @@ -847,11 +847,11 @@ shf_vfprintf(struct shf *shf, const char *fmt, va_list args) if (ksh_isdigit(c)) { bool overflowed = false; - tmp = c - '0'; + tmp = ksh_numdig(c); while (c = *fmt++, ksh_isdigit(c)) { if (notok2mul(2147483647, tmp, 10)) overflowed = true; - tmp = tmp * 10 + c - '0'; + tmp = tmp * 10 + ksh_numdig(c); } --fmt; if (overflowed) @@ -872,7 +872,7 @@ shf_vfprintf(struct shf *shf, const char *fmt, va_list args) /* nasty format */ break; - if (c >= 'A' && c <= 'Z') { + if (ksh_isupper(c)) { flags |= FL_UPPER; c = ksh_tolower(c); } @@ -917,7 +917,7 @@ shf_vfprintf(struct shf *shf, const char *fmt, va_list args) /* FALLTHROUGH */ case 'u': do { - *--cp = lnum % 10 + '0'; + *--cp = digits_lc[lnum % 10]; lnum /= 10; } while (lnum); @@ -933,7 +933,7 @@ shf_vfprintf(struct shf *shf, const char *fmt, va_list args) case 'o': do { - *--cp = (lnum & 0x7) + '0'; + *--cp = digits_lc[lnum & 0x7]; lnum >>= 3; } while (lnum); @@ -945,7 +945,7 @@ shf_vfprintf(struct shf *shf, const char *fmt, va_list args) const char *digits = (flags & FL_UPPER) ? digits_uc : digits_lc; do { - *--cp = digits[lnum & 0xf]; + *--cp = digits[lnum & 0xF]; lnum >>= 4; } while (lnum); @@ -1013,7 +1013,7 @@ shf_vfprintf(struct shf *shf, const char *fmt, va_list args) s++; nwritten++; if (--precision > 0 && - (*s | 0x20) == 'x') { + ksh_eq(*s, 'X', 'x')) { shf_putc(*s, shf); s++; precision--; @@ -1025,8 +1025,10 @@ shf_vfprintf(struct shf *shf, const char *fmt, va_list args) c = flags & FL_ZERO ? '0' : ' '; if (field < 0) { nwritten += -field; - for ( ; field < 0 ; field++) + while (field < 0) { shf_putc(c, shf); + ++field; + } } } else c = ' '; diff --git a/syn.c b/syn.c index 8dca08e..dafeda9 100644 --- a/syn.c +++ b/syn.c @@ -23,7 +23,7 @@ #include "sh.h" -__RCSID("$MirOS: src/bin/mksh/syn.c,v 1.100 2015/04/11 22:03:32 tg Exp $"); +__RCSID("$MirOS: src/bin/mksh/syn.c,v 1.101 2015/04/29 20:07:35 tg Exp $"); struct nesting_state { int start_token; /* token than began nesting (eg, FOR) */ @@ -214,10 +214,10 @@ synio(int cf) if (iop->unit > 9) { *cp++ = CHAR; - *cp++ = '0' + (iop->unit / 10); + *cp++ = digits_lc[iop->unit / 10]; } *cp++ = CHAR; - *cp++ = '0' + (iop->unit % 10); + *cp++ = digits_lc[iop->unit % 10]; *cp = EOS; iop->ioflag &= ~IOBASH; @@ -1074,7 +1074,8 @@ parse_usec(const char *s, struct timeval *tv) tv->tv_sec = 0; /* parse integral part */ while (ksh_isdigit(*s)) { - tt.tv_sec = tv->tv_sec * 10 + (*s++ - '0'); + tt.tv_sec = tv->tv_sec * 10 + ksh_numdig(*s++); + /*XXX this overflow check maybe UB */ if (tt.tv_sec / 10 != tv->tv_sec) { errno = EOVERFLOW; return (true); @@ -1095,7 +1096,7 @@ parse_usec(const char *s, struct timeval *tv) /* parse decimal fraction */ i = 100000; while (ksh_isdigit(*s)) { - tv->tv_usec += i * (*s++ - '0'); + tv->tv_usec += i * ksh_numdig(*s++); if (i == 1) break; i /= 10; diff --git a/var.c b/var.c index e230db9..57442f6 100644 --- a/var.c +++ b/var.c @@ -28,7 +28,7 @@ #include #endif -__RCSID("$MirOS: src/bin/mksh/var.c,v 1.191 2015/04/29 18:38:54 tg Exp $"); +__RCSID("$MirOS: src/bin/mksh/var.c,v 1.192 2015/04/29 20:07:35 tg Exp $"); /*- * Variables @@ -553,11 +553,11 @@ getint(struct tbl *vp, mksh_ari_u *nump, bool arith) continue; } if (ksh_isdigit(c)) - c -= '0'; + c = ksh_numdig(c); else if (ksh_isupper(c)) - c -= 'A' - 10; + c = ksh_numuc(c) + 10; else if (ksh_islower(c)) - c -= 'a' - 10; + c = ksh_numlc(c) + 10; else return (-1); if (c >= base)