diff --git a/BUGS b/BUGS index 7d02834..18b5be4 100644 --- a/BUGS +++ b/BUGS @@ -78,6 +78,42 @@ Known problems or mis-features: and not much in the way of comments. We need some major cleanup and documentation. + * On Solaris cc when compile with -Xc (which results in BASEB=16 + because it eliminates the long long type), some of the hash + functions fail. + + NOTE: As a work-a-round, Solaris cc users should compile + with -DFORCE_STDC and without -Xc. + + From: "Dr.D.J.Picton" + Subject: Re: calc version 2.11.0t4 + Date: Fri, 1 Oct 1999 16:12:30 +0100 (BST) + + **** Non-true result (0): 7120: sha(sha(isqrt(2e1000)==0x6db8d9cf0b018b8f9cbbf5aa1edb8066d19e1bb0 + 7120 result came out as 0x2f19f0baa7824cb8da5e9908044a3f648e992 + **** Non-true result (0): 7122: sha(sha("this is", 7^19-8, ..., "hash")) == 0x21e4... + 7122 result came out as 0xa050ece371eda88a461afcb807091f7613aa4488 + 7123: z = sha(list(1,2,3), "curds and whey", 2^21701-1, pi()); + **** Non-true result (0): 7124: sha(z) == 0x36dcca3e51865c30a2cf738023cda446f1368340 + 7124 result came out as 0xccaff4f97187821018d983cc0ce51787fb96a73c + **** Non-true result (0): 7209: sha1(sha1("this is",7^19-8,"a composit",3i+4.5,"hash")) == ... + 7209 result came out as 0xb9631fea54a3e999521efa99745d2e2a5f65cd3b + 7210: z = sha1(list(1,2,3), "curds and whey", 2^21701-1, pi()); + **** Non-true result (0): 7211: sha1(z) == 0xc19e7317675dbf71e293b4c41e117169e9da5b6f + 7211result came out as 0xb8e5c8fdbbe4539cf601b0f6eb874f9662edb50c + **** Non-true result (0): 7227: sha1(sha1(isqrt(2e1000)))==0x6852a1365c51050c3d039e3c5d9cf29c12283ef4 + 7227 result came out as 0x91018a59d87c7d945451538412cadd56b7ec4681 + **** Non-true result (0): 7310: md5(md5("this is", 7^19-8, "a composit", 3i+4.5, "hash")) == ... + 7310 result came out as 0x65c29173098713fdec0f319551355243 + 7311: z = md5(list(1,2,3), "curds and whey", 2^21701-1, pi()); + **** Non-true result (0): 7312: md5(z) == 0x63d2b2fccae2de265227c30b05abb6b5 + 7311 result came out as 0x1ba0c3eb5ba11dfe11394c0837f52d85 + **** Non-true result (0): 7328: md5(md5(isqrt(2e1000))) == 0xe56ac4b8cad869e738a04fedc97058f3 + 7328 result came out as 0x5afae12a1db610da2846c35f2bf144b0 + + **** 9 error(s) found \/++\/ + 9999: Ending regression tests + * On a Dec Alpha, make check for version 2.11.0t1 core dumps: From vandermj@molbio.sbphrd.com Fri Sep 24 06:15:28 1999 diff --git a/CHANGES b/CHANGES index 6bb63e8..7fc27d2 100644 --- a/CHANGES +++ b/CHANGES @@ -23,16 +23,11 @@ Following is the change from calc version 2.11.0t1 to date: Made some of the source a little more ++ friendly. We are NOT porting calc to C++! We will NOT support C++ compilation of calc. - Calc will written ANSI C. We just compiled with a suggestion from - Love-Jensen, John to make calc's version + Calc will written ANSI C. We just compiled with a suggestion from + Love-Jensen, John to make calc's version of C a little more to C++ compilers. Avoiding symbols such as new or try for example. - Thanks to the efforts of Ernest Bowen and - Dr.D.J.Picton , a nasty endian-ness bug - in the sha and sha1 hash functions that showed up on machines such - as the Sparc was fixed. - Updated README.FIRST and BUGS to reflect new URLs and addresses. Added a HOWTO.INSTALL file. @@ -51,7 +46,7 @@ Following is the change from calc version 2.11.0t1 to date: Fixed some problems related to path processing while opening files. Under extreme cases, an excessively long filename or CALCPATH value could create problems. Placed guards in opensearchfile() function - in input.c to catch these cases. + in input.c to catch these cases. Fixed cases were malloc failures were silently ignored in input.c. @@ -67,9 +62,12 @@ Following is the change from calc version 2.11.0t1 to date: Added a 'Dec Alpha / Compaq Tru64 cc (non-gnu) compiler set' section to the main Makefile. - Fixed a string handling bug discovered by Dr.D.J.Picton + Fixed a string handling bug discovered by Dr.D.J.Picton in the custom demo code. + Fixed a bug in the hnrmod() builtin that was discovered by + Ernest Bowen . + Added FORCE_STDC symbol. When defined it will force __STDC__ like conditions. Thus for compilers with as the Solaris cc compiler that are ANSI-like but still define __STDC__ as 0, one can use @@ -80,6 +78,73 @@ Following is the change from calc version 2.11.0t1 to date: The custom.c file is now compiled with full ${CFLAGS}. + ### XXX - this change has been backed out: + # + # Thanks to the efforts of Ernest Bowen and + # Dr.D.J.Picton , a nasty endian-ness bug + # in the sha and sha1 hash functions that showed up on machines such + # as the Sparc was fixed. + # + ### + + Rewrote command line / argument processing code. Calc is now + using getopt(3) argument processing. + + Fixed a memory leak related to converting strings to numbers + in the str2q() function in qio.c. + + Fixed a problem with reading uninitialized memory in the + v_subtype of a VALUE in the copyvalue() function in value.c. + + Fixed problems in func.c where temporary VALUEs were not + having their v_type elements initialized. + + Fixed a memory leak in qpi() in qtrans.c. + + Fixed a memory leak in math_getdivertedio() in zio.c. + + Fixed a problem with points going beyond the end of allocated + memory in addstring() in string.c. + + Fixed a memory leak in zgcdrem(), f_putenv(), zlog() and + zlog10() in zfunc.c. + + Fixed a memory leak in zdiv() and zshift() in zmath.c. + + Fixed memory leaks in zsrand() in zrand.c. + + Fixed a memory leak in zsrandom1() in zrandom.c. + + Added seed() builtin to return a 64 bit seed for a + psuedo-random generator. + + Added functionality from Ernest Bowen + to give arguments as well as function names after definitions when + calc_debug >= 0. + + Added functionality from Ernest Bowen to + permit nested "= {...}" assignments for lists as well as matrices + and objects. Now one can have a list, matrix or object, some of + whose elements are lists, matrices or objects, to any depth of + recursion, and assign values to any number of particular elements + by an appropriate "initialization" expression. For example: + + A = mat[2] = {list(1,2), list(3,4,list(5,6))}; + + and then assign values to the 6 number elements by: + + A = {{7,8}, {9,10,{11,12}}}; + + Closed files that were previously left open from test4600.cal + as executed by regress.cal and from opening /dev/null by + regress.cal itself. + + Fixed memory leaks from f_strprintf() and f_putenv() in func.c. + + The regress.cal test suite calls freeredc(), freestatics() and + freeglobals() at the end of the test suite to free storage + consumed during the regression. + Fixed misc compile warnings and notices. diff --git a/HOWTO.INSTALL b/HOWTO.INSTALL index 7909e73..b9b6b41 100644 --- a/HOWTO.INSTALL +++ b/HOWTO.INSTALL @@ -4,13 +4,11 @@ Installing calc in 4 easy steps: Here are some Makefile hints: - Select a compiler set by commenting in the appropriate - set of cc options. As shipped the Makefile assumes - a gcc-like environment such as Linux. - - If a more appropriate cc set if found below, comment - out the Linux set and comment in that set or edit - the gcc set or the common cc set as needed. + Select a compiler set by commenting in the appropriate set + of cc options. As shipped the Makefile assumes a gcc-like + environment such as Linux. If a more appropriate cc set if + found below, comment out the Linux set and comment in that + set or edit the gcc set or the common cc set as needed. You may or may not need RANLIB when building libraries. As shipped the Makefile assumes RANLIB is needed. @@ -40,13 +38,14 @@ Installing calc in 4 easy steps: make all ==> We are interested in any compiler warnings (and errors) that - you may find. See the BUGS file if you find any. + you may find. See the BUGS file if you find any compiler + warning or errors. 3) test calc: make check - ==> If you run into problems, follow the instructions in the BUGS file + ==> If you run into problems, follow the BUGS file instructions. 4) install calc: diff --git a/Makefile b/Makefile index 05a923e..1a26548 100644 --- a/Makefile +++ b/Makefile @@ -775,7 +775,7 @@ LIBSRC= addop.c assocfunc.c blkcpy.c block.c byteswap.c \ file.c func.c hash.c help.c hist.c input.c jump.c label.c \ lib_calc.c lib_util.c listfunc.c matfunc.c math_error.c \ md5.c obj.c opcodes.c pix.c poly.c prime.c qfunc.c qio.c \ - qmath.c qmod.c qtrans.c quickhash.c shs.c shs1.c size.c \ + qmath.c qmod.c qtrans.c quickhash.c seed.c shs.c shs1.c size.c \ string.c symbol.c token.c value.c version.c zfunc.c zio.c \ zmath.c zmod.c zmul.c zprime.c zrand.c zrandom.c @@ -789,7 +789,7 @@ LIBOBJS= addop.o assocfunc.o blkcpy.o block.o byteswap.o calcerr.o \ file.o func.o hash.o help.o hist.o input.o jump.o label.o \ lib_calc.o lib_util.o listfunc.o matfunc.o math_error.o \ md5.o obj.o opcodes.o pix.o poly.o prime.o qfunc.o qio.o \ - qmath.o qmod.o qtrans.o quickhash.o shs.o shs1.o size.o \ + qmath.o qmod.o qtrans.o quickhash.o seed.o shs.o shs1.o size.o \ string.o symbol.o token.o value.o version.o zfunc.o zio.o \ zmath.o zmod.o zmul.o zprime.o zrand.o zrandom.o @@ -2749,6 +2749,7 @@ byteswap.o: longbits.h byteswap.o: qmath.h byteswap.o: zmath.h calc.o: alloc.h +calc.o: args.h calc.o: block.h calc.o: byteswap.h calc.o: calc.c @@ -2784,6 +2785,7 @@ calc.o: symbol.h calc.o: token.h calc.o: value.h calc.o: zmath.h +calc_errno.o: calc_errno.c calcerr.o: calcerr.c calcerr.o: calcerr.h calcerr.o: have_const.h @@ -2961,6 +2963,7 @@ func.o: alloc.h func.o: block.h func.o: byteswap.h func.o: calc.h +func.o: calc_errno.h func.o: calcerr.h func.o: cmath.h func.o: config.h @@ -3327,7 +3330,6 @@ obj.o: symbol.h obj.o: value.h obj.o: zmath.h opcodes.o: alloc.h -opcodes.o: args.h opcodes.o: block.h opcodes.o: byteswap.h opcodes.o: calc.h @@ -3512,6 +3514,18 @@ quickhash.o: value.h quickhash.o: zmath.h quickhash.o: zrand.h quickhash.o: zrandom.h +seed.o: alloc.h +seed.o: byteswap.h +seed.o: endian_calc.h +seed.o: have_malloc.h +seed.o: have_memmv.h +seed.o: have_newstr.h +seed.o: have_stdlib.h +seed.o: have_string.h +seed.o: longbits.h +seed.o: qmath.h +seed.o: seed.c +seed.o: zmath.h shs.o: align32.h shs.o: alloc.h shs.o: block.h diff --git a/addop.c b/addop.c index b82287f..19f0e0e 100644 --- a/addop.c +++ b/addop.c @@ -135,6 +135,7 @@ endfunc(void) { register FUNC *fp; /* function just finished */ unsigned long size; /* size of just created function */ + long index; if (oldop != OP_RETURN) { addop(OP_UNDEF); @@ -163,14 +164,22 @@ endfunc(void) size += dumpop(&fp->f_opcodes[size]); } } + if (inputisterminal() || conf->lib_debug >= 0) { + printf("%s(", fp->f_name); + for (index = 0; index < fp->f_paramcount; index++) { + if (index) + putchar(','); + printf("%s", paramname(index)); + } + printf(") "); + if (functions[newindex]) + printf("re"); + printf("defined\n"); + } if (functions[newindex]) { freenumbers(functions[newindex]); free(functions[newindex]); - if (inputisterminal() || conf->lib_debug >= 0) - printf("%s() redefined\n", fp->f_name); } - else if (inputisterminal() || conf->lib_debug >= 0) - printf("%s() defined\n", fp->f_name); functions[newindex] = fp; objuncache(); } diff --git a/calc.c b/calc.c index d43e03f..471fd7b 100644 --- a/calc.c +++ b/calc.c @@ -39,7 +39,7 @@ /* - * external and static definitions + * external definitions and functions */ extern int abortlevel; /* current level of aborts */ extern BOOL inputwait; /* TRUE if in a terminal input wait */ @@ -52,6 +52,7 @@ extern int u_flag; /* TRUE => unbuffer stdin and stdout */ extern char *pager; /* $PAGER or default */ extern int stdin_tty; /* TRUE if stdin is a tty */ +extern int interactive; /* TRUE if interactive session (no cmd args) */ extern char *program; /* our name */ extern char cmdbuf[]; /* command line expression */ @@ -59,8 +60,10 @@ extern char *version(void); /* return version string */ /* - * forward static functions + * static definitions and functions */ +static char *usage = "usage: %s [-C] [-e] [-h] [-i] [-m mode] [-n] [-p]\n" + "\t[-q] [-u] [[--] calc_cmd ...]\n"; static void intint(int arg); /* interrupt routine */ @@ -70,124 +73,121 @@ static void intint(int arg); /* interrupt routine */ int main(int argc, char **argv) { - static char *str; /* current option string or expression */ int want_defhelp = 0; /* 1=> we only want the default help */ + int cmdlen; /* length of the command string */ + extern char *optarg; /* option argument */ + extern int optind; /* option index */ + int c; /* option */ long i; - char *p; /* * parse args */ program = argv[0]; - argc--; - argv++; - while ((argc > 0) && (**argv == '-')) { - for (str = &argv[0][1]; *str; str++) switch (*str) { - case 'C': + while ((c = getopt(argc, argv, "Cehim:npquv")) != -1) { + switch (c) { + case 'C': #if defined(CUSTOM) - allow_custom = TRUE; - break; -#else - fprintf(stderr, - "Calc was built with custom functions " - "disabled, -C usage is disallowed\n"); - /* - * we are too early in processing to call - * libcalc_call_me_last() - nothing to cleanup - */ - exit(1); -#endif /* CUSTOM */ - case 'e': - no_env = TRUE; - break; - case 'h': - want_defhelp = 1; - break; - case 'i': - ign_errmax = TRUE; - break; - case 'm': - if (argv[0][2]) { - p = &argv[0][2]; - } else if (argc > 1) { - p = argv[1]; - argc--; - argv++; - } else { - fprintf(stderr, "-m requires an arg\n"); - /* - * we are too early in processing to - * call libcalc_call_me_last() - * nothing to cleanup - */ - exit(1); - } - if (p[1] != '\0' || *p < '0' || *p > '7') { - fprintf(stderr, "unknown -m arg\n"); - /* - * we are too early in processing to - * call libcalc_call_me_last() - * nothing to cleanup - */ - exit(1); - } - allow_read = (((*p-'0') & 04) > 0); - allow_write = (((*p-'0') & 02) > 0); - allow_exec = (((*p-'0') & 01) > 0); - break; - case 'n': - new_std = TRUE; - break; - case 'p': - p_flag = TRUE; - break; - case 'q': - q_flag = TRUE; - break; - case 'u': - u_flag = TRUE; - break; - case 'v': - printf("%s (version %s)\n", - CALC_TITLE, version()); - /* - * we are too early in processing to call - * libcalc_call_me_last() - nothing to cleanup - */ - exit(0); - default: - fprintf(stderr, - "usage: %s [-C] [-e] [-h] [-i] [-m mode] [-n] [-p]\n", - program); - fprintf(stderr, "\t[-q] [-u] [calc_cmd ...]\n"); - /* - * we are too early in processing to call - * libcalc_call_me_last() - nothing to cleanup - */ - exit(1); - } - argc--; - argv++; - } - cmdbuf[0] = '\0'; - str = cmdbuf; - while (--argc >= 0) { - i = (long)strlen(*argv); - if (i+3 >= MAXCMD) { - fprintf(stderr, "command in arg list too long\n"); + allow_custom = TRUE; + break; +#else /* CUSTOM */ /* * we are too early in processing to call * libcalc_call_me_last() - nothing to cleanup */ + fprintf(stderr, + "%s: calc was built with custom functions " + "disabled, -C usage is disallowed\n", program); + exit(1); +#endif /* CUSTOM */ + case 'e': + no_env = TRUE; + break; + case 'h': + want_defhelp = 1; + break; + case 'i': + ign_errmax = TRUE; + break; + case 'm': + if (optarg[1] == '\0' || *optarg<'0' || *optarg>'7') { + /* + * we are too early in processing to + * call libcalc_call_me_last() + * nothing to cleanup + */ + fprintf(stderr, + "%s: unknown -m arg\n", program); + exit(1); + } + allow_read = (((*optarg-'0') & 04) > 0); + allow_write = (((*optarg-'0') & 02) > 0); + allow_exec = (((*optarg-'0') & 01) > 0); + break; + case 'n': + new_std = TRUE; + break; + case 'p': + p_flag = TRUE; + break; + case 'q': + q_flag = TRUE; + break; + case 'u': + u_flag = TRUE; + break; + case 'v': + /* + * we are too early in processing to call + * libcalc_call_me_last() - nothing to cleanup + */ + printf("%s (version %s)\n", CALC_TITLE, version()); + exit(0); + default: + /* + * we are too early in processing to call + * libcalc_call_me_last() - nothing to cleanup + */ + fprintf(stderr, usage, program); exit(1); } - *str++ = ' '; - strcpy(str, *argv++); - str += i; - str[0] = '\n'; - str[1] = '\0'; } - str = cmdbuf; + interactive = (optind >= argc); + + /* + * look at the length of any trailing command args + * + * We make room for the trailing '\0\n' as well as an extra guard byte. + */ + for (cmdlen=0, i=optind; i < argc; ++i) { + /* argument + space separator */ + cmdlen += strlen(argv[i]) + 1; + } + if (i > MAXCMD) { + /* + * we are too early in processing to call + * libcalc_call_me_last() - nothing to cleanup + */ + fprintf(stderr, + "%s: command in arg list is too long\n", program); + exit(1); + } + + /* + * We will form a command the remaining args separated by spaces. + */ + cmdbuf[0] = '\0'; + if (optind < argc) { + strcpy(cmdbuf, argv[optind]); + cmdlen = strlen(argv[optind]); + for (i=optind+1; i < argc; ++i) { + cmdbuf[cmdlen++] = ' '; + strcpy(cmdbuf+cmdlen, argv[i]); + cmdlen += strlen(argv[i]); + } + cmdbuf[cmdlen++] = '\n'; + cmdbuf[cmdlen] = '\0'; + } /* * unbuffered mode @@ -212,7 +212,7 @@ main(int argc, char **argv) /* * if allowed or needed, print version and setup bindings */ - if (str >= cmdbuf+MAXCMD || *str == '\0') { + if (interactive) { /* * check for pipe mode and/or non-tty stdin */ @@ -220,11 +220,6 @@ main(int argc, char **argv) stdin_tty = isatty(0); /* assume stdin is on fd 0 */ } - /* - * empty string arg is no string - */ - str = NULL; - /* * if tty, setup bindings */ @@ -235,14 +230,15 @@ main(int argc, char **argv) switch (hist_init(calcbindings)) { case HIST_NOFILE: fprintf(stderr, - "Cannot open bindings file \"%s\", %s.\n", - calcbindings, "fancy editing disabled"); + "%s: Cannot open bindings file \"%s\", " + "fancy editing disabled.\n", + program, calcbindings); break; case HIST_NOTTY: fprintf(stderr, - "Cannot set terminal modes, %s.\n", - "fancy editing disabled"); + "%s: Cannot set terminal modes, " + "fancy editing disabled\n", program); break; } } @@ -260,21 +256,21 @@ main(int argc, char **argv) initialize(); } else { /* initialize already done, jmpbuf is ready */ - post_init = TRUE; + post_init = TRUE; } /* * if arg mode or non-tty mode, just do the work and be gone */ - if (str || !stdin_tty) { + if (!interactive || !stdin_tty) { if (q_flag == FALSE && allow_read) { runrcfiles(); q_flag = TRUE; } - if (str) - (void) openstring(str); - else + if (interactive) (void) openterminal(); + else + (void) openstring(cmdbuf); start_done = TRUE; getcommands(FALSE); libcalc_call_me_last(); @@ -282,7 +278,7 @@ main(int argc, char **argv) } } /* if in arg mode, we should not get here */ - if (str) { + if (!interactive) { libcalc_call_me_last(); exit(1); } @@ -339,7 +335,8 @@ math_error(char *fmt, ...) if (funcname && (*funcname != '*')) fprintf(stderr, "\"%s\": ", funcname); - if (funcline && ((funcname && (*funcname != '*')) || !inputisterminal())) + if (funcline && ((funcname && (*funcname != '*')) || + !inputisterminal())) fprintf(stderr, "line %ld: ", funcline); va_start(ap, fmt); vsprintf(buf, fmt, ap); diff --git a/config.c b/config.c index 28cdbe5..1388677 100644 --- a/config.c +++ b/config.c @@ -890,7 +890,7 @@ config_copy(CONFIG *src) /* * copy over the values */ - *dest = *src; + memcpy((void *)dest, (void *)src, sizeof(CONFIG)); /* * clone the pointer values diff --git a/custom/c_sysinfo.c b/custom/c_sysinfo.c index bf31bed..2f1d5a8 100644 --- a/custom/c_sysinfo.c +++ b/custom/c_sysinfo.c @@ -240,7 +240,7 @@ c_sysinfo(char *name, int count, VALUE **vals) buf = (char *)malloc(strlen((char *)vals[0]->v_str->s_str)+1); for (q = (char *)vals[0]->v_str->s_str, r = buf; *q; ++q, ++r) { - if (isascii(*q) && islower(*q)) { + if (isascii((int)*q) && islower((int)*q)) { *r = *q - 'a' + 'A'; } else { *r = *q; diff --git a/file.c b/file.c index f039a51..469e60f 100644 --- a/file.c +++ b/file.c @@ -2271,6 +2271,7 @@ freadnum(FILE *fp, VALUE *valptr) num = newnum; zden = newden; } + zfree(div); } q = qalloc(); q->num = num; diff --git a/func.c b/func.c index f074dd6..a7b8f5c 100644 --- a/func.c +++ b/func.c @@ -230,33 +230,34 @@ f_str(VALUE *vp) switch (vp->v_type) { case V_STR: result.v_str = stringcopy(vp->v_str); - return result; + break; case V_NULL: result.v_str = slink(&_nullstring_); - return result; + break; case V_OCTET: result.v_str = charstring(*vp->v_octet); - return result; + break; case V_NUM: math_divertio(); qprintnum(vp->v_num, MODE_DEFAULT); cp = math_getdivertedio(); + result.v_str = makestring(cp); break; case V_COM: math_divertio(); comprint(vp->v_com); cp = math_getdivertedio(); + result.v_str = makestring(cp); break; default: return error_value(E_STR); } - result.v_str = makestring(cp); return result; } static VALUE -f_name (VALUE *vp) +f_name(VALUE *vp) { VALUE result; char *cp; @@ -767,6 +768,13 @@ f_nextcand(int count, NUMBER **vals) } +static NUMBER * +f_seed(void) +{ + return pseudo_seed(); +} + + static NUMBER * f_rand(int count, NUMBER **vals) { @@ -1242,6 +1250,7 @@ minlistitems(LIST *lp) VALUE min; min.v_type = V_NULL; + term.v_type = V_NULL; for (ep = lp->l_first; ep; ep = ep->e_next) { vp = &ep->e_value; @@ -1291,6 +1300,7 @@ maxlistitems(LIST *lp) VALUE max; max.v_type = V_NULL; + term.v_type = V_NULL; for (ep = lp->l_first; ep; ep = ep->e_next) { vp = &ep->e_value; @@ -1339,6 +1349,8 @@ f_min(int count, VALUE **vals) VALUE rel; min.v_type = V_NULL; + term.v_type = V_NULL; + while (count-- > 0) { vp = *vals++; switch(vp->v_type) { @@ -1390,6 +1402,7 @@ f_max(int count, VALUE **vals) VALUE rel; max.v_type = V_NULL; + term.v_type = V_NULL; while (count-- > 0) { vp = *vals++; @@ -1494,6 +1507,7 @@ sumlistitems(LIST *lp) VALUE sum; sum.v_type = V_NULL; + term.v_type = V_NULL; for (ep = lp->l_first; ep; ep = ep->e_next) { vp = &ep->e_value; @@ -1534,6 +1548,8 @@ f_sum(int count, VALUE **vals) VALUE *vp; sum.v_type = V_NULL; + term.v_type = V_NULL; + while (count-- > 0) { vp = *vals++; switch(vp->v_type) { @@ -5169,11 +5185,14 @@ f_strprintf(int count, VALUE **vals) math_divertio(); i = idprintf(FILEID_STDOUT, vals[0]->v_str->s_str, count - 1, vals + 1); - if (i) + if (i) { + free(math_getdivertedio()); return error_value(E_STRPRINTF2); + } cp = math_getdivertedio(); result.v_type = V_STR; result.v_str = makenewstring(cp); + free(cp); return result; } @@ -5917,6 +5936,7 @@ f_putenv(int count, VALUE **vals) /* return putenv result */ result.v_type = V_NUM; result.v_num = itoq((long) putenv(putenv_str)); + free(putenv_str); return result; } @@ -7136,6 +7156,8 @@ static CONST struct builtin builtins[] = { "sec of a within accuracy b"}, {"sech", 1, 2, 0, OP_NOP, 0, f_sech, "hyperbolic secant of a within accuracy b"}, + {"seed", 0, 0, 0, OP_NOP, f_seed, 0, + "return a 64 bit seed for a psuedo-random generator"}, {"segment", 2, 3, 0, OP_NOP, 0, f_segment, "specified segment of specified list"}, {"select", 2, 2, 0, OP_NOP, 0, f_select, diff --git a/help/Makefile b/help/Makefile index 1285e91..b9617bc 100644 --- a/help/Makefile +++ b/help/Makefile @@ -124,7 +124,7 @@ DETAIL_HELP= abs access acos acosh acot acoth acsc acsch address agd append \ pmod polar poly pop popcnt power prevcand prevprime printf prompt \ protect ptest push putenv quo quomod rand randbit random randombit \ randperm rcin rcmul rcout rcpow rcsq re remove reverse rewind rm root \ - round rsearch runtime saveval scale scan scanf search sec sech \ + round rsearch runtime saveval scale scan scanf search sec sech seed \ segment select sgn sha sha1 sin sinh size sizeof sort sqrt srand \ srandom ssq str strcat strerror strlen strpos strprintf strscan \ strscanf substr sum swap system tail tan tanh test time trunc xor diff --git a/help/isrand b/help/isrand index 6cb03e1..9f798a1 100644 --- a/help/isrand +++ b/help/isrand @@ -25,7 +25,7 @@ LIBRARY none SEE ALSO - rand, srand, randbit, + seed, rand, srand, randbit, isassoc, isatty, isblk, isconfig, isdefined, iserror, iseven, isfile, ishash, isident, isint, islist, ismat, ismult, isnull, isnum, isobj, isobjtype, isodd, isprime, israndom, isreal, isrel, diff --git a/help/israndom b/help/israndom index 1b94523..f6da8d2 100644 --- a/help/israndom +++ b/help/israndom @@ -27,7 +27,7 @@ LIBRARY none SEE ALSO - random, srandom, randombit, + seed, random, srandom, randombit, isassoc, isatty, isblk, isconfig, isdefined, iserror, iseven, isfile, ishash, isident, isint, islist, ismat, ismult, isnull, isnum, isobj, isobjtype, isodd, isprime, isrand, isreal, isrel, diff --git a/help/rand b/help/rand index 3269a6d..98a8ba3 100644 --- a/help/rand +++ b/help/rand @@ -230,4 +230,4 @@ LIBRARY long irand(long max) SEE ALSO - srand, randbit, isrand, random, srandom, israndom + seed, srand, randbit, isrand, random, srandom, israndom diff --git a/help/randbit b/help/randbit index e7b8e53..de87f92 100644 --- a/help/randbit +++ b/help/randbit @@ -40,4 +40,4 @@ LIBRARY void zrand(long cnt, ZVALUE *res) SEE ALSO - srand, randbit, isrand, random, srandom, israndom + seed, srand, randbit, isrand, random, srandom, israndom diff --git a/help/random b/help/random index 004624a..6c97f2f 100644 --- a/help/random +++ b/help/random @@ -154,4 +154,4 @@ LIBRARY long irandom(long max) SEE ALSO - srand, randbit, isrand, rand, srandom, israndom + seed, srand, randbit, isrand, rand, srandom, israndom diff --git a/help/randombit b/help/randombit index 5327f78..9edf994 100644 --- a/help/randombit +++ b/help/randombit @@ -39,4 +39,4 @@ LIBRARY void zrandom(long cnt, ZVALUE *res) SEE ALSO - srand, randbit, isrand, rand, srandom, israndom + seed, srand, randbit, isrand, rand, srandom, israndom diff --git a/help/seed b/help/seed new file mode 100644 index 0000000..c845c46 --- /dev/null +++ b/help/seed @@ -0,0 +1,52 @@ +NAME + seed - return a value that may be used to seed a pseudo-random generator + +SYNOPSIS + seed() + +TYPES + return integer + +DESCRIPTION + Generate a pseudo-random seed based on a collection of system and process + information. The seed() builtin function returns a value: + + 0 <= seed < 2^64 + + IMPORTANT WARNING: + + It should be pointed out that the information collected by seed + is almost certainly non-chaotic. This function is likely not + suitable for applications (such as cryptographic applications) + where the unpredictability of seeds is critical. For such critical + applications, lavarand should be used. Seed: + + http://lavarand.sgi.com + + for information about seeding a pseudo-random number generator + (such as rand() or random()) with the cryptographic hash of the + digitization of chaotic system. + + Given the above warning, this builtin function produces a seed that is + suitable for most applications that desire a different pseudo-random + sequence each time they are run. + + The return value of this builtin function should NOT be considered + a random or pseudo-random value. The return value should be used + as an argument to a seed function such as srand() or srandom(). + +EXAMPLE + > print srand(seed()) + RAND state + + > print srandom(seed()) + RAND state + +LIMITS + none + +LIBRARY + NUMBER *pseudo_seed(void) + +SEE ALSO + seed, srand, randbit, isrand, rand, random, srandom, israndom diff --git a/help/srand b/help/srand index c858d0e..751ad8e 100644 --- a/help/srand +++ b/help/srand @@ -148,4 +148,4 @@ LIBRARY RAND *zsetrand(RAND *state) SEE ALSO - srandom, randbit, isrand, random, srandom, israndom + seed, srandom, randbit, isrand, random, srandom, israndom diff --git a/help/srandom b/help/srandom index df2c0d5..0ac3a16 100644 --- a/help/srandom +++ b/help/srandom @@ -337,4 +337,4 @@ LIBRARY RAND *zsetrandom(RAND *state) SEE ALSO - srand, randbit, isrand, random, srandom, israndom + seed, srand, randbit, isrand, random, srandom, israndom diff --git a/lib/regress.cal b/lib/regress.cal index c15503d..b8ff3a1 100644 --- a/lib/regress.cal +++ b/lib/regress.cal @@ -1555,7 +1555,12 @@ define test_rand() vrfy(randbit() == 1, '1567: randbit() == 1'); vrfy(randbit() == 0, '1568: randbit() == 0'); - print '1569: Ending rand test'; + /* test seed() as best as we can */ + vrfy(seed() >= 0, '1569: seed() >= 0'); + vrfy(seed() < 2^64, '1570: seed() < 2^64'); + vrfy(isrand(srand(seed())), '1571: isrand(srand(seed()))'); + + print '1572: Ending rand test'; } print '025: parsed test_rand()'; @@ -4410,7 +4415,12 @@ define test_random() vrfy(randombit(123) == 0x2058f802dd42b3aee4e734eacc13057, \ '5463: randombit(123) == 0x2058f802dd42b3aee4e734eacc13057'); - print '5464: Ending test_random'; + /* test seed() as best as we can */ + vrfy(seed() >= 0, '5464: seed() >= 0'); + vrfy(seed() < 2^64, '5465: seed() < 2^64'); + vrfy(israndom(srandom(seed())), '5466: israndom(srandom(seed()))'); + + print '5467: Ending test_random'; } print '137: parsed test_random()'; @@ -5907,8 +5917,10 @@ define test_is() */ blkfree("blk5900"); print '6663: blkfree("blk5900")'; + fclose(ofd); + print '6664: fclose(ofd)'; - print '6664: Ending test_is'; + print '6665: Ending test_is'; } print '168: test_is()'; @@ -7144,7 +7156,7 @@ print '200: Reserved for top level test use'; define count_errors() { if (prob == 0) { - print "9998: passed all tests /\\../\\"; + print "9997: passed all tests /\\../\\"; } else { print "****", prob, "error(s) found \\/++\\/"; } @@ -7380,6 +7392,15 @@ return test_natnumset(); print; return test_somenew(); +/* + * cleanup and report the results + */ print; +freeredc(); +print '9995: freeredc()'; +freestatics(); +print '9996: freestatics()'; return count_errors(); +freeglobals(); +print '9998: freeglobals()'; print '9999: Ending regression tests'; diff --git a/lib/test4600.cal b/lib/test4600.cal index 40b8af8..98892d3 100644 --- a/lib/test4600.cal +++ b/lib/test4600.cal @@ -223,6 +223,11 @@ define ttest(str, m, n, verbose) return 1; } } + if (iserror(fclose(f))) { + print 'failed'; + printf("**** Failure 6 for i = %d\n", i); + return 1; + } i = rm("junk4600"); if (verbose > 0) { printf("passed\n"); diff --git a/lib_calc.c b/lib_calc.c index 3386a50..fe95d1a 100644 --- a/lib_calc.c +++ b/lib_calc.c @@ -65,7 +65,7 @@ BOOL inputwait; /* TRUE if in a terminal input wait */ jmp_buf jmpbuf; /* for errors */ int start_done = FALSE; /* TRUE => start up processing finished */ char *program = "calc"; /* our name */ -char cmdbuf[MAXCMD+1+1]; /* command line expression */ +char cmdbuf[MAXCMD+1+1+1]; /* command line expression + "\n\0" + guard */ /* @@ -94,6 +94,7 @@ char *home; /* $HOME or default */ char *pager; /* $PAGER or default */ char *shell; /* $SHELL or default */ int stdin_tty = FALSE; /* TRUE if stdin is a tty */ +int interactive = FALSE; /* TRUE if interactive session (no cmd args) */ int post_init = FALSE; /* TRUE setjmp for math_error is readready */ int no_env = FALSE; /* TRUE (-e) => ignore env vars on startup */ diff --git a/opcodes.c b/opcodes.c index d0a8251..bb79252 100644 --- a/opcodes.c +++ b/opcodes.c @@ -640,9 +640,8 @@ o_elemaddr(FUNC *fp, long index) math_error("Non-existent element for matrix"); /*NOTREACHED*/ } - stack->v_type = V_ADDR; - stack->v_addr = &mp->m_table[index]; - return; + vp = &mp->m_table[index]; + break; case V_OBJ: op = vp->v_obj; offset = objoffset(op, index); @@ -650,13 +649,21 @@ o_elemaddr(FUNC *fp, long index) math_error("Non-existent element for object"); /*NOTREACHED*/ } - stack->v_type = V_ADDR; - stack->v_addr = &op->o_table[offset]; - return; + vp = &op->o_table[offset]; + break; + case V_LIST: + vp = listfindex(vp->v_list, index); + if (vp == NULL) { + math_error("Index out of bounds for list"); + /*NOTREACHED*/ + } + break; default: - math_error("Not indexing matrix or object"); + math_error("Not initializing matrix, object or list"); /*NOTREACHED*/ } + stack->v_type = V_ADDR; + stack->v_addr = vp; } @@ -746,8 +753,10 @@ o_assign(void) math_error("No-assign-from source for assign"); /*NOTREACHED*/ } + tmp.v_subtype = V_NOSUBTYPE; copyvalue(vp, &tmp); } else if (vp->v_type == V_OCTET) { + tmp.v_subtype = V_NOSUBTYPE; copyvalue(vp, &tmp); } else { tmp = *vp; diff --git a/qfunc.c b/qfunc.c index e9d8f30..00a11da 100644 --- a/qfunc.c +++ b/qfunc.c @@ -521,12 +521,12 @@ qilog2(NUMBER *q) else if (n > 0) { zshift(q->den, n, &tmp2); c = zrel(tmp1, tmp2); + zfree(tmp2); } else { zshift(tmp1, -n, &tmp2); c = zrel(tmp2, q->den); - } - if (n) zfree(tmp2); + } if (c < 0) n--; return n; diff --git a/qio.c b/qio.c index 81970f3..82793e2 100644 --- a/qio.c +++ b/qio.c @@ -558,6 +558,7 @@ str2q(char *s) q->num = newnum; q->den = newden; } + zfree(div); } return q; } diff --git a/qmath.h b/qmath.h index 397272a..d8bae6a 100644 --- a/qmath.h +++ b/qmath.h @@ -200,6 +200,12 @@ extern NUMBER *qlegtoleg(NUMBER *q, NUMBER *epsilon, BOOL wantneg); extern NUMBER *qpi(NUMBER *epsilon); +/* + * pseudo-seed generator + */ +extern NUMBER *pseudo_seed(void); + + /* * external swap functions */ diff --git a/qtrans.c b/qtrans.c index accdeb1..292b8c6 100644 --- a/qtrans.c +++ b/qtrans.c @@ -480,6 +480,7 @@ qatan(NUMBER *q, NUMBER *epsilon) zsqrt(ztmp2, &ztmp1, 24L); zfree(ztmp2); zadd(ztmp1, D, &ztmp2); + zfree(ztmp1); zshift(X, m, &ztmp1); zfree(X); zquo(ztmp1, ztmp2, &X, 24L); @@ -726,6 +727,7 @@ qpi(NUMBER *epsilon) zfree(tmp2); shift += 12; } while ((shift - t) < bits); + zfree(comb); qtmp.num = _one_; qtmp.den = sum; t1 = qscale(&qtmp, shift); diff --git a/quickhash.c b/quickhash.c index 6312a65..c7d5083 100644 --- a/quickhash.c +++ b/quickhash.c @@ -23,7 +23,7 @@ */ /* - * quickhash - qickly hash a calc value using a partial Fowler/Noll/Vo hash + * quickhash - quickly hash a calc value using a partial Fowler/Noll/Vo hash * * NOTE: This file does not contain a hash interface. It is used by * associative arrays and other internal processes. @@ -40,6 +40,13 @@ * quick and dirty job of hashing on a part of a calc value, * combined with using a reasonable hash function will result * acceptable associative array performance. + * + * See: + * http://reality.sgi.com/chongo/src/fnv/fnv_hash.tar.gz + * http://reality.sgi.com/chongo/src/fnv/h32.c + * http://reality.sgi.com/chongo/src/fnv/h64.c + * + * for information on 32bit and 64bit Fowler/Noll/Vo hashs. */ #include "value.h" @@ -81,6 +88,11 @@ static QCKHASH blk_hash(BLOCK *blk, QCKHASH val); * is able to process 234936 words from the web2 dictionary without * any collisions. * + * See: + * http://reality.sgi.com/chongo/src/fnv/fnv_hash.tar.gz + * http://reality.sgi.com/chongo/src/fnv/h32.c + * http://reality.sgi.com/chongo/src/fnv/h64.c + * * given: * x the value to hash (must not be longer than 32 bits) * val previous QCKHASH value diff --git a/seed.c b/seed.c new file mode 100644 index 0000000..11d9d5c --- /dev/null +++ b/seed.c @@ -0,0 +1,326 @@ +/* + * seed - produce a pseudo-random seeds + * + * Generate a quasi-random seed based on system and process information. + * + * NOTE: This is not a good source of chaotic data. The lavarand + * system does a much better job of that. See: + * + * http://lavarand.sgi.com + * + * Copyright (c) 1999 by Landon Curt Noll. All Rights Reserved. + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby granted, + * provided that the above copyright, this permission notice and text + * this comment, and the disclaimer below appear in all of the following: + * + * supporting documentation + * source copies + * source works derived from this source + * binaries derived from this source or from derived source + * + * LANDON CURT NOLL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO + * EVENT SHALL LANDON CURT NOLL BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + * + * chongo was here /\../\ {chongo,noll}@{toad,sgi}.com + * + * Share and enjoy! :-) + */ + +#include +#include +#include + +/* + * PORTING NOTE: + * These includes are used by pseudo_seed(). If for some + * reason some of these include files are missing or damaged + * on your system, feel free to remove them (and the related + * calls inside pseudo_seed()), add or replace them. The + * pseudo_seed() function just needs to gather a bunch of + * information about the process and system state so the + * loss or inclusion of a few other calls should not hurt + * that much. + */ +#include +#include +#include +#include +#include +#if defined(__linux) +# include +# define DEV_URANDOM "/dev/urandom" +# define DEV_URANDOM_POOL 128 +#endif /* __linux */ +#include "qmath.h" +#include "longbits.h" + + +/* + * 64 bit hash value + */ +#if defined(HAVE_B64) +typedef USB64 hash64; +#else +struct s_hash64 { + USB32 w32[2]; +}; +typedef struct s_hash64 hash64; +#endif + + +/* + * hash_buf - perform a 64 bit Fowler/Noll/Vo hash on a buffer + * + * input: + * buf - start of buffer to hash + * len - length of buffer in octets + * hval - the hash value to modify + * + * returns: + * 64 bit hash as a static hash64 structure + */ +static hash64 +hash_buf(char *buf, unsigned len) +{ + hash64 hval; /* current hash value */ +#if !defined(HAVE_B64) + USB32 val[4]; /* hash value in base 2^16 */ + USB32 tmp[4]; /* tmp 64 bit value */ +#endif /* HAVE_B64 */ + char *buf_end = buf+len; /* beyond end of hash area */ + + /* + * Fowler/Noll/Vo hash - hash each character in the string + * + * The basis of the hash algorithm was taken from an idea + * sent by Email to the IEEE POSIX P1003.2 mailing list from + * Phong Vo (kpv@research.att.com) and Glenn Fowler + * (gsf@research.att.com). + * + * See: + * http://reality.sgi.com/chongo/src/fnv/fnv_hash.tar.gz + * http://reality.sgi.com/chongo/src/fnv/h32.c + * http://reality.sgi.com/chongo/src/fnv/h64.c + * + * for information on 32bit and 64bit Fowler/Noll/Vo hashes. + * + * Landon Curt Noll (chongo@toad.com) later improved on their + * algorithm to come up with Fowler/Noll/Vo hash. + * + * The 32 hash was able to process 234936 words from the web2 dictionary + * without any 32 bit collisions using a constant of + * 16777619 = 0x1000193. + * + * The 64 bit hash uses 1099511628211 = 0x100000001b3 instead. + */ +#if defined(HAVE_B64) + /* hash each octet of the buffer */ + for (hval = (hash64)0ULL; buf < buf_end; ++buf) { + + /* multiply by 1099511628211ULL mod 2^64 using 64 bit longs */ + hval *= (hash64)1099511628211ULL; + + /* xor the bottom with the current octet */ + hval ^= (hash64)(*buf); + } + +#else /* HAVE_B64 */ + + /* hash each octet of the buffer */ + for (val[0]=val[1]=val[2]=val[3]=0; buf < buf_end; ++buf) { + + /* + * multiply by 1099511628211 mod 2^64 using 32 bit longs + * + * Using 1099511628211, we have the following digits base 2^16: + * + * 0x0 0x100 0x0 0x1b3 + */ + /* multiply by the lowest order digit base 2^16 */ + tmp[0] = val[0] * 0x1b3; + tmp[1] = val[1] * 0x1b3; + tmp[2] = val[2] * 0x1b3; + tmp[3] = val[3] * 0x1b3; + /* multiply by the other non-zero digit */ + tmp[2] += val[0] << 8; /* tmp[2] += val[0] * 0x100 */ + tmp[3] += val[1] << 8; /* tmp[1] += val[1] * 0x100 */ + /* proapage carries */ + tmp[1] += (tmp[0] >> 16); + val[0] = tmp[0] & 0xffff; + tmp[2] += (tmp[1] >> 16); + val[1] = tmp[1] & 0xffff; + val[3] += (tmp[2] >> 16); + val[2] = tmp[2] & 0xffff; + /* + * Doing a val[3] &= 0xffff; is not really needed since it simply + * removes multiples of 2^64. We can discard these excess bits + * outside of the loop when we convert to hash64. + */ + + /* xor the bottom with the current octet */ + val[0] ^= (USB32)(*buf); + } + + /* convert to hash64 */ + /* hval.w32[1] = 0xffff&(val[3]<<16)+val[2]; */ + hval.w32[1] = val[3]<<16 + val[2]; + hval.w32[0] = val[1]<<16 + val[0]; + +#endif /* HAVE_B64 */ + + /* return our hash value */ + return hval; +} + + +/* + * pseudo_seed - seed the generator with a quasi-random seed + * + * Generate a quasi-random seed based on system and process information. + * + * NOTE: This is not a good source of chaotic data. The lavarand + * system does a much better job of that. See: + * + * http://lavarand.sgi.com + * + * PORTING NOTE: + * If when porting this code to your system and something + * won't compile, just remove that line or replace it with + * some other system call. We don't have to have every call + * operating below. We only want to hash the resulting data. + * + * returns: + * a pseudo-seed as a NUMBER over the range [0, 2^64) + */ +NUMBER * +pseudo_seed(void) +{ + struct { /* data used for quasi-random seed */ +#if defined(__sgi) + struct timespec sgi_cycle; /* SGI hardware clock */ + prid_t getprid; /* project ID */ + struct timespec realtime; /* POSIX realtime clock */ +#endif /* __sgi */ +#if defined(__linux) + int urandom_fd; /* open scriptor for /dev/urandom */ + int urandom_ret; /* read() of /dev/random */ + char urandom_pool[DEV_URANDOM_POOL]; /* /dev/urandom data pool */ +#endif /* __linux */ + struct timeval tp; /* time of day */ + pid_t getsid; /* session ID */ + pid_t getpgid; /* process group ID */ + pid_t getpid; /* process ID */ + pid_t getppid; /* parent process ID */ + uid_t getuid; /* real user ID */ + uid_t geteuid; /* effective user ID */ + gid_t getgid; /* real group ID */ + gid_t getegid; /* effective group ID */ + struct stat stat_dot; /* stat of "." */ + struct stat stat_dotdot; /* stat of ".." */ + struct stat stat_tmp; /* stat of "/tmp" */ + struct stat stat_root; /* stat of "/" */ + struct stat fstat_stdin; /* stat of stdin */ + struct stat fstat_stdout; /* stat of stdout */ + struct stat fstat_stderr; /* stat of stderr */ + struct ustat ustat_dot; /* usage stat of "." */ + struct ustat ustat_dotdot; /* usage stat of ".." */ + struct ustat ustat_tmp; /* usage stat of "/tmp" */ + struct ustat ustat_root; /* usage stat of "/" */ + struct ustat ustat_stdin; /* usage stat of stdin */ + struct ustat ustat_stdout; /* usage stat of stdout */ + struct ustat ustat_stderr; /* usage stat of stderr */ + struct rusage rusage; /* resource utilization */ + struct rusage rusage_chld; /* resource utilization of children */ + struct timeval tp2; /* time of day again */ + size_t size; /* size of this data structure */ + jmp_buf env; /* setjmp() context */ + char *sdata_p; /* address of this structure */ + } sdata; + hash64 hash_val; /* fnv64 hash of sdata */ + ZVALUE hash; /* hash_val as a ZVALUE */ + NUMBER *ret; /* return seed as a NUMBER */ + + /* + * pick up process/system information + * + * NOTE: + * We do care (that much) if these calls fail. We do not + * need to process any data in the 'sdata' structure. + */ +#if defined(__sgi) + (void) clock_gettime(CLOCK_SGI_CYCLE, &sdata.sgi_cycle); + sdata.getprid = getprid(); + (void) clock_gettime(CLOCK_REALTIME, &sdata.realtime); +#endif /* __sgi */ +#if defined(__linux) + sdata.urandom_fd = open(DEV_URANDOM, O_NONBLOCK|O_RDONLY); + if (sdata.urandom_fd >= 0) { + sdata.urandom_ret = read(sdata.urandom_fd, + &sdata.urandom_pool, DEV_URANDOM_POOL); + close(sdata.urandom_fd); + } else { + memset(&sdata.urandom_pool, EOF, DEV_URANDOM_POOL); + sdata.urandom_ret = EOF; + } +#endif /* __linux */ + (void) gettimeofday(&sdata.tp); + sdata.getsid = getsid((pid_t)0); + sdata.getpgid = getpgid((pid_t)0); + sdata.getpid = getpid(); + sdata.getppid = getppid(); + sdata.getuid = getuid(); + sdata.geteuid = geteuid(); + sdata.getgid = getgid(); + sdata.getegid = getegid(); + (void) stat(".", &sdata.stat_dot); + (void) stat("..", &sdata.stat_dotdot); + (void) stat("/tmp", &sdata.stat_tmp); + (void) stat("/", &sdata.stat_root); + (void) fstat(0, &sdata.fstat_stdin); + (void) fstat(1, &sdata.fstat_stdout); + (void) fstat(2, &sdata.fstat_stderr); + (void) ustat(sdata.stat_dotdot.st_dev, &sdata.ustat_dotdot); + (void) ustat(sdata.stat_dot.st_dev, &sdata.ustat_dot); + (void) ustat(sdata.stat_tmp.st_dev, &sdata.ustat_tmp); + (void) ustat(sdata.stat_root.st_dev, &sdata.ustat_root); + (void) ustat(sdata.fstat_stdin.st_dev, &sdata.ustat_stdin); + (void) ustat(sdata.fstat_stdout.st_dev, &sdata.ustat_stdout); + (void) ustat(sdata.fstat_stderr.st_dev, &sdata.ustat_stderr); + (void) getrusage(RUSAGE_SELF, &sdata.rusage); + (void) getrusage(RUSAGE_CHILDREN, &sdata.rusage_chld); + (void) gettimeofday(&sdata.tp2); + sdata.size = sizeof(sdata); + (void) setjmp(sdata.env); + sdata.sdata_p = (char *)&sdata; + + /* + * seed the generator with the above data + */ + hash_val = hash_buf((char *)&sdata, sizeof(sdata)); + + /* + * load the hash data into the ZVALUE + * + * We do not care about byte-order or endian issues, we just + * want to load in data. + */ + hash.len = sizeof(hash_val) / sizeof(HALF); + hash.v = alloc(hash.len); + hash.sign = 0; + memcpy((void *)hash.v, (void *)&hash_val, hash.len*sizeof(HALF)); + ztrim(&hash); + + /* + * return a number + */ + ret = qalloc(); + ret->num = hash; + return ret; +} diff --git a/string.c b/string.c index a1ebcec..9047e08 100644 --- a/string.c +++ b/string.c @@ -1195,8 +1195,7 @@ addstring(char *str, long len) } s->s_str = c; s->s_len = len; - while (len-- >= 0) - *c++ = *str++; + memcpy(s->s_str, str, len+1); if (havefirst) { stringconsttable[first] = s; return first; diff --git a/value.c b/value.c index 5d29d27..ac04b2f 100644 --- a/value.c +++ b/value.c @@ -142,7 +142,6 @@ protectall(VALUE *vp, int sts) void copyvalue(VALUE *oldvp, VALUE *newvp) { - newvp->v_type = oldvp->v_type; if (oldvp->v_type >= 0) { switch (oldvp->v_type) { @@ -205,7 +204,7 @@ copyvalue(VALUE *oldvp, VALUE *newvp) /*NOTREACHED*/ } } - newvp->v_subtype |= oldvp->v_subtype; + newvp->v_subtype = oldvp->v_subtype; } diff --git a/version.c b/version.c index d850434..8e43f42 100644 --- a/version.c +++ b/version.c @@ -12,7 +12,7 @@ #define MAJOR_VER 2 /* major version */ #define MINOR_VER 11 /* minor version */ #define MAJOR_PATCH 0 /* patch level or 0 if no patch */ -#define MINOR_PATCH "4" /* test number or empty string if no patch */ +#define MINOR_PATCH "5" /* test number or empty string if no patch */ /* * calc version constants diff --git a/zfunc.c b/zfunc.c index 609670e..1f5d393 100644 --- a/zfunc.c +++ b/zfunc.c @@ -1123,6 +1123,7 @@ zlog(ZVALUE z1, ZVALUE z2) if (zp != squares) zfree(*zp); } + zfree(val); return power; } @@ -1173,6 +1174,7 @@ zlog10(ZVALUE z) zfree(temp); } } + zfree(val); return power; } @@ -1323,6 +1325,7 @@ zgcdrem(ZVALUE z1, ZVALUE z2, ZVALUE *res) res->v = alloc(z1.len); res->sign = 0; zcopyval(z1, *res); + zfree(tmp1); return; } zequo(z1, tmp1, &tmp2); @@ -1340,6 +1343,7 @@ zgcdrem(ZVALUE z1, ZVALUE z2, ZVALUE *res) zfree(z2); z2 = tmp1; } + zfree(z2); *res = z1; } diff --git a/zio.c b/zio.c index e8c30d9..3c46bb5 100644 --- a/zio.c +++ b/zio.c @@ -238,6 +238,7 @@ math_getdivertedio(void) outbufused = sp->outbufused; outbuf = sp->outbuf; outputisstring = sp->outputisstring; + free(sp); return cp; } @@ -394,7 +395,7 @@ zprintb(ZVALUE z, long width) PUTSTR("0b"); while (len-- >= 0) { val = *hp--; - mask = (1 << (BASEB - 1)); + mask = ((HALF)1 << (BASEB - 1)); while (mask) { ch = '0' + ((mask & val) != 0); if (didprint || (ch != '0')) { diff --git a/zmath.c b/zmath.c index 6282d04..173c21e 100644 --- a/zmath.c +++ b/zmath.c @@ -741,7 +741,7 @@ done: while (m > 0 && A[m - 1] == 0) f = *b & 1 ? TOPHALF : 0; } if (g == BASE && f == 0) { - while (i-- && (*--a | *--b) == 0); + while (i-- && (*a-- | *b--) == 0); t = (i > 0); } else if (g >= BASE) @@ -903,8 +903,9 @@ zequo(ZVALUE z1, ZVALUE z2, ZVALUE *res) n = z2.len - o; len = m - n + 1; /* Maximum length of quotient */ v = *B; - A = alloc(len); + A = alloc(len+1); memcpy(A, z1.v + o, len * sizeof(HALF)); + A[len] = 0; if (n == 1) { if (v > 1) { a = A + len; @@ -916,8 +917,7 @@ zequo(ZVALUE z1, ZVALUE z2, ZVALUE *res) f %= v; } } - } - else { + } else { k = 0; while (!(v & 1)) { k++; diff --git a/zrand.c b/zrand.c index 2404981..6cf74d4 100644 --- a/zrand.c +++ b/zrand.c @@ -816,6 +816,7 @@ zsrand(CONST ZVALUE *pseed, CONST MATRIX *pmat55) RAND *ret; /* previous a55 state */ CONST VALUE *v; /* value from a passed matrix */ ZVALUE zscram; /* scrambled 64 bit seed */ + ZVALUE ztmp; /* temp holding value for zscram */ ZVALUE seed; /* to hold *pseed */ FULL shufxor[SLEN]; /* zshufxor as an 64 bit array of FULLs */ long indx; /* index to shuffle slots for seeding */ @@ -938,7 +939,9 @@ zsrand(CONST ZVALUE *pseed, CONST MATRIX *pmat55) for (i=A55-1; i > 0 && !zislezero(zscram); --i) { /* determine what we will swap with */ - indx = zdivi(zscram, i+1, &zscram); + indx = zdivi(zscram, i+1, &ztmp); + zfree(zscram); + zscram = ztmp; /* do nothing if swap with itself */ if (indx == i) { @@ -949,6 +952,8 @@ zsrand(CONST ZVALUE *pseed, CONST MATRIX *pmat55) SSWAP(a55, i, indx); } zfree(zscram); + } else if (pseed != NULL) { + zfree(zscram); } /* diff --git a/zrandom.c b/zrandom.c index 50a4584..3205112 100644 --- a/zrandom.c +++ b/zrandom.c @@ -1623,7 +1623,9 @@ zsrandom1(CONST ZVALUE seed, BOOL need_ret) /* set to the default generator state */ zfree(blum.n); zfree(blum.r); - blum = *randomcopy(&init_blum); + p_blum = randomcopy(&init_blum); + blum = *p_blum; + free(p_blum); /* * srandom(seed >= 2^32) @@ -2398,7 +2400,8 @@ randomfree(RANDOM *state) if (state == &init_blum) { return; } - if (state >= random_pregen && state < random_pregen+BLUM_PREGEN) { + if (state >= &random_pregen[0] && + state <= &random_pregen[BLUM_PREGEN-1]) { return; }