Hi,
this patch increases the number range on 32 bit architectures like
i386 to 64 bit. These are already supported on 64 bit architectures
due to using "long".
The rational behind this patch is to unify test/expr/ksh in allowing
64 bit integers, making variable handling more consistent in base
tools.
Also, keep in mind that 32 bit architectures also support large files,
so 64 bit file sizes in variables aren't totally out of the question.
When this is in, I want to merge the expr integer overflow checks
into ksh.
Verification of this patch is rather easy on amd64, because binary
does not change. I have extended regress tests to show that i386 can
handle 64 bit integers.
My i386 system is running with this patch and nothing broke so far.
Tobias
Index: bin/ksh/c_ksh.c
===================================================================
RCS file: /cvs/src/bin/ksh/c_ksh.c,v
retrieving revision 1.59
diff -u -p -u -p -r1.59 c_ksh.c
--- bin/ksh/c_ksh.c 15 Mar 2018 16:51:29 -0000 1.59
+++ bin/ksh/c_ksh.c 3 Apr 2018 18:00:31 -0000
@@ -1017,7 +1017,7 @@ int
c_let(char **wp)
{
int rv = 1;
- long val;
+ int64_t val;
if (wp[1] == NULL) /* at&t ksh does this */
bi_errorf("no arguments");
Index: bin/ksh/c_sh.c
===================================================================
RCS file: /cvs/src/bin/ksh/c_sh.c,v
retrieving revision 1.62
diff -u -p -u -p -r1.62 c_sh.c
--- bin/ksh/c_sh.c 27 Dec 2017 13:02:57 -0000 1.62
+++ bin/ksh/c_sh.c 3 Apr 2018 18:00:31 -0000
@@ -33,7 +33,7 @@ c_shift(char **wp)
{
struct block *l = genv->loc;
int n;
- long val;
+ int64_t val;
char *arg;
if (ksh_getopt(wp, &builtin_opt, null) == '?')
Index: bin/ksh/c_test.c
===================================================================
RCS file: /cvs/src/bin/ksh/c_test.c,v
retrieving revision 1.24
diff -u -p -u -p -r1.24 c_test.c
--- bin/ksh/c_test.c 26 Dec 2017 19:10:31 -0000 1.24
+++ bin/ksh/c_test.c 3 Apr 2018 18:00:31 -0000
@@ -308,7 +308,7 @@ test_eval(Test_env *te, Test_op op, cons
case TO_INTLE: /* -le */
case TO_INTLT: /* -lt */
{
- long v1, v2;
+ int64_t v1, v2;
if (!evaluate(opnd1, &v1, KSH_RETURN_ERROR, false) ||
!evaluate(opnd2, &v2, KSH_RETURN_ERROR, false)) {
Index: bin/ksh/c_ulimit.c
===================================================================
RCS file: /cvs/src/bin/ksh/c_ulimit.c,v
retrieving revision 1.27
diff -u -p -u -p -r1.27 c_ulimit.c
--- bin/ksh/c_ulimit.c 15 Mar 2018 16:51:29 -0000 1.27
+++ bin/ksh/c_ulimit.c 3 Apr 2018 18:00:31 -0000
@@ -22,6 +22,7 @@
#include <ctype.h>
#include <errno.h>
+#include <inttypes.h>
#include <string.h>
#include "sh.h"
@@ -139,7 +140,7 @@ set_ulimit(const struct limits *l, const
if (strcmp(v, "unlimited") == 0)
val = RLIM_INFINITY;
else {
- long rval;
+ int64_t rval;
if (!evaluate(v, &rval, KSH_RETURN_ERROR, false))
return 1;
@@ -187,6 +188,6 @@ print_ulimit(const struct limits *l, int
shprintf("unlimited\n");
else {
val /= l->factor;
- shprintf("%ld\n", (long) val);
+ shprintf("%" PRIi64 "\n", (int64_t) val);
}
}
Index: bin/ksh/edit.c
===================================================================
RCS file: /cvs/src/bin/ksh/edit.c,v
retrieving revision 1.64
diff -u -p -u -p -r1.64 edit.c
--- bin/ksh/edit.c 15 Mar 2018 16:51:29 -0000 1.64
+++ bin/ksh/edit.c 3 Apr 2018 18:00:31 -0000
@@ -80,10 +80,10 @@ check_sigwinch(void)
ws.ws_col;
if ((vp = typeset("COLUMNS", 0, 0, 0, 0)))
- setint(vp, (long) ws.ws_col);
+ setint(vp, (int64_t) ws.ws_col);
}
if (ws.ws_row && (vp = typeset("LINES", 0, 0, 0, 0)))
- setint(vp, (long) ws.ws_row);
+ setint(vp, (int64_t) ws.ws_row);
}
}
}
Index: bin/ksh/eval.c
===================================================================
RCS file: /cvs/src/bin/ksh/eval.c,v
retrieving revision 1.59
diff -u -p -u -p -r1.59 eval.c
--- bin/ksh/eval.c 16 Jan 2018 22:52:32 -0000 1.59
+++ bin/ksh/eval.c 3 Apr 2018 18:00:31 -0000
@@ -732,7 +732,7 @@ varsub(Expand *xp, char *sp, char *word,
if (Flag(FNOUNSET) && c == 0 && !zero_ok)
errorf("%s: parameter not set", sp);
*stypep = 0; /* unqualified variable/string substitution */
- xp->str = str_save(ulton((unsigned long)c, 10), ATEMP);
+ xp->str = str_save(u64ton((uint64_t)c, 10), ATEMP);
return XSUB;
}
Index: bin/ksh/expr.c
===================================================================
RCS file: /cvs/src/bin/ksh/expr.c,v
retrieving revision 1.32
diff -u -p -u -p -r1.32 expr.c
--- bin/ksh/expr.c 30 Dec 2015 09:07:00 -0000 1.32
+++ bin/ksh/expr.c 3 Apr 2018 18:00:31 -0000
@@ -148,7 +148,7 @@ static struct tbl *intvar(Expr_state *,
* parse and evaluate expression
*/
int
-evaluate(const char *expr, long int *rval, int error_ok, bool arith)
+evaluate(const char *expr, int64_t *rval, int error_ok, bool arith)
{
struct tbl v;
int ret;
@@ -280,7 +280,7 @@ evalexpr(Expr_state *es, enum prec prec)
{
struct tbl *vl, *vr = NULL, *vasn;
enum token op;
- long res = 0;
+ int64_t res = 0;
if (prec == P_PRIMARY) {
op = es->tok;
Index: bin/ksh/mail.c
===================================================================
RCS file: /cvs/src/bin/ksh/mail.c,v
retrieving revision 1.22
diff -u -p -u -p -r1.22 mail.c
--- bin/ksh/mail.c 19 Oct 2015 14:42:16 -0000 1.22
+++ bin/ksh/mail.c 3 Apr 2018 18:00:31 -0000
@@ -81,7 +81,7 @@ mcheck(void)
}
void
-mcset(long int interval)
+mcset(int64_t interval)
{
mailcheck_interval = interval;
}
Index: bin/ksh/main.c
===================================================================
RCS file: /cvs/src/bin/ksh/main.c,v
retrieving revision 1.90
diff -u -p -u -p -r1.90 main.c
--- bin/ksh/main.c 15 Mar 2018 16:51:29 -0000 1.90
+++ bin/ksh/main.c 3 Apr 2018 18:00:31 -0000
@@ -287,7 +287,7 @@ main(int argc, char *argv[])
setstr(pwd_v, current_wd, KSH_RETURN_ERROR);
}
ppid = getppid();
- setint(global("PPID"), (long) ppid);
+ setint(global("PPID"), (int64_t) ppid);
/* setstr can't fail here */
setstr(global(version_param), ksh_version, KSH_RETURN_ERROR);
Index: bin/ksh/misc.c
===================================================================
RCS file: /cvs/src/bin/ksh/misc.c,v
retrieving revision 1.69
diff -u -p -u -p -r1.69 misc.c
--- bin/ksh/misc.c 15 Mar 2018 16:51:29 -0000 1.69
+++ bin/ksh/misc.c 3 Apr 2018 18:00:32 -0000
@@ -56,10 +56,10 @@ initctypes(void)
setctypes(" \n\t\"#$&'()*;<>?[\\`|", C_QUOTE);
}
-/* convert unsigned long to base N string */
+/* convert uint64_t to base N string */
char *
-ulton(long unsigned int n, int base)
+u64ton(uint64_t n, int base)
{
char *p;
static char buf [20];
Index: bin/ksh/sh.h
===================================================================
RCS file: /cvs/src/bin/ksh/sh.h,v
retrieving revision 1.71
diff -u -p -u -p -r1.71 sh.h
--- bin/ksh/sh.h 16 Jan 2018 22:52:32 -0000 1.71
+++ bin/ksh/sh.h 3 Apr 2018 18:00:32 -0000
@@ -440,7 +440,7 @@ int search_access(const char *, int, int
int pr_menu(char *const *);
int pr_list(char *const *);
/* expr.c */
-int evaluate(const char *, long *, int, bool);
+int evaluate(const char *, int64_t *, int, bool);
int v_evaluate(struct tbl *, const char *, volatile int, bool);
/* history.c */
void init_histvec(void);
@@ -512,7 +512,7 @@ pid_t j_async(void);
int j_stopped_running(void);
/* mail.c */
void mcheck(void);
-void mcset(long);
+void mcset(int64_t);
void mbset(char *);
void mpset(char *);
/* main.c */
@@ -527,7 +527,7 @@ void cleanup_proc_env(void);
/* misc.c */
void setctypes(const char *, int);
void initctypes(void);
-char * ulton(unsigned long, int);
+char * u64ton(uint64_t, int);
char * str_save(const char *, Area *);
char * str_nsave(const char *, int, Area *);
int option(const char *);
@@ -583,11 +583,11 @@ void initvar(void);
struct tbl * global(const char *);
struct tbl * local(const char *, bool);
char * str_val(struct tbl *);
-long intval(struct tbl *);
+int64_t intval(struct tbl *);
int setstr(struct tbl *, const char *, int);
struct tbl *setint_v(struct tbl *, struct tbl *, bool);
-void setint(struct tbl *, long);
-int getint(struct tbl *, long *, bool);
+void setint(struct tbl *, int64_t);
+int getint(struct tbl *, int64_t *, bool);
struct tbl *typeset(const char *, int, int, int, int);
void unset(struct tbl *, int);
char * skip_varname(const char *, int);
Index: bin/ksh/table.h
===================================================================
RCS file: /cvs/src/bin/ksh/table.h,v
retrieving revision 1.13
diff -u -p -u -p -r1.13 table.h
--- bin/ksh/table.h 27 Dec 2017 13:02:57 -0000 1.13
+++ bin/ksh/table.h 3 Apr 2018 18:00:32 -0000
@@ -19,7 +19,7 @@ struct tbl { /* table item */
Area *areap; /* area to allocate from */
union {
char *s; /* string */
- long i; /* integer */
+ int64_t i; /* integer */
int (*f)(char **); /* int function */
struct op *t; /* "function" tree */
} val; /* value */
Index: bin/ksh/tree.c
===================================================================
RCS file: /cvs/src/bin/ksh/tree.c,v
retrieving revision 1.33
diff -u -p -u -p -r1.33 tree.c
--- bin/ksh/tree.c 15 Mar 2018 16:51:29 -0000 1.33
+++ bin/ksh/tree.c 3 Apr 2018 18:00:32 -0000
@@ -365,7 +365,7 @@ vfptreef(struct shf *shf, int indent, co
while ((c = *fmt++)) {
if (c == '%') {
- long n;
+ int64_t n;
char *p;
int neg;
@@ -376,7 +376,7 @@ vfptreef(struct shf *shf, int indent, co
case 'd': /* decimal */
n = va_arg(va, int);
neg = n < 0;
- p = ulton(neg ? -n : n, 10);
+ p = u64ton(neg ? -n : n, 10);
if (neg)
*--p = '-';
while (*p)
@@ -392,7 +392,7 @@ vfptreef(struct shf *shf, int indent, co
tputS(p, shf);
break;
case 'u': /* unsigned decimal */
- p = ulton(va_arg(va, unsigned int), 10);
+ p = u64ton(va_arg(va, unsigned int), 10);
while (*p)
tputc(*p++, shf);
break;
Index: bin/ksh/var.c
===================================================================
RCS file: /cvs/src/bin/ksh/var.c,v
retrieving revision 1.66
diff -u -p -u -p -r1.66 var.c
--- bin/ksh/var.c 15 Mar 2018 16:51:29 -0000 1.66
+++ bin/ksh/var.c 3 Apr 2018 18:00:32 -0000
@@ -4,6 +4,7 @@
#include <ctype.h>
#include <errno.h>
+#include <inttypes.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
@@ -136,7 +137,7 @@ array_index_calc(const char *n, bool *ar
p = skip_varname(n, false);
if (p != n && *p == '[' && (len = array_ref_len(p))) {
char *sub, *tmp;
- long rval;
+ int64_t rval;
/* Calculate the value of the subscript */
*arrayp = true;
@@ -146,7 +147,8 @@ array_index_calc(const char *n, bool *ar
n = str_nsave(n, p - n, ATEMP);
evaluate(sub, &rval, KSH_UNWIND_ERROR, true);
if (rval < 0 || rval > INT_MAX)
- errorf("%s: subscript %ld out of range", n, rval);
+ errorf("%s: subscript %" PRIi64 " out of range",
+ n, rval);
*valp = rval;
afree(sub, ATEMP);
}
@@ -295,18 +297,18 @@ str_val(struct tbl *vp)
else if (!(vp->flag&INTEGER)) /* string source */
s = vp->val.s + vp->type;
else { /* integer source */
- /* worst case number length is when base=2, so use BITS(long) */
- /* minus base # number null */
- char strbuf[1 + 2 + 1 + BITS(long) + 1];
+ /* worst case number length is when base=2, so use
+ * minus base # number BITS(int64_t) NUL */
+ char strbuf[1 + 2 + 1 + BITS(int64_t) + 1];
const char *digits = (vp->flag & UCASEV_AL) ?
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" :
"0123456789abcdefghijklmnopqrstuvwxyz";
- unsigned long n;
+ uint64_t n;
unsigned int base;
s = strbuf + sizeof(strbuf);
if (vp->flag & INT_U)
- n = (unsigned long) vp->val.i;
+ n = (uint64_t) vp->val.i;
else
n = (vp->val.i < 0) ? -vp->val.i : vp->val.i;
base = (vp->type == 0) ? 10 : vp->type;
@@ -335,10 +337,10 @@ str_val(struct tbl *vp)
}
/* get variable integer value, with error checking */
-long
+int64_t
intval(struct tbl *vp)
{
- long num;
+ int64_t num;
int base;
base = getint(vp, &num, false);
@@ -393,7 +395,7 @@ setstr(struct tbl *vq, const char *s, in
/* set variable to integer */
void
-setint(struct tbl *vq, long int n)
+setint(struct tbl *vq, int64_t n)
{
if (!(vq->flag&INTEGER)) {
struct tbl *vp = &vtemp;
@@ -411,13 +413,13 @@ setint(struct tbl *vq, long int n)
}
int
-getint(struct tbl *vp, long int *nump, bool arith)
+getint(struct tbl *vp, int64_t *nump, bool arith)
{
char *s;
int c;
int base, neg;
int have_base = 0;
- long num;
+ int64_t num;
if (vp->flag&SPECIAL)
getspec(vp);
@@ -483,7 +485,7 @@ struct tbl *
setint_v(struct tbl *vq, struct tbl *vp, bool arith)
{
int base;
- long num;
+ int64_t num;
if ((base = getint(vp, &num, arith)) == -1)
return NULL;
@@ -920,27 +922,27 @@ getspec(struct tbl *vp)
* (see initcoms[] in main.c).
*/
if (vp->flag & ISSET)
- setint(vp, (long)(time(NULL) - seconds)); /* XXX 2038 */
+ setint(vp, (int64_t)(time(NULL) - seconds));
vp->flag |= SPECIAL;
break;
case V_RANDOM:
vp->flag &= ~SPECIAL;
- setint(vp, (long) (rand() & 0x7fff));
+ setint(vp, (int64_t) (rand() & 0x7fff));
vp->flag |= SPECIAL;
break;
case V_HISTSIZE:
vp->flag &= ~SPECIAL;
- setint(vp, (long) histsize);
+ setint(vp, (int64_t) histsize);
vp->flag |= SPECIAL;
break;
case V_OPTIND:
vp->flag &= ~SPECIAL;
- setint(vp, (long) user_opt.uoptind);
+ setint(vp, (int64_t) user_opt.uoptind);
vp->flag |= SPECIAL;
break;
case V_LINENO:
vp->flag &= ~SPECIAL;
- setint(vp, (long) current_lineno + user_lineno);
+ setint(vp, (int64_t) current_lineno + user_lineno);
vp->flag |= SPECIAL;
break;
}
@@ -1004,7 +1006,7 @@ setspec(struct tbl *vp)
break;
case V_COLUMNS:
{
- long l;
+ int64_t l;
if (getint(vp, &l, false) == -1) {
x_cols = MIN_COLS;
@@ -1034,7 +1036,7 @@ setspec(struct tbl *vp)
break;
case V_SECONDS:
vp->flag &= ~SPECIAL;
- seconds = time(NULL) - intval(vp); /* XXX 2038 */
+ seconds = time(NULL) - intval(vp);
vp->flag |= SPECIAL;
break;
case V_TMOUT:
Index: regress/bin/ksh/integer.t
===================================================================
RCS file: /cvs/src/regress/bin/ksh/integer.t,v
retrieving revision 1.2
diff -u -p -u -p -r1.2 integer.t
--- regress/bin/ksh/integer.t 27 Sep 2016 15:35:34 -0000 1.2
+++ regress/bin/ksh/integer.t 3 Apr 2018 18:00:32 -0000
@@ -216,3 +216,14 @@ expected-stdout:
64
---
+name: integer-1
+description:
+ Check that 64 bit integers get assigned
+stdin:
+ echo $(( zz = 0x7fffffffffffffff))
+ echo $zz
+expected-stdout:
+ 9223372036854775807
+ 9223372036854775807
+---
+