From 2c9b160dc5dc743623a51e371abe7868e6a3a366 Mon Sep 17 00:00:00 2001 From: Landon Curt Noll Date: Thu, 18 Nov 1999 05:43:44 -0800 Subject: [PATCH] Release calc version 2.11.0t10.4 --- CHANGES | 61 ++++++++- HOWTO.INSTALL | 5 - Makefile | 28 +---- addop.c | 85 +++++++++---- calc.h | 3 +- calc.man | 5 +- config.c | 319 +++++++++++++++++++++++++++-------------------- config.h | 16 ++- func.c | 4 +- hash.c | 72 ++++++----- help/Makefile | 14 +-- help/base | 49 ++++++-- help/config | 245 +++++++++++++++++++++++++++++++----- help/environment | 2 - help/help | 1 - help/todo | 1 - hist.c | 49 +++++++- lib/Makefile | 2 +- lib/altbind | 49 -------- lib/regress.cal | 53 ++++---- nametype.h | 2 +- quickhash.c | 1 + string.c | 13 +- value.c | 3 +- version.c | 2 +- zmath.c | 43 +++---- 26 files changed, 736 insertions(+), 391 deletions(-) delete mode 100644 lib/altbind diff --git a/CHANGES b/CHANGES index 8267932..507d02b 100644 --- a/CHANGES +++ b/CHANGES @@ -44,7 +44,66 @@ The following are the changes from calc version 2.11.0t10 to date: Added calcliblist and calcliblistfmt utility Makefile rules to allow one to print the list of distribution files that are used (but not - built) to form a .a calc library. + built) to form either the libcalc.a or the libcustcalc.a library. + + Added a patch from Randall.Gray@marine.csiro.au to make ^D terminate, + but *only* if the line it is on is completely empty. Removed lib/altbind + and removed the CALCBINDINGS Makefile variable. + + A new config("ctrl_d") value controls how the ``delete_char'', which + by default is bound to ^D (Control D), will or will not exit calc: + + config("ctrl_d", "virgin_eof") + + If ^D is the only character that has been typed on a line, + then calc will exit. Otherwise ^D will act according to the + calc binding, which by default is a Emacs-style delete-char. + + This is the default mode. + + config("ctrl_d", "never_eof") + + The ^D never exits calc and only acts according calc binding, + which by default is a Emacs-style delete-char. + + Emacs purists may want to set this in their ~/.calcrc startup file. + + config("ctrl_d", "empty_eof") + + The ^D always exits calc if typed on an empty line. This + condition occurs when ^D either the first character typed, + or when all other characters on the line have been removed + (say by deleting them). + + Users who always want to exit when ^D is typed at the beginning + of a line may want to set this in their ~/.calcrc startup file. + + Note that config("ctrl_d") apples to the character bound to each + and every ``delete_char''. So if an alternate binding it setup, + then those char(s) will have this functionality. + + Updated help/config and help/mode, improved the readability and + fixed a few typos. Documented modes, block formats and block bases + ("mode", "blkfmt" & "blkbase") that were previously left off out of + the documentation. + + The config("blkbase") and config("blkfmt") values return strings + instead of returning integers. One cannot use integers to set + these values, so returning integers was useless. + + The following config values return "on" or "off" strings: + + tilde tab leadzero fullzero blkverbose verbose_quit + + These config values can still be set with same boolean strings + ("on", "off", "true", "false", "t", ...) as well as via the + numerical values 0 (for "off") and non-0 (for "on"), however. + + Applied the dangling name fix from Ernest Bowen . + + Show func prints function on order of their indices, and with + config("lib_debug") & 4 == 4 some more details about the functions + are displayed. The following are the changes from calc version 2.11.0t8.9.1 to 2.11.0t9.4.5: diff --git a/HOWTO.INSTALL b/HOWTO.INSTALL index 377e02d..cb1c471 100644 --- a/HOWTO.INSTALL +++ b/HOWTO.INSTALL @@ -19,11 +19,6 @@ Installing calc in 4 easy steps: As shipped the Makefile assumes 'more'. On your system you may find 'less' to be a better pager. - The CALCBINDINGS is matter of personal taste. As shipped - the Makefile assumes a default quasi-emacs-like command - line editor. Changing CALCBINDINGS= altbind will cause ^D - to end calc in a fashion similar to that of the bc(1) command. - Set TOPDIR to be the place under which help files, calc, include files and calc libs are to be installed. As shipped the Makefile assumes a TOPDIR of /usr/local/lib. diff --git a/Makefile b/Makefile index 315ad4c..a58f1db 100644 --- a/Makefile +++ b/Makefile @@ -402,23 +402,11 @@ CALCPATH= .:./lib:~/lib:${LIBDIR}:${CUSTOMLIBDIR} # CALCRC= ${LIBDIR}/startup:~/.calcrc -# If the $CALCBINDINGS environment variable is not defined, then the following -# file will be used for the command line and edit history key bindings. -# The $CALCPATH will be used to search for this file. -# -# ${LIBDIR}/bindings uses ^D for editing -# ${LIBDIR}/altbind uses ^D for EOF -# -# NOTE: This facility is disabled if USE_READLINE is set to -DUSE_READLINE. -# -CALCBINDINGS= bindings -#CALCBINDINGS= altbind - # Determine of the GNU-readline facility will be used instead of the -# built-in CALCBINDINGS above. +# built-in calc binding method. # -# USE_READLINE= Do not use GNU-readline, use CALCBINDINGS -# USE_READLINE= -DUSE_READLINE Use GNU-readline, do not use CALCBINDINGS +# USE_READLINE= Do not use GNU-readline, use calc bindings +# USE_READLINE= -DUSE_READLINE Use GNU-readline, do not use calc bindings # # NOTE: If you select the 'USE_READLINE= -DUSE_READLINE' mode, you must set: # @@ -1094,8 +1082,7 @@ calc.1: calc.man ${MAKE_FILE} -rm -f calc.1 ${SED} -e 's:$${LIBDIR}:${LIBDIR}:g' \ -e 's,$${CALCPATH},${CALCPATH},g' \ - -e 's,$${CALCRC},${CALCRC},g' \ - -e 's,$${CALCBINDINGS},${CALCBINDINGS},g' < calc.man > calc.1 + -e 's,$${CALCRC},${CALCRC},g' < calc.man > calc.1 ## # @@ -1159,11 +1146,6 @@ conf.h: ${MAKE_FILE} ${Q}echo '#define DEFAULTCALCRC "${CALCRC}"' >> conf.h ${Q}echo '#endif /* DEFAULTCALCRC */' >> conf.h ${Q}echo '' >> conf.h - ${Q}echo '/* the default key bindings file */' >> conf.h - ${Q}echo '#ifndef DEFAULTCALCBINDINGS' >> conf.h - ${Q}echo '#define DEFAULTCALCBINDINGS "${CALCBINDINGS}"' >> conf.h - ${Q}echo '#endif /* DEFAULTCALCBINDINGS */' >> conf.h - ${Q}echo '' >> conf.h ${Q}echo '/* the location of the help directory */' >> conf.h ${Q}echo '#ifndef HELPDIR' >> conf.h ${Q}echo '#define HELPDIR "${HELPDIR}"' >> conf.h @@ -2652,7 +2634,6 @@ env: @echo "MANMAKE=${MANMAKE}"; echo "" @echo "CALCPATH=${CALCPATH}"; echo "" @echo "CALCRC=${CALCRC}"; echo "" - @echo "CALCBINDINGS=${CALCBINDINGS}"; echo "" @echo "CALCPAGER=${CALCPAGER}"; echo "" @echo "DEBUG=${DEBUG}"; echo "" @echo "NO_SHARED=${NO_SHARED}"; echo "" @@ -2964,6 +2945,7 @@ install: calc libcalc.a ${LIB_H_SRC} ${BUILD_H_SRC} calc.1 -rm -f ${LIBDIR}/libcalcerr.a libcalcerr.a -rm -f ${LIBDIR}/calc_errno.h calc_errno.h ${INCDIRCALC}/calc_errno.h -rm -f calc_errno.c calc_errno.o calc_errno + -rm -f ${LIBDIR}/altbind ${HELPDIR}/altbind ${V} echo '=-=-=-=-= end of $@ rule =-=-=-=-=' ## diff --git a/addop.c b/addop.c index 974d382..01eea23 100644 --- a/addop.c +++ b/addop.c @@ -22,6 +22,7 @@ static long maxopcodes; /* number of opcodes available */ static long newindex; /* index of new function */ +static char *newname; /* name of new function */ static long oldop; /* previous opcode */ static long oldoldop; /* opcode before previous opcode */ static long debugline; /* line number of latest debug opcode */ @@ -61,26 +62,49 @@ initfunctions(void) void showfunctions(void) { - FUNC **fpp; /* pointer into function table */ FUNC *fp; /* current function */ long count; + long index; count = 0; if (funccount > 0) { - for (fpp = &functions[funccount - 1]; fpp >= functions; fpp--) { - fp = *fpp; - if (fp == NULL) - continue; - if (count++ == 0) { - printf("Name Arguments\n---- ---------\n"); + if (conf->lib_debug & LIBDBG_FUNC_INFO) + math_str("Index\tName \tArgs\tOpcodes\n" + "-----\t------ \t---- \t------\n"); + else + math_str("Name\tArguments\n" + "----\t---------\n"); + for (index = 0; index < funccount; index++) { + fp = functions[index]; + if (conf->lib_debug & LIBDBG_FUNC_INFO) { + + math_fmt("%5ld\t%-12s\t", index, + namestr(&funcnames,index)); + if (fp) { + count++; + math_fmt("%-5d\t%-5ld\n", + fp->f_paramcount, fp->f_opcodecount); + } else { + math_str("null\t0\n"); + } + } else { + if (fp == NULL) + continue; + count++; + math_fmt("%-12s\t%-2d\n", namestr(&funcnames, + index), fp->f_paramcount); } - printf("%-12s %-2d\n", fp->f_name, fp->f_paramcount); } } - if (count > 0) { - printf("\nNumber: %ld\n", count); + if (conf->lib_debug & LIBDBG_FUNC_INFO) { + math_fmt("\nNumber non-null: %ld\n", count); + math_fmt("Number null: %ld\n", funccount - count); + math_fmt("Total number: %ld\n", funccount); } else { - printf("No user functions defined\n"); + if (count > 0) + math_fmt("\nNumber: %ld\n", count); + else + math_str("No user functions defined\n"); } } @@ -115,7 +139,8 @@ beginfunc(char *name, BOOL newflag) fp->f_opcodecount = 0; fp->f_savedvalue.v_type = V_NULL; fp->f_savedvalue.v_subtype = V_NOSUBTYPE; - fp->f_name = namestr(&funcnames, newindex); + newname = namestr(&funcnames, newindex); + fp->f_name = newname; curfunc = fp; initlocals(); initlabels(); @@ -142,10 +167,11 @@ endfunc(void) addop(OP_UNDEF); addop(OP_RETURN); } + checklabels(); + if (errorcount) { - freefunc(curfunc); - printf("\"%s\": %ld error%s\n", curfunc->f_name, errorcount, + printf("\"%s\": %ld error%s\n", newname, errorcount, ((errorcount == 1) ? "" : "s")); return; } @@ -167,7 +193,7 @@ endfunc(void) } if ((inputisterminal() && conf->lib_debug & LIBDBG_STDIN_FUNC) || (!inputisterminal() && conf->lib_debug & LIBDBG_FILE_FUNC)) { - printf("%s(", fp->f_name); + printf("%s(", newname); for (index = 0; index < fp->f_paramcount; index++) { if (index) putchar(','); @@ -231,7 +257,7 @@ rmuserfunc(char *name) index = findstr(&funcnames, name); if (index < 0) { - printf("%s() has never been defined\n", + fprintf(stderr, "%s() has never been defined\n", name); return; } @@ -252,12 +278,25 @@ rmuserfunc(char *name) void freefunc(FUNC *fp) { + long index; long i; if (fp == NULL) return; + if (fp == curfunc) { + index = newindex; + } else { + for (index = 0; index < funccount; index++) { + if (functions[index] == fp) + break; + } + if (index == funccount) { + math_error("Bad call to freefunc!!!"); + /*NOTREACHED*/ + } + } if (conf->traceflags & TRACE_FNCODES) { - printf("Freeing function \"%s\"\n", fp->f_name); + printf("Freeing function \"%s\"\n",namestr(&funcnames,index)); dumpnames = FALSE; for (i = 0; i < fp->f_opcodecount; ) { printf("%ld: ", i); @@ -273,12 +312,14 @@ freefunc(FUNC *fp) void rmalluserfunc(void) { - FUNC **fpp; + FUNC *fp; + long index; - for (fpp = functions; fpp < &functions[funccount]; fpp++) { - if (*fpp) { - freefunc(*fpp); - *fpp = NULL; + for (index = 0; index < funccount; index++) { + fp = functions[index]; + if (fp) { + freefunc(fp); + functions[index] = NULL; } } } diff --git a/calc.h b/calc.h index 2e419ae..2b1e44f 100644 --- a/calc.h +++ b/calc.h @@ -22,10 +22,11 @@ */ #define CALCPATH "CALCPATH" /* environment variable for files */ #define CALCRC "CALCRC" /* environment variable for startup */ -#define CALCBINDINGS "CALCBINDINGS" /* environment variable for hist bindings */ +#define CALCBINDINGS "CALCBINDINGS" /* env variable for hist bindings */ #define HOME "HOME" /* environment variable for home dir */ #define PAGER "PAGER" /* environment variable for help */ #define SHELL "SHELL" /* environment variable for shell */ +#define DEFAULTCALCBINDINGS "bindings" /* default calc bindings file */ #define DEFAULTCALCHELP "help" /* help file that -h prints */ #define DEFAULTSHELL "sh" /* default shell to use */ #define CALCEXT ".cal" /* extension for files read in */ diff --git a/calc.man b/calc.man index ee62e75..9909680 100644 --- a/calc.man +++ b/calc.man @@ -555,9 +555,10 @@ line, or \fI\-m\fP disallows opening files for reading), reads key bindings from the filename specified by this environment variable. -.br +The key binding file is searched for along the $CALCPATH list +of directories. .sp -Default value: ${CALCBINDINGS} +Default value: binding .sp This variable is not used if calc was compiled with GNU-readline support. In that case, the standard readline mechanisms (see readline(3)) are used. diff --git a/config.c b/config.c index 125b738..316011a 100644 --- a/config.c +++ b/config.c @@ -56,6 +56,8 @@ NAMETYPE configs[] = { {"calc_debug", CONFIG_CALC_DEBUG}, {"user_debug", CONFIG_USER_DEBUG}, {"verbose_quit",CONFIG_VERBOSE_QUIT}, + {"ctrl_d", CONFIG_CTRL_D}, + {"ctrl-d", CONFIG_CTRL_D}, /* alias for ctrl_d */ {NULL, 0} }; @@ -97,7 +99,8 @@ CONFIG oldstd = { /* backward compatible standard configuration */ 0, /* internal calc debug level */ 3, /* calc library debug level */ 0, /* user defined debug level */ - TRUE /* print Quit or abort executed messages */ + TRUE, /* print Quit or abort executed messages */ + CTRL_D_VIRGIN /* ^D only exits on virgin lines */ }; CONFIG newstd = { /* new non-backward compatible configuration */ MODE_INITIAL, /* current output mode */ @@ -133,7 +136,8 @@ CONFIG newstd = { /* new non-backward compatible configuration */ 0, /* internal calc debug level */ 3, /* calc library debug level */ 0, /* user defined debug level */ - TRUE /* print Quit or abort executed messages */ + TRUE, /* print Quit or abort executed messages */ + CTRL_D_VIRGIN /* ^D only exits on virgin lines */ }; CONFIG *conf = NULL; /* loaded in at startup - current configuration */ @@ -142,11 +146,15 @@ CONFIG *conf = NULL; /* loaded in at startup - current configuration */ * Possible output modes. */ static NAMETYPE modes[] = { + {"fraction", MODE_FRAC}, {"frac", MODE_FRAC}, - {"decimal", MODE_FRAC}, - {"dec", MODE_FRAC}, + {"integer", MODE_INT}, {"int", MODE_INT}, {"real", MODE_REAL}, + {"float", MODE_REAL}, + {"default", MODE_INITIAL}, /* MODE_REAL */ + {"scientific", MODE_EXP}, + {"sci", MODE_EXP}, {"exp", MODE_EXP}, {"hexadecimal", MODE_HEX}, {"hex", MODE_HEX}, @@ -158,34 +166,13 @@ static NAMETYPE modes[] = { }; -/* - * Possible binary config state values - */ -static NAMETYPE truth[] = { - {"y", TRUE}, - {"n", FALSE}, - {"yes", TRUE}, - {"no", FALSE}, - {"set", TRUE}, - {"unset", FALSE}, - {"on", TRUE}, - {"off", FALSE}, - {"true", TRUE}, - {"false", FALSE}, - {"t", TRUE}, - {"f", FALSE}, - {"1", TRUE}, - {"0", FALSE}, - {NULL, 0} -}; - - /* * Possible block base output modes */ static NAMETYPE blk_base[] = { {"hexadecimal", BLK_BASE_HEX}, {"hex", BLK_BASE_HEX}, + {"default", BLK_BASE_HEX}, {"octal", BLK_BASE_OCT}, {"oct", BLK_BASE_OCT}, {"character", BLK_BASE_CHAR}, @@ -202,17 +189,60 @@ static NAMETYPE blk_base[] = { * Possible block output formats */ static NAMETYPE blk_fmt[] = { - {"line", BLK_FMT_LINE}, {"lines", BLK_FMT_LINE}, - {"str", BLK_FMT_STRING}, - {"string", BLK_FMT_STRING}, + {"line", BLK_FMT_LINE}, {"strings", BLK_FMT_STRING}, - {"od", BLK_FMT_OD_STYLE}, - {"odstyle", BLK_FMT_OD_STYLE}, + {"string", BLK_FMT_STRING}, + {"str", BLK_FMT_STRING}, {"od_style", BLK_FMT_OD_STYLE}, - {"hd", BLK_FMT_HD_STYLE}, - {"hdstyle", BLK_FMT_HD_STYLE}, + {"odstyle", BLK_FMT_OD_STYLE}, + {"od", BLK_FMT_OD_STYLE}, {"hd_style", BLK_FMT_HD_STYLE}, + {"hdstyle", BLK_FMT_HD_STYLE}, + {"hd", BLK_FMT_HD_STYLE}, + {"default", BLK_FMT_HD_STYLE}, + {NULL, 0} +}; + + +/* + * Possible ctrl_d styles + */ +static NAMETYPE ctrl_d[] = { + {"virgin_eof", CTRL_D_VIRGIN}, + {"virgineof", CTRL_D_VIRGIN}, + {"virgin", CTRL_D_VIRGIN}, + {"default", CTRL_D_VIRGIN}, + {"never_eof", CTRL_D_EMACS}, + {"nevereof", CTRL_D_EMACS}, + {"never", CTRL_D_EMACS}, + {"empty_eof", CTRL_D_EOF}, + {"emptyeof", CTRL_D_EOF}, + {"empty", CTRL_D_EOF}, + {NULL, 0} +}; + + +/* + * Possible binary config state values + */ +#define TRUE_STRING "on" +#define FALSE_STRING "off" +static NAMETYPE truth[] = { + {TRUE_STRING, TRUE}, + {"true", TRUE}, + {"t", TRUE}, + {"yes", TRUE}, + {"y", TRUE}, + {"set", TRUE}, + {"1", TRUE}, + {FALSE_STRING, FALSE}, + {"false", FALSE}, + {"f", FALSE}, + {"no", FALSE}, + {"n", FALSE}, + {"unset", FALSE}, + {"0", FALSE}, {NULL, 0} }; @@ -220,11 +250,8 @@ static NAMETYPE blk_fmt[] = { /* * declate static functions */ -static int modetype(char *name); -static int blkbase(char *name); -static int blkfmt(char *name); -static int truthtype(char *name); -static char *modename(int type); +static long lookup_long(NAMETYPE *set, char *name); +static char *lookup_name(NAMETYPE *set, long val); /* @@ -249,18 +276,21 @@ configtype(char *name) /* - * Given the name of a mode, convert it to the internal format. - * Returns -1 if the string is unknown. + * lookup_long - given a name and a NAMETYPE, return the int * * given: - * name mode name + * set the NAMESET array of name/int pairs + * name mode name + * + * returns: + * numeric value of the name or -1 if not found */ -static int -modetype(char *name) +static long +lookup_long(NAMETYPE *set, char *name) { NAMETYPE *cp; /* current config pointer */ - for (cp = modes; cp->name; cp++) { + for (cp = set; cp->name; cp++) { if (strcmp(cp->name, name) == 0) return cp->type; } @@ -269,78 +299,22 @@ modetype(char *name) /* - * Given the name of a block output base, convert it to the internal format. - * Returns -1 if the string is unknown. + * lookup_name - given numeric value and a NAMETYPE, return the name * * given: - * name mode name - */ -static int -blkbase(char *name) -{ - NAMETYPE *cp; /* current config pointer */ - - for (cp = blk_base; cp->name; cp++) { - if (strcmp(cp->name, name) == 0) - return cp->type; - } - return -1; -} - - -/* - * Given the name of a block output format, convert it to the internal format. - * Returns -1 if the string is unknown. + * set the NAMESET array of name/int pairs + * val numeric value to lookup * - * given: - * name mode name - */ -static int -blkfmt(char *name) -{ - NAMETYPE *cp; /* current config pointer */ - - for (cp = blk_fmt; cp->name; cp++) { - if (strcmp(cp->name, name) == 0) - return cp->type; - } - return -1; -} - - -/* - * Given the name of a truth value, convert it to a BOOL or -1. - * Returns -1 if the string is unknown. - * - * given: - * name mode name - */ -static int -truthtype(char *name) -{ - NAMETYPE *cp; /* current config pointer */ - - for (cp = truth; cp->name; cp++) { - if (strcmp(cp->name, name) == 0) - return cp->type; - } - return -1; -} - - -/* - * Given the mode type, convert it to a string representing that mode. - * Where there are multiple strings representing the same mode, the first - * one in the table is used. Returns NULL if the node type is unknown. - * The returned string cannot be modified. + * returns: + * name of the value found of NULL */ static char * -modename(int type) +lookup_name(NAMETYPE *set, long val) { NAMETYPE *cp; /* current config pointer */ - for (cp = modes; cp->name; cp++) { - if (type == cp->type) + for (cp = set; cp->name; cp++) { + if (val == cp->type) return cp->name; } return NULL; @@ -417,7 +391,7 @@ setconfig(int type, VALUE *vp) math_error("Non-string for mode"); /*NOTREACHED*/ } - temp = modetype(vp->v_str->s_str); + temp = lookup_long(modes, vp->v_str->s_str); if (temp < 0) { math_error("Unknown mode \"%s\"", vp->v_str); /*NOTREACHED*/ @@ -526,7 +500,7 @@ setconfig(int type, VALUE *vp) q = vp->v_num; conf->tilde_ok = !qiszero(q); } else if (vp->v_type == V_STR) { - temp = truthtype(vp->v_str->s_str); + temp = lookup_long(truth, vp->v_str->s_str); if (temp < 0) { math_error("Illegal truth value for tilde"); /*NOTREACHED*/ @@ -540,7 +514,7 @@ setconfig(int type, VALUE *vp) q = vp->v_num; conf->tab_ok = !qiszero(q); } else if (vp->v_type == V_STR) { - temp = truthtype(vp->v_str->s_str); + temp = lookup_long(truth, vp->v_str->s_str); if (temp < 0) { math_error("Illegal truth value for tab"); /*NOTREACHED*/ @@ -680,7 +654,7 @@ setconfig(int type, VALUE *vp) q = vp->v_num; conf->leadzero = !qiszero(q); } else if (vp->v_type == V_STR) { - temp = truthtype(vp->v_str->s_str); + temp = lookup_long(truth, vp->v_str->s_str); if (temp < 0) { { math_error("Illegal truth value for leadzero"); /*NOTREACHED*/ @@ -695,7 +669,7 @@ setconfig(int type, VALUE *vp) q = vp->v_num; conf->fullzero = !qiszero(q); } else if (vp->v_type == V_STR) { - temp = truthtype(vp->v_str->s_str); + temp = lookup_long(truth, vp->v_str->s_str); if (temp < 0) { { math_error("Illegal truth value for fullzero"); /*NOTREACHED*/ @@ -772,7 +746,7 @@ setconfig(int type, VALUE *vp) q = vp->v_num; conf->blkverbose = !qiszero(q); } else if (vp->v_type == V_STR) { - temp = truthtype(vp->v_str->s_str); + temp = lookup_long(truth, vp->v_str->s_str); if (temp < 0) { math_error("Illegal truth value for blkverbose"); /*NOTREACHED*/ @@ -786,7 +760,7 @@ setconfig(int type, VALUE *vp) math_error("Non-string for blkbase"); /*NOTREACHED*/ } - temp = blkbase(vp->v_str->s_str); + temp = lookup_long(blk_base, vp->v_str->s_str); if (temp < 0) { math_error("Unknown mode \"%s\" for blkbase", vp->v_str->s_str); @@ -800,7 +774,7 @@ setconfig(int type, VALUE *vp) math_error("Non-string for blkfmt"); /*NOTREACHED*/ } - temp = blkfmt(vp->v_str->s_str); + temp = lookup_long(blk_fmt, vp->v_str->s_str); if (temp < 0) { math_error("Unknown mode \"%s\" for blkfmt", vp->v_str->s_str); @@ -856,9 +830,9 @@ setconfig(int type, VALUE *vp) q = vp->v_num; conf->verbose_quit = !qiszero(q); } else if (vp->v_type == V_STR) { - temp = truthtype(vp->v_str->s_str); + temp = lookup_long(truth, vp->v_str->s_str); if (temp < 0) { - math_error("Illegal truth value" + math_error("Illegal truth value " "for verbose_quit"); /*NOTREACHED*/ } @@ -866,6 +840,20 @@ setconfig(int type, VALUE *vp) } break; + case CONFIG_CTRL_D: + if (vp->v_type != V_STR) { + math_error("Non-string for ctrl_d"); + /*NOTREACHED*/ + } + temp = lookup_long(ctrl_d, vp->v_str->s_str); + if (temp < 0) { + math_error("Unknown mode \"%s\" for ctrl_d", + vp->v_str->s_str); + /*NOTREACHED*/ + } + conf->ctrl_d = temp; + break; + default: math_error("Setting illegal config parameter"); /*NOTREACHED*/ @@ -986,6 +974,7 @@ void config_value(CONFIG *cfg, int type, VALUE *vp) { long i=0; + char *p; /* * firewall @@ -1017,7 +1006,12 @@ config_value(CONFIG *cfg, int type, VALUE *vp) case CONFIG_MODE: vp->v_type = V_STR; - vp->v_str = makenewstring(modename(cfg->outmode)); + p = lookup_name(modes, cfg->outmode); + if (p == NULL) { + math_error("invalid output mode: %d", cfg->outmode); + /*NOTREACHED*/ + } + vp->v_str = makenewstring(p); return; case CONFIG_EPSILON: @@ -1045,12 +1039,22 @@ config_value(CONFIG *cfg, int type, VALUE *vp) break; case CONFIG_TILDE: - i = cfg->tilde_ok; - break; + vp->v_type = V_STR; + if (cfg->tilde_ok) { + vp->v_str = makenewstring(TRUE_STRING); + } else { + vp->v_str = makenewstring(FALSE_STRING); + } + return; case CONFIG_TAB: - i = cfg->tab_ok; - break; + vp->v_type = V_STR; + if (cfg->tab_ok) { + vp->v_str = makenewstring(TRUE_STRING); + } else { + vp->v_str = makenewstring(FALSE_STRING); + } + return; case CONFIG_QUOMOD: i = cfg->quomod; @@ -1089,12 +1093,22 @@ config_value(CONFIG *cfg, int type, VALUE *vp) break; case CONFIG_LEADZERO: - i = cfg->leadzero; - break; + vp->v_type = V_STR; + if (cfg->leadzero) { + vp->v_str = makenewstring(TRUE_STRING); + } else { + vp->v_str = makenewstring(FALSE_STRING); + } + return; case CONFIG_FULLZERO: - i = cfg->fullzero; - break; + vp->v_type = V_STR; + if (cfg->fullzero) { + vp->v_str = makenewstring(TRUE_STRING); + } else { + vp->v_str = makenewstring(FALSE_STRING); + } + return; case CONFIG_MAXSCAN: i = cfg->maxscancount; @@ -1115,16 +1129,33 @@ config_value(CONFIG *cfg, int type, VALUE *vp) break; case CONFIG_BLKVERBOSE: - i = cfg->blkverbose; - break; + vp->v_type = V_STR; + if (cfg->blkverbose) { + vp->v_str = makenewstring(TRUE_STRING); + } else { + vp->v_str = makenewstring(FALSE_STRING); + } + return; case CONFIG_BLKBASE: - i = cfg->blkbase; - break; + vp->v_type = V_STR; + p = lookup_name(blk_base, cfg->blkbase); + if (p == NULL) { + math_error("invalid block base: %d", cfg->blkbase); + /*NOTREACHED*/ + } + vp->v_str = makenewstring(p); + return; case CONFIG_BLKFMT: - i = cfg->blkfmt; - break; + vp->v_type = V_STR; + p = lookup_name(blk_fmt, cfg->blkfmt); + if (p == NULL) { + math_error("invalid block format: %d", cfg->blkfmt); + /*NOTREACHED*/ + } + vp->v_str = makenewstring(p); + return; case CONFIG_CALC_DEBUG: i = cfg->calc_debug; @@ -1139,8 +1170,23 @@ config_value(CONFIG *cfg, int type, VALUE *vp) break; case CONFIG_VERBOSE_QUIT: - i = cfg->verbose_quit; - break; + vp->v_type = V_STR; + if (cfg->verbose_quit) { + vp->v_str = makenewstring(TRUE_STRING); + } else { + vp->v_str = makenewstring(FALSE_STRING); + } + return; + + case CONFIG_CTRL_D: + vp->v_type = V_STR; + p = lookup_name(ctrl_d, cfg->ctrl_d); + if (p == NULL) { + math_error("invalid Control-D: %d", cfg->ctrl_d); + /*NOTREACHED*/ + } + vp->v_str = makenewstring(p); + return; default: math_error("Getting illegal CONFIG element"); @@ -1218,5 +1264,6 @@ config_cmp(CONFIG *cfg1, CONFIG *cfg2) cfg1->calc_debug != cfg2->calc_debug || cfg1->lib_debug != cfg2->lib_debug || cfg1->user_debug != cfg2->user_debug || - cfg1->verbose_quit != cfg2->verbose_quit; + cfg1->verbose_quit != cfg2->verbose_quit || + cfg1->ctrl_d != cfg2->ctrl_d; } diff --git a/config.h b/config.h index 690cb5c..e923564 100644 --- a/config.h +++ b/config.h @@ -81,6 +81,7 @@ #define CONFIG_CALC_DEBUG 31 #define CONFIG_USER_DEBUG 32 #define CONFIG_VERBOSE_QUIT 33 +#define CONFIG_CTRL_D 34 /* @@ -102,7 +103,9 @@ * * quickhash.c - config_hash() * hash.c - hash_value() - * config.c - setconfig(), config_value(), config_cmp() + * config.c - configs[], oldstd, newstd, setconfig(), + * config_value(), config_cmp() + * config.h - CONFIG_XYZ_SYMBOL (see above) */ struct config { int outmode; /* current output mode */ @@ -139,6 +142,7 @@ struct config { long lib_debug; /* library debug, see LIB_DEBUG_XXX below */ long user_debug; /* user defined debug value: 0 default */ BOOL verbose_quit; /* TRUE => print Quit or abort executed msg */ + int ctrl_d; /* see CTRL_D_xyz below */ }; typedef struct config CONFIG; @@ -148,7 +152,8 @@ typedef struct config CONFIG; */ #define LIBDBG_STDIN_FUNC (0x00000001) /* interactive func define debug */ #define LIBDBG_FILE_FUNC (0x00000002) /* file read func define debug */ -#define LIBDBG_MASK (0x00000003) +#define LIBDBG_FUNC_INFO (0x00000004) /* print extra info for show func */ +#define LIBDBG_MASK (0x00000007) /* @@ -162,6 +167,13 @@ typedef struct config CONFIG; #define CALCDBG_RUNSTATE (0x00000020) /* report run_state changes */ #define CALCDBG_MASK (0x0000003f) +/* + * ctrl-d meanings + */ +#define CTRL_D_VIRGIN (0) /* ^D only exits on virgin command lines */ +#define CTRL_D_EMACS (1) /* ^D never exits, emacs binding meaning only */ +#define CTRL_D_EOF (2) /* ^D always exits at start of line */ + /* * global configuration states and aliases diff --git a/func.c b/func.c index 1f22ef1..95723bd 100644 --- a/func.c +++ b/func.c @@ -6781,14 +6781,14 @@ f_blk(int count, VALUE **vals) int chunk; /* block chunk size */ VALUE result; int id; - VALUE *vp; + VALUE *vp = NULL; int type; /* initialize VALUE */ result.v_type = V_BLOCK; result.v_subtype = V_NOSUBTYPE; - type = 0; + type = V_NULL; if (count > 0) { vp = *vals; type = vp->v_type; diff --git a/hash.c b/hash.c index 9d3c630..03d0012 100644 --- a/hash.c +++ b/hash.c @@ -39,6 +39,15 @@ extern void shs1_init_state(HASH*); extern void MD5_init_state(HASH*); +/* + * hash_long can deal with BOOL's, int's, FLAGS's and LEN's + */ +#define hash_bool(type, val, state) (hash_long((type), (long)(val), (state))) +#define hash_int(type, val, state) (hash_long((type), (long)(val), (state))) +#define hash_flag(type, val, state) (hash_long((type), (long)(val), (state))) +#define hash_len(type, val, state) (hash_long((type), (long)(val), (state))) + + /* * hash_setup - setup the hash state for a given hash */ @@ -257,6 +266,9 @@ hash_final(HASH *state) * This function will hash a long value as if it were a 64 bit value. * The input is a long. If a long is smaller than 64 bits, we will * hash a final 32 bits of zeros. + * + * This function is OK to hash BOOL's, unslogned long's, unsigned int's + * signed int's as well as FLAG's and LEN's. */ HASH * hash_long(int type, long longval, HASH *state) @@ -734,11 +746,10 @@ hash_value(int type, void *v, HASH *state) (state->type)(value->v_type, state); /* hash as if we have a 64 bit value */ - state = hash_long(type, (long)value->v_int, state); + state = hash_int(type, value->v_int, state); break; case V_NUM: - /* hash this type */ state = hash_number(type, value->v_num, state); break; @@ -884,12 +895,12 @@ hash_value(int type, void *v, HASH *state) (state->type)(value->v_type, state); /* hash the RAND state */ - state = hash_long(type, (long)value->v_rand->seeded, state); - state = hash_long(type, (long)value->v_rand->bits, state); + state = hash_int(type, value->v_rand->seeded, state); + state = hash_int(type, value->v_rand->bits, state); (state->update)(state, (USB8 *)value->v_rand->buffer, SLEN*FULL_BITS/8); - state = hash_long(type, (long)value->v_rand->j, state); - state = hash_long(type, (long)value->v_rand->k, state); + state = hash_int(type, value->v_rand->j, state); + state = hash_int(type, value->v_rand->k, state); (state->update)(state, (USB8 *)value->v_rand->slot, SCNT*FULL_BITS/8); (state->update)(state, @@ -903,8 +914,8 @@ hash_value(int type, void *v, HASH *state) (state->type)(value->v_type, state); /* hash the RANDOM state */ - state = hash_long(type, (long)value->v_random->seeded, state); - state = hash_long(type, (long)value->v_random->bits, state); + state = hash_int(type, value->v_random->seeded, state); + state = hash_int(type, value->v_random->bits, state); (state->update)(state, (USB8 *)&(value->v_random->buffer), BASEB/8); state = hash_zvalue(type, value->v_random->r, state); @@ -918,20 +929,19 @@ hash_value(int type, void *v, HASH *state) (state->type)(value->v_type, state); /* hash the CONFIG state */ - state = hash_long(type, (long)value->v_config->outmode, state); + state = hash_int(type, value->v_config->outmode, state); state = hash_long(type,(long)value->v_config->outdigits, state); state = hash_number(type, value->v_config->epsilon, state); state = hash_long(type, (long)value->v_config->epsilonprec, state); - state = hash_long(type, - (long)value->v_config->traceflags, state); + state = hash_flag(type, value->v_config->traceflags, state); state = hash_long(type, (long)value->v_config->maxprint, state); - state = hash_long(type, (long)value->v_config->mul2, state); - state = hash_long(type, (long)value->v_config->sq2, state); - state = hash_long(type, (long)value->v_config->pow2, state); - state = hash_long(type, (long)value->v_config->redc2, state); - state = hash_long(type, (long)value->v_config->tilde_ok, state); - state = hash_long(type, (long)value->v_config->tab_ok, state); + state = hash_len(type, value->v_config->mul2, state); + state = hash_len(type, value->v_config->sq2, state); + state = hash_len(type, value->v_config->pow2, state); + state = hash_len(type, value->v_config->redc2, state); + state = hash_bool(type, value->v_config->tilde_ok, state); + state = hash_bool(type, value->v_config->tab_ok, state); state = hash_long(type, (long)value->v_config->quomod, state); state = hash_long(type, (long)value->v_config->quo, state); state = hash_long(type, (long)value->v_config->mod, state); @@ -941,28 +951,26 @@ hash_value(int type, void *v, HASH *state) state = hash_long(type, (long)value->v_config->cfsim, state); state = hash_long(type, (long)value->v_config->outround, state); state = hash_long(type, (long)value->v_config->round, state); - state = hash_long(type, (long)value->v_config->leadzero, state); - state = hash_long(type, (long)value->v_config->fullzero, state); + state = hash_bool(type, value->v_config->leadzero, state); + state = hash_bool(type, value->v_config->fullzero, state); state = hash_long(type, (long)value->v_config->maxscancount, state); state = hash_str(type, value->v_config->prompt1, state); state->bytes = FALSE; /* as if just read words */ state = hash_str(type, value->v_config->prompt2, state); state->bytes = FALSE; /* as if just read words */ - state = hash_long(type, - (long)value->v_config->blkmaxprint, state); - state = hash_long(type, - (long)value->v_config->blkverbose, state); - state = hash_long(type, - (long)value->v_config->blkbase, state); - state = hash_long(type, - (long)value->v_config->blkfmt, state); + state = hash_int(type, value->v_config->blkmaxprint, state); + state = hash_bool(type, value->v_config->blkverbose, state); + state = hash_int(type, value->v_config->blkbase, state); + state = hash_int(type, value->v_config->blkfmt, state); state = hash_long(type, (long)value->v_config->lib_debug, state); state = hash_long(type, (long)value->v_config->calc_debug, state); state = hash_long(type, (long)value->v_config->user_debug, state); + state = hash_bool(type, value->v_config->verbose_quit, state); + state = hash_int(type, value->v_config->ctrl_d, state); break; case V_HASH: @@ -971,11 +979,11 @@ hash_value(int type, void *v, HASH *state) (state->type)(value->v_type, state); /* hash the HASH state */ - state = hash_long(type, (long)value->v_hash->type, state); - state = hash_long(type, (long)value->v_hash->bytes,state); - state = hash_long(type, (long)value->v_hash->base, state); - state = hash_long(type, (long)value->v_hash->chunksize, state); - state = hash_long(type, (long)value->v_hash->unionsize, state); + state = hash_int(type, value->v_hash->type, state); + state = hash_bool(type, value->v_hash->bytes,state); + state = hash_int(type, value->v_hash->base, state); + state = hash_int(type, value->v_hash->chunksize, state); + state = hash_int(type, value->v_hash->unionsize, state); (state->update)(state, value->v_hash->h_union.data, state->unionsize); state->bytes = FALSE; /* as if reading words */ diff --git a/help/Makefile b/help/Makefile index 6d5bd86..e0a91af 100644 --- a/help/Makefile +++ b/help/Makefile @@ -67,7 +67,7 @@ BLT_HELP_FILES_9= stdlib STD_HELP_FILES_10= types usage unexpected variable -BLT_HELP_FILES_11= altbind bindings custom_cal libcalc new_custom stdlib +BLT_HELP_FILES_11= bindings custom_cal libcalc new_custom stdlib STD_HELP_FILES_12= archive @@ -175,18 +175,6 @@ bindings: ../lib/bindings true; \ fi -altbind: ../lib/altbind - rm -f $@ - cp ../lib/altbind $@ - chmod 0444 $@ - -@if [ -z "${Q}" ]; then \ - echo ''; \ - echo '=-=-= skipping the cat of help/$@ =-=-='; \ - echo ''; \ - else \ - true; \ - fi - stdlib: ../lib/README rm -f $@ cp ../lib/README $@ diff --git a/help/base b/help/base index 685eeaa..88166ab 100644 --- a/help/base +++ b/help/base @@ -18,19 +18,46 @@ DESCRIPTION The following convention is used to declare modes: - base config - value string + base equivalent + config("mode")'s - 2 "binary" binary fractions - 8 "octal" octal fractions - 10 "real" decimal floating point - 16 "hex" hexadecimal fractions - -10 "int" decimal integer - 1/3 "frac" decimal fractions - 1e20 "exp" decimal exponential + 2 "binary" base 2 fractions + "bin" - For convenience, any non-integer value is assumed to mean "frac", - and any integer >= 2^64 is assumed to mean "exp". + 8 "octal" base 8 fractions + "oct" + + 10 "real" base 10 floating point + "float" + "default" + + -10 "integer" base 10 integers + "int" + + 16 "hexadecimal" base 16 fractions + "hex" + + 1/3 "fraction" base 10 fractions + "frac" + + 1e20 "scientific" base 10 scientific notation + "sci" + "exp" + + For convenience, any non-integer value is assumed to mean base 10 + fractions and any integer >= 2^64 is assumed to mean base 10 + scientific notation. + + These base() calls have the same meaning as config("mode", "fraction"): + + base(1/3) base(0.1415) base(16/37) + + These base() calls have the same meaning as config("mode", "scientific"): + + base(1e20) base(2^64) base(2^8191-1) + + However the base() function will only return one of the base values + lised in the table above. EXAMPLE > base() diff --git a/help/config b/help/config index e08f3a6..99787a6 100644 --- a/help/config +++ b/help/config @@ -44,7 +44,7 @@ Configuration parameters "lib_debug" controls library script debug information "user_debug" for user defined debug information "verbose_quit" TRUE=>print message on empty quit or abort - + "ctrl_d" The interactive meaning of ^D (Control D) The "all" config value allows one to save/restore the configuration set of values. The return of: @@ -82,6 +82,43 @@ Configuration parameters startup files; newstd may also be established by invoking calc with the flag -n. + The following are synonyms for true: + + "on" + "true" + "t" + "yes" + "y" + "set" + "1" + any non-zero number + + The following are synonyms for false: + + "off" + "false" + "f" + "no" + "n" + "unset" + "0" + the number zero (0) + + Examples of setting some parameters are: + + config("mode", "exp"); exponential output + config("display", 50); 50 digits of output + epsilon(epsilon() / 8); 3 bits more accuracy + config("tilde", 0) disable roundoff tilde printing + config("tab", "off") disable leading tab printing + + +Detailed config descriptions + + =-= + + config("trace", bitflag) + When nonzero, the "trace" parameter activates one or more features that may be useful for debugging. These features correspond to powers of 2 which contribute additively to config("trace"): @@ -101,6 +138,10 @@ Configuration parameters See also lib_debug, calc_debug and user_debug below for more debug levels. + =-= + + config("display", int) + The "display" parameter specifies the maximum number of digits after the decimal point to be printed in real or exponential mode in normal unformatted printing (print, strprint, fprint) or in @@ -112,6 +153,11 @@ Configuration parameters display up to d decimal places, the type of rounding to be used is controlled by config("outround"). + =-= + + config("epsilon", real) + epsilon(real) + The "epsilon" parameter specifies the default accuracy for the calculation of functions for which exact values are not possible or not desired. For most functions, the @@ -130,22 +176,58 @@ Configuration parameters For the transcendental functions and the functions sqrt() and appr(), the calculated value is always a multiple of epsilon. + =-= + + config("mode", "mode_string") + The "mode" parameter is a string specifying the mode for printing of numbers by the unformatted print functions, and the default ("%d" specifier) for formatted print functions. The initial mode is "real". The available modes are: - "frac" decimal fractions - "int" decimal integer - "real" decimal floating point - "exp" decimal exponential - "hex" hex fractions - "oct" octal fractions - "bin" binary fractions + config("mode") meaning equivalent + string base() call + + "binary" base 2 fractions base(2) + "bin" + + "octal" base 8 fractions base(8) + "oct" + + "real" base 10 floating point base(10) + "float" + "default" + + "integer" base 10 integer base(-10) + "int" + + "hexadecimal" base 16 fractions base(16) + "hex" + + "fraction" base 10 fractions base(1/3) + "frac" + + "scientific" base 10 scientific notation base(1e20) + "sci" + "exp" + + Where multiple strings are given, the first string listed is what + config("mode") will return. + + The default "mode" is "real". + + =-= + + config("maxprint", int) The "maxprint" parameter specifies the maximum number of elements to be displayed when a matrix or list is printed. The initial value is 16. + =-= + + config("mul2", int) + config("sq2", int) + Mul2 and sq2 specify the sizes of numbers at which calc switches from its first to its second algorithm for multiplying and squaring. The first algorithm is the usual method of cross multiplying, which @@ -163,6 +245,10 @@ Configuration parameters the parameter back to its default value. Usually there is no need to change these parameters. + =-= + + config("pow2", int) + Pow2 specifies the sizes of numbers at which calc switches from its first to its second algorithm for calculating powers modulo another number. The first algorithm for calculating modular powers @@ -171,6 +257,10 @@ Configuration parameters which avoids divisions. The argument for pow2 is the size of the modulus at which the second algorithm begins to be used. + =-= + + config("redc2", int) + Redc2 specifies the sizes of numbers at which calc switches from its first to its second algorithm when using the REDC algorithm. The first algorithm performs a multiply and a modular reduction @@ -179,16 +269,36 @@ Configuration parameters O(N^1.585). The argument for redc2 is the size of the modulus at which the second algorithm begins to be used. + =-= + + config("tilde", boolean) + Config("tilde") controls whether or not a leading tilde ('~') is printed to indicate that a number has not been printed exactly because the number of decimal digits required would exceed the specified maximum number. The initial "tilde" value is 1. + =-= + + config("tab", boolean) + Config ("tab") controls the printing of a tab before results automatically displayed when working interactively. It does not affect the printing by the functions print, printf, etc. The initial "tab" value is 1. + =-= + + config("quomod", bitflag) + config("quo", bitflag) + config("mod", bitflag) + config("sqrt", bitflag) + config("appr", bitflag) + config("cfappr", bitflag) + config("cfsim", bitflag) + config("outround", bitflag) + config("round", bitflag) + The "quomod", "quo", "mod", "sqrt", "appr", "cfappr", "cfsim", and "round" control the way in which any necessary rounding occurs. Rounding occurs when for some reason, a calculated or displayed @@ -234,11 +344,19 @@ Configuration parameters by the various kinds of printing to the output: bits 0, 1, 3 and 4 are used in the same way as for the functions round and bround. + =-= + + config("leadzero", bool) + The "leadzero" parameter controls whether or not a 0 is printed before the decimal point in non-zero fractions with absolute value less than 1, e.g. whether 1/2 is printed as 0.5 or .5. The initial value is 0, corresponding to the printing .5. + =-= + + config("fullzero", bool) + The "fullzero" parameter controls whether or not in decimal floating- point printing, the digits are padded with zeros to reach the number of digits specified by config("display") or by a precision @@ -246,10 +364,18 @@ Configuration parameters parameter is 0, so that, for example, if config("display") >= 2, 5/4 will print in "real" mode as 1.25. + =-= + + config("maxscan", int) + The maxscan value controls how many scan errors are allowed before the compiling phase of a computation is aborted. The initial value of "maxscan" is 20. Setting maxscan to 0 disables this feature. + =-= + + config("prompt", str) + The default prompt when in interactive mode is "> ". One may change this prompt to a more cut-and-paste friendly prompt by: @@ -259,17 +385,29 @@ Configuration parameters cut/copy an input line and paste it directly into input. The leading ';' will be ignored. + =-= + + config("more", str) + When inside multi-line input, the more prompt is used. One may change it by: config("more", ";; ") + =-= + + config("blkmaxprint", int) + The "blkmaxprint" config value limits the number of octets to print for a block. A "blkmaxprint" of 0 means to print all octets of a block, regardless of size. The default is to print only the first 256 octets. + =-= + + config("blkverbose", bool) + The "blkverbose" determines if all lines, including duplicates should be printed. If TRUE, then all lines are printed. If false, duplicate lines are skipped and only a "*" is printed in a style @@ -278,11 +416,16 @@ Configuration parameters The default value for "blkverbose" is FALSE: duplicate lines are not printed. + =-= + + config("blkbase", "blkbase_string") + The "blkbase" determines the base in which octets of a block are printed. Possible values are: "hexadecimal" Octets printed in 2 digit hex "hex" + "default" "octal" Octets printed in 3 digit octal "oct" @@ -296,26 +439,41 @@ Configuration parameters "raw" Octets printed as is, i.e. raw binary "none" - The default "blkbase" is "hex". + Where multiple strings are given, the first string listed is what + config("blkbase") will return. + + The default "blkbase" is "hexadecimal". + + =-= + + config("blkfmt", "blkfmt_string") The "blkfmt" determines for format of how block are printed: - "line" print in lines of up to 79 chars + newline - "lines" + "lines" print in lines of up to 79 chars + newline + "line" - "str" print as one long string + "strings" print as one long string "string" - "strings" + "str" - "od" print in od-like format, with leading offset, + "od_style" print in od-like format, with leading offset, "odstyle" followed by octets in the given base - "od_style" + "od" - "hd" print in hex dump format, with leading offset, + "hd_style" print in hex dump format, with leading offset, "hdstyle" followed by octets in the given base, followed - "hd_style" by chars or '.' if no-printable or blank + "hd" by chars or '.' if no-printable or blank + "default" - The default "blkfmt" is "hd". + Where multiple strings are given, the first string listed is what + config("blkfmt") will return. + + The default "blkfmt" is "hd_style". + + =-= + + config("calc_debug", bitflag) The "calc_debug" is intended for controlling internal calc routines that test its operation, or collect or display information that @@ -352,6 +510,10 @@ Configuration parameters By default, "calc_debug" is 0. The initial value may be overridden by the -D command line option. + =-= + + config("lib_debug", bitflag) + The "lib_debug" parameter is intended for controlling the possible display of special information relating to functions, objects, and other structures created by instructions in calc scripts. @@ -369,6 +531,9 @@ Configuration parameters the reading of a file, a message saying what has been done is displayed. + 2 Show func will display more information about a functions + arguments as well as more argument sdummary information. + The value for config("lib_debug") in both oldstd and newstd is 3, but if calc is invoked with the -d flag, its initial value is zero. Thus, if calc is started without the -d flag, until config("lib_debug") @@ -378,6 +543,10 @@ Configuration parameters By default, "lib_debug" is 3. The -d flag changes this default to 0. The initial value may be overridden by the -D command line option. + =-= + + config("user_debug", int) + The "user_debug" is provided for use by users. Calc ignores this value other than to set it to 0 by default (for both "oldstd" and "newstd"). No calc code or shipped library should change this value. Users @@ -391,26 +560,44 @@ Configuration parameters By default, "user_debug" is 0. The initial value may be overridden by the -D command line option. + =-= + + config("verbose_quit", bool) + The "verbose_quit" controls the print of the message: Quit or abort executed - when a non-interactive quit or abort without an argument is encounted. + when a non-interactive quit or abort without an argument is encountered. A quit of abort without an argument does not display a message when invoked at the interactive level. - The following are synonyms for true: + =-= - "on" "yes" "y" "true" "t" "1" any non-zero number + config("ctrl_d", "ctrl_d_string") - The following are synonyms for false: + The "ctrl_d" controls the interactive meaning of ^D (Control D): - "off" "no" "n" "false" "f" "0" the number zero (0) + "virgin_eof" If ^D is the only character that has been typed + "virgineof" on a line, then calc will exit. Otherwise ^D + "virgin" will act according to the calc binding, which + "default" by default is a Emacs-style delete-char. - Examples of setting some parameters are: + "never_eof" The ^D never exits calc and only acts according + "nevereof" calc binding, which by default is a Emacs-style + "never" delete-char. - config("mode", "exp"); exponential output - config("display", 50); 50 digits of output - epsilon(epsilon() / 8); 3 bits more accuracy - config("tilde", 0) disable roundoff tilde printing - config("tab", "off") disable leading tab printing + "empty_eof" The ^D always exits calc if typed on an empty line. + "emptyeof" This condition occurs when ^D either the first + "empty" character typed, or when all other characters on + the line have been removed (say by deleting them). + + Where multiple strings are given, the first string listed is what + config("ctrl_d") will return. + + Note that config("ctrl_d") actually controls each and every character + that is bound to ``delete_char''. By default, ``delete_char'' is + Control D. Any character(s) bound to ``delete_char'' will cause calc + to exit (or not exit) as directed by config("ctrl_d"). + + The default "ctrl_d" is "virgin_eof". diff --git a/help/environment b/help/environment index c60369e..a04ba99 100644 --- a/help/environment +++ b/help/environment @@ -48,8 +48,6 @@ Environment variables Typically compiled in value is: bindings - or: - altbind (bindings where ^D means exit) The bindings file is searched along the CALCPATH. Unlike the READ command, a .cal extension is not added. diff --git a/help/help b/help/help index a304202..03318e3 100644 --- a/help/help +++ b/help/help @@ -30,7 +30,6 @@ following topics: usage how to invoke the calc command variable variables and variable declarations - altbind alternative input & history character bindings bindings input & history character bindings custom_cal information about custom calc library files libcalc using the arbitrary precision routines in a C program diff --git a/help/todo b/help/todo index 4efd6dd..742523b 100644 --- a/help/todo +++ b/help/todo @@ -39,7 +39,6 @@ Very High priority items: overview overview of calc assoc using associations command top level commands - config configuration parameters define how to define functions environment how environment variables effect calc errorcodes calc generated error codes diff --git a/hist.c b/hist.c index 83bc797..7be259a 100644 --- a/hist.c +++ b/hist.c @@ -76,6 +76,7 @@ static struct { int linelen; int histcount; int curhist; + BOOL virgin_line; /* 1 => never typed chars, 0 => chars typed */ } HS; @@ -250,9 +251,15 @@ static void insert_string(char *str, int len); int hist_getline(char *prompt, char *buf, int len) { + /* + * initialize if we have not already done so + */ if (!inited) (void) hist_init(calcbindings); + /* + * establish the beginning of a line condition + */ HS.prompt = prompt; HS.bufsize = len - 2; HS.buf = buf; @@ -260,19 +267,38 @@ hist_getline(char *prompt, char *buf, int len) HS.end = buf; HS.mark = NULL; HS.linelen = -1; + HS.virgin_line = TRUE; + /* + * prep the I/O + */ fputs(prompt, stdout); fflush(stdout); + /* + * special case: non-interactive editing + */ if (!canedit) { if (fgets(buf, len, stdin) == NULL) return 0; return strlen(buf); } - while (HS.linelen < 0) + /* + * get the line + */ + while (HS.linelen < 0) { + + /* get the next char */ read_key(); + /* chars typed, no longer virgin */ + HS.virgin_line = FALSE; + } + + /* + * return the line + */ return HS.linelen; } @@ -292,12 +318,18 @@ hist_init(char *filename) { TTYSTRUCT newtty; + /* + * prevent multiple initializations + */ if (inited) { if (conf->calc_debug & CALCDBG_TTY) printf("DEBUG: inited already set in hist_init\n"); return HIST_INITED; } + /* + * setup + */ inited = 1; canedit = 0; if (conf->calc_debug & CALCDBG_TTY) @@ -984,6 +1016,21 @@ forward_kill_char(void) static void delete_char(void) { + /* + * quit delete_char (usually ^D) is at start of line and we are allowed + * + * We exit of start of line and config("ctrl_d", "empty") or + * if config("ctrl_d", "virgin") and we have never typed on the line. + */ + if ((HS.end == HS.buf) && + (conf->ctrl_d == CTRL_D_EOF || + (conf->ctrl_d == CTRL_D_VIRGIN && HS.virgin_line == TRUE))) { + quit_calc(); + } + + /* + * normal case: just forward_kill_char + */ if (HS.end > HS.buf) forward_kill_char(); } diff --git a/lib/Makefile b/lib/Makefile index 577f02c..22599bc 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -39,7 +39,7 @@ CALC_FILES= README bigprime.cal deg.cal ellip.cal lucas.cal lucas_chk.cal \ lucas_tbl.cal mersenne.cal mod.cal pell.cal pi.cal pix.cal \ pollard.cal poly.cal psqrt.cal quat.cal regress.cal solve.cal \ sumsq.cal surd.cal unitfrac.cal varargs.cal chrem.cal mfactor.cal \ - bindings altbind randmprime.cal test1700.cal randrun.cal \ + bindings randmprime.cal test1700.cal randrun.cal \ randbitrun.cal bernoulli.cal test2300.cal test2600.cal \ test2700.cal test3100.cal test3300.cal test3400.cal prompt.cal \ test3500.cal seedrandom.cal test4000.cal test4100.cal test4600.cal \ diff --git a/lib/altbind b/lib/altbind deleted file mode 100644 index e634a8f..0000000 --- a/lib/altbind +++ /dev/null @@ -1,49 +0,0 @@ -# Alternate key bindings for calc line editing functions -# -# NOTE: This facility is ignored if calc was compiled with GNU-readline. -# In that case, the standard readline mechanisms (see readline(3)) -# are used in place of those found below. - -map base-map -default insert-char -^@ set-mark -^A start-of-line -^B backward-char -^D quit -^E end-of-line -^F forward-char -^H backward-kill-char -^J new-line -^K kill-line -^L refresh-line -^M new-line -^N forward-history -^O save-line -^P backward-history -^R reverse-search -^T swap-chars -^U flush-input -^V quote-char -^W kill-region -^Y yank -^? delete-char -^[ ignore-char esc-map - -map esc-map -default ignore-char base-map -G start-of-line -H backward-history -P forward-history -K backward-char -M forward-char -O end-of-line -S delete-char -g goto-line -s backward-word -t forward-word -d forward-kill-word -u uppercase-word -l lowercase-word -h list-history -^[ flush-input -[ arrow-key diff --git a/lib/regress.cal b/lib/regress.cal index 0cf144e..70262a1 100644 --- a/lib/regress.cal +++ b/lib/regress.cal @@ -385,10 +385,10 @@ define test_config() '516: config("pow2") == 40'); vrfy(config("redc2") == 50, '517: config("redc2") == 50'); - vrfy(config("tilde") == 1, - '518: config("tilde") == 1'); - vrfy(config("tab") == 1, - '519: config("tab") == 1'); + vrfy(config("tilde") == "on", + '518: config("tilde") == "on"'); + vrfy(config("tab") == "on", + '519: config("tab") == "on"'); vrfy(config("quomod") == 0, '520: config("quomod") == 0'); vrfy(config("quo") == 2, @@ -407,10 +407,10 @@ define test_config() '527: config("outround") == 2'); vrfy(config("round") == 24, '528: config("round") == 24'); - vrfy(config("leadzero") == 0, - '529: config("leadzero") == 0'); - vrfy(config("fullzero") == 0, - '530: config("fullzero") == 0'); + vrfy(config("leadzero") == "off", + '529: config("leadzero") == "off"'); + vrfy(config("fullzero") == "off", + '530: config("fullzero") == "off"'); vrfy(config("maxscan") == 20, '531: config("maxscan") == 20'); vrfy(config("prompt") == "> ", @@ -426,10 +426,10 @@ define test_config() vrfy(config("quo", 0) == 2, '536: config("quo", 0) == 2'); vrfy(config("outround", 24) == 2, '537: config("outround", 24) == 2'); - vrfy(config("leadzero", "y") == 0, - '538: config("leadzero", "y") == 0'); - vrfy(config("fullzero", 1) == 0, - '539: config("fullzero", 1) == 0'); + vrfy(config("leadzero","y") == "off", + '538: config("leadzero","y") == "off"'); + vrfy(config("fullzero", 1) == "off", + '539: config("fullzero", 1) == "off"'); vrfy(config("prompt", "; ") == "> ", '540: config("prompt", "; ") == "> "'); vrfy(config("more", ";; ") == ">> ", @@ -441,14 +441,14 @@ define test_config() '543: config("all",callcfg) == newcfg'); vrfy(config("display",2) == 20, '544: config("display",2) == 20'); - vrfy(config("fullzero",1) == 0, - '545: config("fullzero",1) == 0'); + vrfy(config("fullzero",1) == "off", + '545: config("fullzero",1) == "off"'); vrfy(strprintf("%d %d %d", 0, 1, 2) == ".00 1.00 2.00", '546: strprintf("%d %d %d", 0, 1, 2) == ".00 1.00 2.00"'); vrfy(config("display",20) == 2, '547: config("display",20) == 2'); - vrfy(config("fullzero",0) == 1, - '548: config("fullzero",0) == 1'); + vrfy(config("fullzero",0) == "on", + '548: config("fullzero",0) == "on"'); vrfy(strprintf("%d %d %d", 0, 1, 2) == "0 1 2", '549: strprintf("%d %d %d", 0, 1, 2) == "0 1 2"'); @@ -1582,12 +1582,12 @@ define test_mode() tmp = config("mode", "int"); print '1604: tmp = config("mode", "int")'; - vrfy(tmp == "frac", '1605: tmp == "frac"'); + vrfy(tmp == "fraction", '1605: tmp == "fraction"'); vrfy(base() == -10, '1606: base() == -10'); tmp = config("mode", "real"); print '1607: tmp = config("mode", "real")'; - vrfy(tmp == "int", '1608: tmp == "int"'); + vrfy(tmp == "integer", '1608: tmp == "integer"'); vrfy(base() == 10, '1609: base() == 10'); tmp = config("mode", "exp"); @@ -1597,7 +1597,7 @@ define test_mode() tmp = config("mode", "hex"); print '1613: tmp = config("mode", "hex")'; - vrfy(tmp == "exp", '1614: tmp == "exp"'); + vrfy(tmp == "scientific", '1614: tmp == "scientific"'); vrfy(base() == 16, '1615: base() == 16'); tmp = config("mode", "oct"); @@ -1616,11 +1616,13 @@ define test_mode() tmp = base(1/3); print '1624: tmp = base(1/3)'; - vrfy(config("mode") == "frac", '1625: config("mode") == "frac"'); + vrfy(config("mode") == "fraction", + '1625: config("mode") == "fraction"'); tmp = base(-10); print '1626: tmp = base(-10)'; - vrfy(config("mode") == "int", '1627: config("mode") == "int"'); + vrfy(config("mode") == "integer", + '1627: config("mode") == "integer"'); tmp = base(10); print '1628: tmp = base(10)'; @@ -1628,7 +1630,8 @@ define test_mode() tmp = base(1e20); print '1630: tmp = base(1e20)'; - vrfy(config("mode") == "exp", '1631: config("mode") == "exp"'); + vrfy(config("mode") == "scientific", + '1631: config("mode") == "scientific"'); tmp = base(16); print '1632: tmp = base(16)'; @@ -2705,11 +2708,11 @@ define test_matobj() B[0,0] = res(2); print '3106: B[0,0] = res(2)'; B[0,1] = res(3); - print '3107: B[0,1] = res(2)'; + print '3107: B[0,1] = res(3)'; B[1,0] = res(5); - print '3108: B[1,0] = res(2)'; + print '3108: B[1,0] = res(5)'; B[1,1] = res(7); - print '3109: B[1,1] = res(2)'; + print '3109: B[1,1] = res(7)'; print '3110: md = 0'; md = 0; vrfy(det(B) == res(-1), '3111: det(B) == res(-1)'); diff --git a/nametype.h b/nametype.h index 645c2dd..5137f81 100644 --- a/nametype.h +++ b/nametype.h @@ -44,7 +44,7 @@ */ typedef struct { char *name; /* name of configuration string */ - int type; /* type for configuration */ + long type; /* type for configuration */ } NAMETYPE; diff --git a/quickhash.c b/quickhash.c index 9526c6d..04f8584 100644 --- a/quickhash.c +++ b/quickhash.c @@ -410,6 +410,7 @@ config_hash(CONFIG *cfg, QCKHASH val) value = (((value>>5) | (value<<27)) ^ (USB32)cfg->lib_debug); value = (((value>>5) | (value<<27)) ^ (USB32)cfg->user_debug); value = (((value>>5) | (value<<27)) ^ (USB32)cfg->verbose_quit); + value = (((value>>5) | (value<<27)) ^ (USB32)cfg->ctrl_d); /* * hash the built up scalar diff --git a/string.c b/string.c index 97433cc..b279d26 100644 --- a/string.c +++ b/string.c @@ -1086,9 +1086,8 @@ makenewstring(char *str) s = stralloc(); s->s_str = c; s->s_len = len; - while (len-- > 0) - *c++ = *str++; - *c = '\0'; + memcpy(c, str, len); + c[len] = '\0'; return s; } @@ -1097,7 +1096,7 @@ STRING * stringcopy (STRING *s1) { STRING *s; - char *c, *c1; + char *c; long len; len = s1->s_len; @@ -1111,10 +1110,8 @@ stringcopy (STRING *s1) s = stralloc(); s->s_len = len; s->s_str = c; - c1 = s1->s_str; - while (len-- > 0) - *c++ = *c1++; - *c = '\0'; + memcpy(c, s1->s_str, len); + c[len] = '\0'; return s; } diff --git a/value.c b/value.c index 0a06701..f954c8d 100644 --- a/value.c +++ b/value.c @@ -2827,7 +2827,8 @@ config_print(CONFIG *cfg) for (cp = configs; cp->name; cp++) { /* skip if special all or duplicate maxerr value */ - if (cp->type == CONFIG_ALL || strcmp(cp->name, "maxerr") == 0) + if (cp->type == CONFIG_ALL || strcmp(cp->name, "maxerr") == 0 || + strcmp(cp->name, "ctrl-d") == 0) continue; /* print tab if allowed */ diff --git a/version.c b/version.c index d0ff249..f09910b 100644 --- a/version.c +++ b/version.c @@ -18,7 +18,7 @@ static char *program; #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 "10.3.1" /* test number or empty string if no patch */ +#define MINOR_PATCH "10.4" /* test number or empty string if no patch */ /* * calc version constants diff --git a/zmath.c b/zmath.c index 3e2a35b..036b349 100644 --- a/zmath.c +++ b/zmath.c @@ -436,12 +436,10 @@ zsub(ZVALUE z1, ZVALUE z2, ZVALUE *res) len1 = z1.len; len2 = z2.len; if (len1 == len2) { - h1 = z1.v + len1 - 1; - h2 = z2.v + len2 - 1; - while ((len1 > 0) && ((FULL)*h1 == (FULL)*h2)) { + h1 = z1.v + len1; + h2 = z2.v + len2; + while ((len1 > 0) && ((FULL)*--h1 == (FULL)*--h2)) { len1--; - h1--; - h2--; } if (len1 == 0) { *res = _zero_; @@ -633,10 +631,12 @@ zdiv(ZVALUE z1, ZVALUE z2, ZVALUE *quo, ZVALUE *rem, long rnd) A[m + 1] = 0; len = m - n + 1; /* quotient length will be len or len +/- 1 */ a1 = A + n; /* start of digits for quotient */ - b0 = B - 1; + b0 = B; p = n; - while (!*++b0) /* b0: working start for divisor */ - p--; + while (!*b0) { /* b0: working start for divisor */ + ++b0; + --p; + } if (p == 1) { u = *b0; if (u == 1) { @@ -893,10 +893,12 @@ zequo(ZVALUE z1, ZVALUE z2, ZVALUE *res) math_error("Bad call to zequo"); /*NOTREACHED*/ } - B = z2.v - 1; + B = z2.v; o = 0; - while (!*++B) - o++; + while (!*B) { + ++B; + ++o; + } m = z1.len - o; n = z2.len - o; len = m - n + 1; /* Maximum length of quotient */ @@ -1047,12 +1049,12 @@ zdivi(ZVALUE z, long n, ZVALUE *res) dest.sign = z.sign; dest.len = len; dest.v = alloc(len); - h1 = z.v + len - 1; - sd = dest.v + len - 1; + h1 = z.v + len; + sd = dest.v + len; val = 0; while (len--) { - val = ((val << BASEB) + ((FULL) *h1--)); - *sd-- = (HALF)(val / n); + val = ((val << BASEB) + ((FULL) *--h1)); + *--sd = (HALF)(val / n); val %= n; } zquicktrim(dest); @@ -1111,10 +1113,10 @@ zmodi(ZVALUE z, long n) * The modulus is by a small number, so we can do this quickly. */ len = z.len; - h1 = z.v + len - 1; + h1 = z.v + len; val = 0; - while (len--) - val = ((val << BASEB) + ((FULL) *h1--)) % n; + while (len-- > 0) + val = ((val << BASEB) + ((FULL) *--h1)) % n; if (val && z.sign) val = n - val; return (long)val; @@ -1784,13 +1786,12 @@ zshiftr(ZVALUE z, long n) } if (n) { len = z.len; - h = z.v + len - 1; + h = z.v + len; mask = 0; while (len--) { - maskt = (((FULL) *h) << (BASEB - n)) & BASE1; + maskt = (((FULL) *--h) << (BASEB - n)) & BASE1; *h = ((*h >> n) | (HALF)mask); mask = maskt; - --h; } } }