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
> +---
> +
>