From 4cf3ef90330cf19acf70bb4dc2791f200848d39a Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Fri, 4 Aug 2006 09:22:13 +0000 Subject: 22583: erand48() needs initialisation on Cygwin. --- ChangeLog | 5 ++ Src/Modules/mathfunc.c | 123 ++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 126 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index c3447196c..01e8b8745 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2006-08-04 Peter Stephenson + + * 22583: Peter A. Castro: Src/Modules/mathfunc.c: Cygwin erand48() + apparently needs initialisation. + 2006-08-02 Peter Stephenson * unposted: Completion/Unix/Command/_subversion: update from diff --git a/Src/Modules/mathfunc.c b/Src/Modules/mathfunc.c index 5fef695ea..280fe343a 100644 --- a/Src/Modules/mathfunc.c +++ b/Src/Modules/mathfunc.c @@ -69,7 +69,9 @@ MF_LOGB, MF_NEXTAFTER, MF_RINT, MF_SCALB, +#ifdef HAVE_SIGNGAM MF_SIGNGAM, +#endif MF_SIN, MF_SINH, MF_SQRT, @@ -80,6 +82,12 @@ MF_Y1, MF_YN }; +/* also functions taking a string argument */ + +enum { +MS_RAND48 +}; + /* * also to do, but differently argument or returned: abs (no type * conversion), atan2. @@ -117,6 +125,12 @@ enum { static struct mathfunc mftab[] = { + /* Functions taking string arguments */ +#ifdef HAVE_ERAND48 + /* here to avoid comma hassle */ + STRMATHFUNC("rand48", math_string, MS_RAND48), +#endif + NUMMATHFUNC("abs", math_func, 1, 1, MF_ABS | BFLAG(BF_FRAC) | TFLAG(TF_NOCONV|TF_NOASS)), NUMMATHFUNC("acos", math_func, 1, 1, MF_ACOS | BFLAG(BF_FRAC)), @@ -155,7 +169,9 @@ static struct mathfunc mftab[] = { NUMMATHFUNC("nextafter", math_func, 2, 2, MF_NEXTAFTER), NUMMATHFUNC("rint", math_func, 1, 1, MF_RINT), NUMMATHFUNC("scalb", math_func, 2, 2, MF_SCALB | TFLAG(TF_INT2)), +#ifdef HAVE_SIGNGAM NUMMATHFUNC("signgam", math_func, 0, 0, MF_SIGNGAM | TFLAG(TF_NOASS)), +#endif NUMMATHFUNC("sin", math_func, 1, 1, MF_SIN), NUMMATHFUNC("sinh", math_func, 1, 1, MF_SINH), NUMMATHFUNC("sqrt", math_func, 1, 1, MF_SQRT | BFLAG(BF_NONNEG)), @@ -392,10 +408,12 @@ math_func(char *name, int argc, mnumber *argv, int id) retd = scalb(argd, argi); break; +#ifdef HAVE_SIGNGAM case MF_SIGNGAM: ret.type = MN_INTEGER; ret.u.l = signgam; break; +#endif case MF_SIN: retd = sin(argd); @@ -442,9 +460,110 @@ math_func(char *name, int argc, mnumber *argv, int id) return ret; } +/**/ +static mnumber +math_string(UNUSED(char *name), char *arg, int id) +{ + mnumber ret = zero_mnumber; + char *send; + /* + * Post-process the string argument, which is just passed verbatim. + * Not clear if any other functions that use math_string() will + * want this, but assume so for now. + */ + while (iblank(*arg)) + arg++; + send = arg + strlen(arg); + while (send > arg && iblank(send[-1])) + send--; + *send = '\0'; + + switch (id) + { +#ifdef HAVE_ERAND48 + case MS_RAND48: + { + static unsigned short seedbuf[3]; + static int seedbuf_init; + unsigned short tmp_seedbuf[3], *seedbufptr; + int do_init = 1; + + if (*arg) { + /* Seed is contained in parameter named by arg */ + char *seedstr; + seedbufptr = tmp_seedbuf; + if ((seedstr = getsparam(arg)) && strlen(seedstr) >= 12) { + int i, j; + do_init = 0; + /* + * Decode three sets of four hex digits corresponding + * to each unsigned short. + */ + for (i = 0; i < 3 && !do_init; i++) { + unsigned short *seedptr = seedbufptr + i; + *seedptr = 0; + for (j = 0; j < 4; j++) { + if (*seedstr >= '0' && *seedstr <= '9') + *seedptr += *seedstr - '0'; + else if (tolower(*seedstr) >= 'a' && + tolower(*seedstr) <= 'f') + *seedptr += tolower(*seedstr) - 'a' + 10; + else { + do_init = 1; + break; + } + seedstr++; + if (j < 3) + *seedptr *= 16; + } + } + } + else if (errflag) + break; + } + else + { + /* Use default seed: must be initialised. */ + seedbufptr = seedbuf; + if (!seedbuf_init) + seedbuf_init = 1; + else + do_init = 1; + } + if (do_init) { + seedbufptr[0] = (unsigned short)rand(); + seedbufptr[1] = (unsigned short)rand(); + seedbufptr[2] = (unsigned short)rand(); + /* + * Some implementations of rand48() need initialization. + * This is likely to be harmless elsewhere, since + * according to the documentation erand48() normally + * doesn't look at the seed set in this way. + */ + (void)seed48(seedbufptr); + } + ret.type = MN_FLOAT; + ret.u.d = erand48(seedbufptr); + + if (*arg) + { + char outbuf[13]; + sprintf(outbuf, "%04x%04x%04x", (int)seedbufptr[0], + (int)seedbufptr[1], (int)seedbufptr[2]); + setsparam(arg, ztrdup(outbuf)); + } + } + break; +#endif + } + + return ret; +} + + /**/ int -setup_(Module m) +setup_(UNUSED(Module m)) { return 0; } @@ -466,7 +585,7 @@ cleanup_(Module m) /**/ int -finish_(Module m) +finish_(UNUSED(Module m)) { return 0; } -- cgit 1.4.1