more low-hanging fruits for EBCDIC; notes:

• ord() new, From: Daniel Richard G. <skunk@iSKUNK.ORG>
  ‣ 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 ☹
This commit is contained in:
tg 2015-04-29 20:07:35 +00:00
parent 3eb806b72b
commit 609b311919
10 changed files with 90 additions and 74 deletions

16
check.t
View File

@ -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 -*- # -*- mode: sh -*-
#- #-
# Copyright © 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, # Copyright © 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
@ -4545,6 +4545,20 @@ expected-stdout:
64 64
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 name: integer-base-check-flat
description: description:
Check behaviour does not match POSuX (except if set -o posix), Check behaviour does not match POSuX (except if set -o posix),

16
edit.c
View File

@ -28,7 +28,7 @@
#ifndef MKSH_NO_CMDLINE_EDITING #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 * in later versions we might use libtermcap for this, but since external
@ -2966,7 +2966,7 @@ x_set_arg(int c)
/* strip command prefix */ /* strip command prefix */
c &= 255; c &= 255;
while (c >= 0 && ksh_isdigit(c)) { while (c >= 0 && ksh_isdigit(c)) {
n = n * 10 + (c - '0'); n = n * 10 + ksh_numdig(c);
if (n > LINE) if (n > LINE)
/* upper bound for repeat */ /* upper bound for repeat */
goto x_set_arg_too_big; goto x_set_arg_too_big;
@ -3627,8 +3627,8 @@ vi_hook(int ch)
return (1); return (1);
cmdlen = 0; cmdlen = 0;
argc1 = 0; argc1 = 0;
if (ch >= '1' && ch <= '9') { if (ch >= ord('1') && ch <= ord('9')) {
argc1 = ch - '0'; argc1 = ksh_numdig(ch);
state = VARG1; state = VARG1;
} else { } else {
curcmd[cmdlen++] = ch; curcmd[cmdlen++] = ch;
@ -3672,7 +3672,7 @@ vi_hook(int ch)
case VARG1: case VARG1:
if (ksh_isdigit(ch)) if (ksh_isdigit(ch))
argc1 = argc1 * 10 + ch - '0'; argc1 = argc1 * 10 + ksh_numdig(ch);
else { else {
curcmd[cmdlen++] = ch; curcmd[cmdlen++] = ch;
state = nextstate(ch); state = nextstate(ch);
@ -3681,8 +3681,8 @@ vi_hook(int ch)
case VEXTCMD: case VEXTCMD:
argc2 = 0; argc2 = 0;
if (ch >= '1' && ch <= '9') { if (ch >= ord('1') && ch <= ord('9')) {
argc2 = ch - '0'; argc2 = ksh_numdig(ch);
state = VARG2; state = VARG2;
return (0); return (0);
} else { } else {
@ -3698,7 +3698,7 @@ vi_hook(int ch)
case VARG2: case VARG2:
if (ksh_isdigit(ch)) if (ksh_isdigit(ch))
argc2 = argc2 * 10 + ch - '0'; argc2 = argc2 * 10 + ksh_numdig(ch);
else { else {
if (argc1 == 0) if (argc1 == 0)
argc1 = argc2; argc1 = argc2;

View File

@ -38,7 +38,7 @@
#endif #endif
#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 #if HAVE_KILLPG
/* /*
@ -1666,8 +1666,11 @@ c_umask(const char **wp)
mode_t new_umask; mode_t new_umask;
if (ksh_isdigit(*cp)) { if (ksh_isdigit(*cp)) {
for (new_umask = 0; *cp >= '0' && *cp <= '7'; cp++) new_umask = 0;
new_umask = new_umask * 8 + (*cp - '0'); while (*cp >= ord('0') && *cp <= ord('7')) {
new_umask = new_umask * 8 + ksh_numdig(*cp);
++cp;
}
if (*cp) { if (*cp) {
bi_errorf("bad number"); bi_errorf("bad number");
return (1); return (1);

4
lex.c
View File

@ -23,7 +23,7 @@
#include "sh.h" #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 * states while lexing word
@ -920,7 +920,7 @@ yylex(int cf)
goto no_iop; goto no_iop;
if (!ksh_isdigit(dp[c2 + 1])) if (!ksh_isdigit(dp[c2 + 1]))
goto no_iop; 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) if (iop->unit >= FDBASE)
goto no_iop; goto no_iop;
} }

34
main.c
View File

@ -34,7 +34,7 @@
#include <locale.h> #include <locale.h>
#endif #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; extern char **environ;
@ -1459,7 +1459,7 @@ check_fd(const char *name, int mode, const char **emsgp)
if (name[0] == 'p' && !name[1]) if (name[0] == 'p' && !name[1])
return (coproc_getfd(mode, emsgp)); return (coproc_getfd(mode, emsgp));
while (ksh_isdigit(*name)) { while (ksh_isdigit(*name)) {
fd = (fd * 10) + *name - '0'; fd = fd * 10 + ksh_numdig(*name);
if (fd >= FDBASE) { if (fd >= FDBASE) {
if (emsgp) if (emsgp)
*emsgp = "file descriptor too large"; *emsgp = "file descriptor too large";
@ -1613,28 +1613,20 @@ maketemp(Area *ap, Temp_type type, struct temp **tlist)
memcpy(cp, "/shXXXXXX.tmp", 14); memcpy(cp, "/shXXXXXX.tmp", 14);
/* point to the first of six Xes */ /* point to the first of six Xes */
cp += 3; 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 */ /* cyclically attempt to open a temporary file */
while ((i = open(tp->tffn, O_CREAT | O_EXCL | O_RDWR | O_BINARY, do {
0600)) < 0) { /* generate random part of filename */
if (errno != EEXIST) 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; goto maketemp_out;
/* count down from z to a then from 9 to 0 */ } while (i < 0);
while (cp[len] == '0')
if (!len--)
goto maketemp_out;
if (cp[len] == 'a')
cp[len] = '9';
else
--cp[len];
/* do another cycle */
}
if (type == TT_FUNSUB) { if (type == TT_FUNSUB) {
/* map us high and mark as close-on-exec */ /* map us high and mark as close-on-exec */

34
misc.c
View File

@ -30,7 +30,7 @@
#include <grp.h> #include <grp.h>
#endif #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 #define KSH_CHVT_FLAG
#ifdef MKSH_SMALL #ifdef MKSH_SMALL
@ -95,10 +95,8 @@ initctypes(void)
{ {
int c; int c;
for (c = 'a'; c <= 'z'; c++) setctypes(digits_uc, C_ALPHA);
chtypes[c] |= C_ALPHA; setctypes(digits_lc, C_ALPHA);
for (c = 'A'; c <= 'Z'; c++)
chtypes[c] |= C_ALPHA;
chtypes['_'] |= C_ALPHA; chtypes['_'] |= C_ALPHA;
setctypes("0123456789", C_DIGIT); setctypes("0123456789", C_DIGIT);
/* \0 added automatically */ /* \0 added automatically */
@ -545,7 +543,7 @@ getn(const char *s, int *ai)
if (num.u > 214748364U) if (num.u > 214748364U)
/* overflow on multiplication */ /* overflow on multiplication */
return (0); 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 */ /* now: num.u <= 2147483649U */
} while ((c = *s++)); } while ((c = *s++));
@ -2194,8 +2192,8 @@ unbksl(bool cstyle, int (*fg)(void), void (*fp)(int))
wc = 0; wc = 0;
i = 3; i = 3;
while (i--) while (i--)
if ((c = (*fg)()) >= '0' && c <= '7') if ((c = (*fg)()) >= ord('0') && c <= ord('7'))
wc = (wc << 3) + (c - '0'); wc = (wc << 3) + ksh_numdig(c);
else { else {
(*fp)(c); (*fp)(c);
break; break;
@ -2204,13 +2202,13 @@ unbksl(bool cstyle, int (*fg)(void), void (*fp)(int))
case 'U': case 'U':
i = 8; i = 8;
if (/* CONSTCOND */ 0) if (/* CONSTCOND */ 0)
/* FALLTHROUGH */ /* FALLTHROUGH */
case 'u': case 'u':
i = 4; i = 4;
if (/* CONSTCOND */ 0) if (/* CONSTCOND */ 0)
/* FALLTHROUGH */ /* FALLTHROUGH */
case 'x': case 'x':
i = cstyle ? -1 : 2; i = cstyle ? -1 : 2;
/** /**
* x: look for a hexadecimal number with up to * x: look for a hexadecimal number with up to
* two (C style: arbitrary) digits; convert * two (C style: arbitrary) digits; convert
@ -2221,12 +2219,12 @@ unbksl(bool cstyle, int (*fg)(void), void (*fp)(int))
wc = 0; wc = 0;
while (i--) { while (i--) {
wc <<= 4; wc <<= 4;
if ((c = (*fg)()) >= '0' && c <= '9') if ((c = (*fg)()) >= ord('0') && c <= ord('9'))
wc += c - '0'; wc += ksh_numdig(c);
else if (c >= 'A' && c <= 'F') else if (c >= ord('A') && c <= ord('F'))
wc += c - 'A' + 10; wc += ksh_numuc(c) + 10;
else if (c >= 'a' && c <= 'f') else if (c >= ord('a') && c <= ord('f'))
wc += c - 'a' + 10; wc += ksh_numlc(c) + 10;
else { else {
wc >>= 4; wc >>= 4;
(*fp)(c); (*fp)(c);

12
sh.h
View File

@ -169,7 +169,7 @@
#endif #endif
#ifdef EXTERN #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 #endif
#define MKSH_VERSION "R51 2015/04/19" #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_uc[] E_INIT("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ");
EXTERN const char digits_lc[] 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 * 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) ? \ #define ctype(c, t) tobool( ((t) == C_SUBOP2) ? \
(((c) == '#' || (c) == '%') ? 1 : 0) : \ (((c) == '#' || (c) == '%') ? 1 : 0) : \
(chtypes[(unsigned char)(c)] & (t)) ) (chtypes[(unsigned char)(c)] & (t)) )
#define ord(c) ((int)(unsigned char)(c))
#define ksh_isalphx(c) ctype((c), C_ALPHA) #define ksh_isalphx(c) ctype((c), C_ALPHA)
#define ksh_isalnux(c) ctype((c), C_ALPHA | C_DIGIT) #define ksh_isalnux(c) ctype((c), C_ALPHA | C_DIGIT)
#define ksh_isdigit(c) (((c) >= '0') && ((c) <= '9')) #define ksh_isdigit(c) (((c) >= '0') && ((c) <= '9'))
#define ksh_islower(c) (((c) >= 'a') && ((c) <= 'z')) #define ksh_islower(c) (((c) >= 'a') && ((c) <= 'z'))
#define ksh_isupper(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_tolower(c) (ksh_isupper(c) ? (c) - 'A' + 'a' : (c))
#define ksh_toupper(c) (((c) >= 'a') && ((c) <= 'z') ? (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_isdash(s) (((s)[0] == '-') && ((s)[1] == '\0'))
#define ksh_isspace(c) ((((c) >= 0x09) && ((c) <= 0x0D)) || ((c) == 0x20)) #define ksh_isspace(c) ((((c) >= 0x09) && ((c) <= 0x0D)) || ((c) == 0x20))
#define ksh_eq(c,u,l) (((c) | 0x20) == (l)) #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 "$*" */ EXTERN int ifs0 E_INIT(' '); /* for "$*" */

20
shf.c
View File

@ -25,7 +25,7 @@
#include "sh.h" #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() */ /* flags to shf_emptybuf() */
#define EB_READSW 0x01 /* about to switch to reading */ #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)) { if (ksh_isdigit(c)) {
bool overflowed = false; bool overflowed = false;
tmp = c - '0'; tmp = ksh_numdig(c);
while (c = *fmt++, ksh_isdigit(c)) { while (c = *fmt++, ksh_isdigit(c)) {
if (notok2mul(2147483647, tmp, 10)) if (notok2mul(2147483647, tmp, 10))
overflowed = true; overflowed = true;
tmp = tmp * 10 + c - '0'; tmp = tmp * 10 + ksh_numdig(c);
} }
--fmt; --fmt;
if (overflowed) if (overflowed)
@ -872,7 +872,7 @@ shf_vfprintf(struct shf *shf, const char *fmt, va_list args)
/* nasty format */ /* nasty format */
break; break;
if (c >= 'A' && c <= 'Z') { if (ksh_isupper(c)) {
flags |= FL_UPPER; flags |= FL_UPPER;
c = ksh_tolower(c); c = ksh_tolower(c);
} }
@ -917,7 +917,7 @@ shf_vfprintf(struct shf *shf, const char *fmt, va_list args)
/* FALLTHROUGH */ /* FALLTHROUGH */
case 'u': case 'u':
do { do {
*--cp = lnum % 10 + '0'; *--cp = digits_lc[lnum % 10];
lnum /= 10; lnum /= 10;
} while (lnum); } while (lnum);
@ -933,7 +933,7 @@ shf_vfprintf(struct shf *shf, const char *fmt, va_list args)
case 'o': case 'o':
do { do {
*--cp = (lnum & 0x7) + '0'; *--cp = digits_lc[lnum & 0x7];
lnum >>= 3; lnum >>= 3;
} while (lnum); } while (lnum);
@ -945,7 +945,7 @@ shf_vfprintf(struct shf *shf, const char *fmt, va_list args)
const char *digits = (flags & FL_UPPER) ? const char *digits = (flags & FL_UPPER) ?
digits_uc : digits_lc; digits_uc : digits_lc;
do { do {
*--cp = digits[lnum & 0xf]; *--cp = digits[lnum & 0xF];
lnum >>= 4; lnum >>= 4;
} while (lnum); } while (lnum);
@ -1013,7 +1013,7 @@ shf_vfprintf(struct shf *shf, const char *fmt, va_list args)
s++; s++;
nwritten++; nwritten++;
if (--precision > 0 && if (--precision > 0 &&
(*s | 0x20) == 'x') { ksh_eq(*s, 'X', 'x')) {
shf_putc(*s, shf); shf_putc(*s, shf);
s++; s++;
precision--; precision--;
@ -1025,8 +1025,10 @@ shf_vfprintf(struct shf *shf, const char *fmt, va_list args)
c = flags & FL_ZERO ? '0' : ' '; c = flags & FL_ZERO ? '0' : ' ';
if (field < 0) { if (field < 0) {
nwritten += -field; nwritten += -field;
for ( ; field < 0 ; field++) while (field < 0) {
shf_putc(c, shf); shf_putc(c, shf);
++field;
}
} }
} else } else
c = ' '; c = ' ';

11
syn.c
View File

@ -23,7 +23,7 @@
#include "sh.h" #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 { struct nesting_state {
int start_token; /* token than began nesting (eg, FOR) */ int start_token; /* token than began nesting (eg, FOR) */
@ -214,10 +214,10 @@ synio(int cf)
if (iop->unit > 9) { if (iop->unit > 9) {
*cp++ = CHAR; *cp++ = CHAR;
*cp++ = '0' + (iop->unit / 10); *cp++ = digits_lc[iop->unit / 10];
} }
*cp++ = CHAR; *cp++ = CHAR;
*cp++ = '0' + (iop->unit % 10); *cp++ = digits_lc[iop->unit % 10];
*cp = EOS; *cp = EOS;
iop->ioflag &= ~IOBASH; iop->ioflag &= ~IOBASH;
@ -1074,7 +1074,8 @@ parse_usec(const char *s, struct timeval *tv)
tv->tv_sec = 0; tv->tv_sec = 0;
/* parse integral part */ /* parse integral part */
while (ksh_isdigit(*s)) { 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) { if (tt.tv_sec / 10 != tv->tv_sec) {
errno = EOVERFLOW; errno = EOVERFLOW;
return (true); return (true);
@ -1095,7 +1096,7 @@ parse_usec(const char *s, struct timeval *tv)
/* parse decimal fraction */ /* parse decimal fraction */
i = 100000; i = 100000;
while (ksh_isdigit(*s)) { while (ksh_isdigit(*s)) {
tv->tv_usec += i * (*s++ - '0'); tv->tv_usec += i * ksh_numdig(*s++);
if (i == 1) if (i == 1)
break; break;
i /= 10; i /= 10;

8
var.c
View File

@ -28,7 +28,7 @@
#include <sys/sysctl.h> #include <sys/sysctl.h>
#endif #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 * Variables
@ -553,11 +553,11 @@ getint(struct tbl *vp, mksh_ari_u *nump, bool arith)
continue; continue;
} }
if (ksh_isdigit(c)) if (ksh_isdigit(c))
c -= '0'; c = ksh_numdig(c);
else if (ksh_isupper(c)) else if (ksh_isupper(c))
c -= 'A' - 10; c = ksh_numuc(c) + 10;
else if (ksh_islower(c)) else if (ksh_islower(c))
c -= 'a' - 10; c = ksh_numlc(c) + 10;
else else
return (-1); return (-1);
if (c >= base) if (c >= base)