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 -*-
#-
# 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),

16
edit.c
View File

@ -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;

View File

@ -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);

4
lex.c
View File

@ -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;
}

34
main.c
View File

@ -34,7 +34,7 @@
#include <locale.h>
#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 */

34
misc.c
View File

@ -30,7 +30,7 @@
#include <grp.h>
#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);

12
sh.h
View File

@ -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 "$*" */

20
shf.c
View File

@ -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 = ' ';

11
syn.c
View File

@ -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;

8
var.c
View File

@ -28,7 +28,7 @@
#include <sys/sysctl.h>
#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)