On 2018/04/03 20:08, Tobias Stoeckmann wrote: > 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.
I don't know if there might be any hidden gotchas, but I have bumped into this limitation a few times and very much support moving to a 64-bit type. It is definitely needed before 2038 for timestamp calculations in shell scripts. > > 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 > +--- > + >