Compare commits

..

5 Commits

Author SHA1 Message Date
Landon Curt Noll
0514dc0de9 Release calc version 2.11.0t10.5.1 2017-05-21 15:38:36 -07:00
Landon Curt Noll
94e35d9b07 Release calc version 2.11.1t0 2017-05-21 15:38:36 -07:00
Landon Curt Noll
867002aa77 Release calc version 2.11.1 2017-05-21 15:38:35 -07:00
Landon Curt Noll
2c9b160dc5 Release calc version 2.11.0t10.4 2017-05-21 15:38:35 -07:00
Landon Curt Noll
fbd3a79eba Release calc version 2.11.0t10.3.1 2017-05-21 15:38:35 -07:00
53 changed files with 1221 additions and 542 deletions

24
BUGS
View File

@@ -100,6 +100,12 @@ Known bugs:
* Use of 'fmt' in the 2nd arg of printf() calls in c_sysinfo.c
cause some compilers to issue warnings.
* The builtin function exp(x) will return 0 when x is a large value
in certain cases such as exp(2^32).
* The builtin function power(x,y) will return 0 in certain cases
such as power(pi(),2^32).
We are sure some more bugs exist. When you find them, please let
us know! See the above for details on how to report and were to
EMail your bug reports and hopefully patches to fix them.
@@ -165,7 +171,17 @@ Problems with known work-a-rounds:
DEBUG= -g
* The sparcv9 support for 64 bit Solaris under gcc-2.96 is able
to compile calc, but calc dumps core very early on in startup.
It is said that sparcv9 support in gcc-2.96 is very unofficial.
There is no work-a-round for this compiler problem.
* There are problems compiling calc on the sparcv9 under 64 bit
Solaris. On that platform, gcc-2.96 is able to compile calc, but
calc dumps core very early on in startup. It is said that sparcv9
support in gcc-2.96 is very unofficial and thus there is no
work-a-round for gcc-2-96.
There is a work-a-round for this architecture us one is using the
Solaris CC on the sparcv9. It has been reported that setting the
following Makefile variables will produce a working version of
calc on the sparcv9 under 64 bit Solaris:
LCC="cc -xarch=v9"
CCWARN="-DFORCE_STDC -w"
DEBUG="-fast -xarch=v9"

104
CHANGES
View File

@@ -19,9 +19,6 @@ The following are the changes from calc version 2.11.0t10 to date:
The 'unused value ignored' messages now start with Line 999: instead
of just 999:.
Fixed some typos in the help files as reported by Klaus Alexander
Seistrup <klaus@seistrup.dk>.
Fixed the long standing issue first reported by Saber-C in the
domul() function in zmil.c thanks to a patch by Ernest Bowen
<ernie@turing.une.edu.au>.
@@ -40,6 +37,107 @@ The following are the changes from calc version 2.11.0t10 to date:
Fixed a number of insure warnings as reported by Michel van der List
<vanderlistmj@sbphrd.com>.
Fixed a number of help file typos discovered by Klaus Alexander
Seistrup <klaus@seistrup.dk>.
Removed REGRESS_CAL as a Makefile variable.
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 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 <ernie@turing.une.edu.au>.
Show func prints function on order of their indices, and with
config("lib_debug") & 4 == 4 some more details about the functions
are displayed.
Fixed another ``dangling name'' bug for when the object types list
exceeded 2000.
Fixed a bug related to opening to a calc session:
define res_add(a,b) = obj res {r} = {a.r + b.r};
...
obj res A = {1,2}. obj res B = {3,4}
A hash of an object takes into account the object type. If X and Y
are different kinds of objects but have the same component values,
they will probably return different rather than the same values for
hash(X) and hash(Y).
Added support for config("ctrl_d") to the GNU-readline interface
as written by Klaus Alexander Seistrup <klaus@seistrup.dk>.
Currently, the config("ctrl_d", "virgin_eof") is not fully
supported. Under GNU-readline, it acts the same way as
config("ctrl_d", "empty_eof"). Emacs users may find this
objectionable as ``hi^A^D^D^D'' will cause calc to exit due to
the issuing of one too many ^D's.
Emacs users may want to put:
config("ctrl_d", "never_eof"),;
into their ~/.calcrc startup files to avoid this problem.
Made misc documentation fixes.
Fixed the make depend rule.
The following are the changes from calc version 2.11.0t8.9.1 to 2.11.0t9.4.5:

View File

@@ -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.

View File

@@ -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:
#
@@ -957,15 +945,6 @@ UTIL_PROGS= align32 fposval have_uid_t longlong have_const \
have_ustat have_getsid have_getpgid \
have_gettime have_getprid ver_calc have_strdup
# These files are required by the regress.cal regression test.
#
REGRESS_CAL= ./lib/lucas_chk.cal ./lib/natnumset.cal ./lib/surd.cal \
./lib/test1700.cal ./lib/test2300.cal ./lib/test2600.cal \
./lib/test2700.cal ./lib/test3100.cal ./lib/test3300.cal \
./lib/test3400.cal ./lib/test3500.cal ./lib/test4000.cal \
./lib/test4100.cal ./lib/test4600.cal ./lib/test5100.cal \
./lib/test5200.cal
# The complete list of makefile vars passed down to custom/Makefile.
#
CUSTOM_PASSDOWN= Q="${Q}" \
@@ -1057,7 +1036,12 @@ C_SRC= ${LIBSRC} ${CALCSRC} ${UTIL_C_SRC}
# These files are found (but not built) in the distribution
#
DISTLIST= ${C_SRC} ${H_SRC} ${MAKE_FILE} BUGS CHANGES LIBRARY README \
calc.man lint.sed HOWTO.INSTALL ${UTIL_MISC_SRC}
calc.man lint.sed HOWTO.INSTALL ${UTIL_MISC_SRC}
# These files are used to make (but not built) a calc .a library
#
CALCLIBLIST= ${LIBSRC} ${UTIL_C_SRC} ${LIB_H_SRC} ${MAKE_FILE} \
${UTIL_MISC_SRC} BUGS CHANGES LIBRARY
# complete list of .o files
#
@@ -1074,7 +1058,7 @@ PROGS= calc ${UTIL_PROGS}
# complete list of targets
#
TARGETS= ${CALC_LIBS} custom/.all calc sample/sample \
lib/.all help/.all help/builtin calc.1
lib/.all help/.all help/builtin calc.1
###
@@ -1098,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
##
#
@@ -1163,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
@@ -2497,14 +2475,15 @@ depend: hsrc
-${Q}rm -rf skel
${Q}mkdir skel
-${Q}for i in ${C_SRC} ${BUILD_C_SRC}; do \
${SED} -n '/^#[ ]*include[ ]*"/p' "$$i" > "skel/$$i"; \
${SED} -n '/^#[ ]*include[ ]*"/p' "$$i" > "skel/$$i"; \
done
${Q}mkdir skel/custom
-${Q}for i in ${H_SRC} ${BUILD_H_SRC} custom.h; do \
tag="`echo $$i | ${SED} 's/[\.+,:]/_/g'`"; \
echo "#ifndef $$tag" > "skel/$$i"; \
echo "#if !defined($$tag)" > "skel/$$i"; \
echo "#define $$tag" >> "skel/$$i"; \
${SED} -n '/^#[ ]*include[ ]*"/p' "$$i" >> "skel/$$i"; \
${SED} -n '/^#[ ]*include[ ]*"/p' "$$i" | \
${SORT} -u >> "skel/$$i"; \
echo '#endif /* '"$$tag"' */' >> "skel/$$i"; \
done
-${Q}rm -f skel/makedep.out
@@ -2515,9 +2494,8 @@ depend: hsrc
${Q}cd skel; \
${MAKEDEPEND} -w 1 -m -f makedep.out ${C_SRC} ${BUILD_C_SRC}
-${Q}for i in ${C_SRC} ${BUILD_C_SRC}; do \
echo "$$i" | \
${SED} 's/^\(.*\)\.c/\1.o: \1.c/' >> skel/makedep.out; \
done
echo "$$i" | ${SED} 's/^\(.*\)\.c/\1.o: \1.c/'; \
done >> skel/makedep.out
${Q}echo dependency list formed
${Q}echo forming new Makefile
-${Q}rm -f Makefile.bak
@@ -2559,17 +2537,29 @@ distlist: ${DISTLIST}
${Q}(for i in ${DISTLIST}; do \
echo $$i; \
done; \
(cd help; ${MAKE} ${HELP_PASSDOWN} distlist); \
(cd lib; ${MAKE} ${LIB_PASSDOWN} distlist); \
(cd custom; ${MAKE} ${CUSTOM_PASSDOWN} distlist); \
(cd sample; ${MAKE} ${SAMPLE_PASSDOWN} distlist)) | ${SORT}
(cd help; ${MAKE} ${HELP_PASSDOWN} $@); \
(cd lib; ${MAKE} ${LIB_PASSDOWN} $@); \
(cd custom; ${MAKE} ${CUSTOM_PASSDOWN} $@); \
(cd sample; ${MAKE} ${SAMPLE_PASSDOWN} $@)) | ${SORT}
distdir:
${Q}(echo .; \
(cd help; ${MAKE} ${HELP_PASSDOWN} distdir); \
(cd lib; ${MAKE} ${LIB_PASSDOWN} distdir); \
(cd custom; ${MAKE} ${CUSTOM_PASSDOWN} distdir); \
(cd sample; ${MAKE} ${SAMPLE_PASSDOWN} distdir)) | ${SORT}
(cd help; ${MAKE} ${HELP_PASSDOWN} $@); \
(cd lib; ${MAKE} ${LIB_PASSDOWN} $@); \
(cd custom; ${MAKE} ${CUSTOM_PASSDOWN} $@); \
(cd sample; ${MAKE} ${SAMPLE_PASSDOWN} $@)) | ${SORT}
calcliblist:
${Q}(for i in ${CALCLIBLIST}; do \
echo $$i; \
done; \
(cd help; ${MAKE} ${HELP_PASSDOWN} $@); \
(cd lib; ${MAKE} ${LIB_PASSDOWN} $@); \
(cd custom; ${MAKE} ${CUSTOM_PASSDOWN} $@); \
(cd sample; ${MAKE} ${SAMPLE_PASSDOWN} $@)) | ${SORT}
calcliblistfmt:
${Q}${MAKE} calcliblist | ${FMT} -64 | ${SED} -e 's/^/ /'
##
#
@@ -2583,10 +2573,10 @@ distdir:
#
##
check: all ./lib/regress.cal ${REGRESS_CAL}
check: all ./lib/regress.cal
${CALC_ENV} ./calc -d -q read regress
chk: ./lib/regress.cal ${REGRESS_CAL}
chk: ./lib/regress.cal
${V} echo '=-=-=-=-= start of $@ rule =-=-=-=-='
${CALC_ENV} ./calc -d -q read regress 2>&1 | ${AWK} -f check.awk
${V} echo '=-=-=-=-= end of $@ rule =-=-=-=-='
@@ -2644,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 ""
@@ -2690,7 +2679,6 @@ env:
@echo "UTIL_TMP=${UTIL_TMP}"; echo ""
@echo "UTIL_PROGS=${UTIL_PROGS}"; echo ""
@echo "LIB_H_SRC=${LIB_H_SRC}"; echo ""
@echo "REGRESS_CAL=${REGRESS_CAL}"; echo ""
@echo "CUSTOM_PASSDOWN=${CUSTOM_PASSDOWN}"; echo ""
@echo "SAMPLE_PASSDOWN=${SAMPLE_PASSDOWN}"; echo ""
@echo "HELP_PASSDOWN=${HELP_PASSDOWN}"; echo ""
@@ -2957,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 =-=-=-=-='
##
@@ -3106,6 +3095,7 @@ calc.o: have_malloc.h
calc.o: have_memmv.h
calc.o: have_newstr.h
calc.o: have_stdlib.h
calc.o: have_strdup.h
calc.o: have_string.h
calc.o: have_uid_t.h
calc.o: have_unistd.h

86
addop.c
View File

@@ -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(',');
@@ -183,7 +209,6 @@ endfunc(void)
free(functions[newindex]);
}
functions[newindex] = fp;
objuncache();
}
@@ -231,7 +256,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 +277,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 +311,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;
}
}
}

208
calc.c
View File

@@ -36,10 +36,17 @@
#include <stdlib.h>
#endif
#include "have_strdup.h"
#if !defined(HAVE_STRDUP)
# define strdup(x) calc_strdup((CONST char *)(x))
#endif /* HAVE_STRDUP */
/*
* static definitions and functions
*/
static void intint(int arg); /* interrupt routine */
static void script_args(int *argc, char ***argv, char **shellfile);
/*
@@ -50,6 +57,7 @@ main(int argc, char **argv)
{
int want_defhelp = 0; /* 1=> we only want the default help */
int cmdlen; /* length of the command string */
char *shellfile = NULL; /* =!NULL ==> name of calc shell script */
extern char *optarg; /* option argument */
extern int optind; /* option index */
int c; /* option */
@@ -60,7 +68,13 @@ main(int argc, char **argv)
* parse args
*/
program = argv[0];
while ((c = getopt(argc, argv, "Cehim:npquvcdD:")) != -1) {
/* catch the case of a leading -s option */
if (argc > 2 && strncmp(argv[1], "-s", 2) == 0) {
/* convert the calc shell options into command line options */
script_args(&argc, &argv, &shellfile);
}
/* process command line options */
while ((c = getopt(argc, argv, "Cehim:npquvcdD:s")) != -1) {
switch (c) {
case 'C':
#if defined(CUSTOM)
@@ -145,6 +159,15 @@ main(int argc, char **argv)
}
}
break;
case 's':
/*
* we are too early in processing to call
* libcalc_call_me_last() - nothing to cleanup
*/
fprintf(stderr,
"%s: -s may only be used in a calc shell script\n",
program);
exit(1);
default:
/*
* we are too early in processing to call
@@ -310,6 +333,8 @@ main(int argc, char **argv)
}
}
/* XXX - if shellfile != NULL process shellfile here */
if (run_state == RUN_PRE_CMD_ARGS) {
if (havecommands) {
if (conf->calc_debug & CALCDBG_RUNSTATE)
@@ -461,3 +486,184 @@ math_error(char *fmt, ...)
exit(3);
}
}
/*
* script_args - concert shell script options into command line form
*
* When a calc shell script is executed, the args are presented to calc
* in a different form. Consider the a calc shell script called /tmp/calcit:
*
* #!/usr/local/bin/calc -s -q -p
* a=eval(prompt("Enter a: "));
* b=eval(prompt("Enter b: "));
* print a+b;
*
* When it is executed as:
*
* /tmp/calcit -D 31
*
* then calc will receive the following as args to main():
*
* argc: 5
* argv[0]: "/usr/local/bin/calc"
* argv[1]: "-s -q -p -e"
* argv[2]: "/tmp/calcit"
* argv[3]: "-D"
* argv[4]: "31"
* argv[5]: NULL
*
* NOTE: The user MUST put -s as the first characters on the calc shell
* script #! line, right after the calc binary path.
*
* NOTE: The arg supplied on the #! calc shell script line are returned
* as a single string. All tabs are converted into spaces.
*
* We must remember the calc script filename, break apart the #! args
* and remove the -s argument. In the above case we would return:
*
* argc: 6
* argv[0]: "/usr/local/bin/calc"
* argv[1]: "-q"
* argv[2]: "-p"
* argv[3]: "-e"
* argv[4]: "-D"
* argv[5]: "31"
* argv[6]: NULL
*
* shellfile: "/tmp/calcit"
*/
static void
script_args(int *argc_p, char ***argv_p, char **shellfile_p)
{
int argc; /* argc to return */
char **argv; /* argv to return */
char *shellfile; /* shell file pathname to return */
int delta; /* the change needed in argc */
int i;
int j;
char *p;
char *q;
/*
* must have at least 3 args and the 2nd must start with -s
*/
argc = *argc_p;
argv = *argv_p;
if (argc < 3 || strncmp(argv[1], "-s", 2) != 0) {
/*
* we are too early in processing to call
* libcalc_call_me_last() - nothing to cleanup
*/
fprintf(stderr,
"%s: FATAL: bad args passed to script_args\n", program);
exit(1);
}
shellfile = argv[2];
/*
* count the additional args beyond the -s
*/
if (argv[1][2] == ' ') {
/*
* process args beyond -s on the #!/usr/local/bin line
*/
p = argv[1]+3 + strspn(argv[1]+3," ");
q = p;
if (q == '\0') {
/* only trailing spaces after -s, ignore them */
for (i = 3; i <= argc; ++i) {
argv[i-2] = argv[i];
}
argc -= 2;
} else {
/* count the space separated strings that follow -s */
for (delta = -1; p != NULL && *p;
p = strchr(p+1,' '), ++delta) {
/* skip multiple spaces in a row */
p += strspn(p, " ");
}
/* allocate the new set of argv pointers */
argv = (char **)malloc(sizeof(char *) * argc+delta);
if (argv == NULL) {
/*
* we are too early in processing to call
* libcalc_call_me_last() - nothing to cleanup
*/
fprintf(stderr,
"%s: failed to malloc %d pointers\n",
program, argc+delta);
exit(1);
}
/* we have the same 0th arg */
argv[0] = (*argv_p)[0];
/* args may be read-only, so duplicate 1st arg */
p = strdup(q);
if (p == NULL) {
/*
* we are too early in processing to call
* libcalc_call_me_last() - nothing to cleanup
*/
fprintf(stderr,
"%s: failed to duplicate 1st arg\n",
program);
exit(1);
}
/* tokenize the 1st arg */
for (p=strtok(q," "), i=1; p != NULL;
p=strtok(NULL," "), ++i) {
argv[i] = p;
}
/* save the 3rd and later args */
for (j=3; (*argv_p)[j] != NULL; ++j, ++i) {
argv[i] = (*argv_p)[j];
}
argv[i] = NULL;
/* set argc */
argc = i;
}
/*
* catch the case of #!/usr/local/bin -stuff_not_extra_args
*/
} else if (argv[1][2] != '\0') {
/*
* we are too early in processing to call
* libcalc_call_me_last() - nothing to cleanup
*/
fprintf(stderr,
"%s: malformed #! line, -s must be "
"followed by space or newline\n",
program);
exit(1);
/*
* Only -s was given in the #!/usr/local/bin line, so we just
* toss the 2nd and 3rd args
*/
} else {
for (i = 3; i <= argc; ++i) {
argv[i-2] = argv[i];
}
argc -= 2;
}
/*
* return and set the argc, argv, shellfile_p values
*/
*argc_p = argc;
*argv_p = argv;
*shellfile_p = shellfile;
return;
}

3
calc.h
View File

@@ -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 */

View File

@@ -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.

319
config.c
View File

@@ -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_EOF /* ^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_EOF /* ^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_EOF},
{"virgineof", CTRL_D_VIRGIN_EOF},
{"virgin", CTRL_D_VIRGIN_EOF},
{"default", CTRL_D_VIRGIN_EOF},
{"never_eof", CTRL_D_NEVER_EOF},
{"nevereof", CTRL_D_NEVER_EOF},
{"never", CTRL_D_NEVER_EOF},
{"empty_eof", CTRL_D_EMPTY_EOF},
{"emptyeof", CTRL_D_EMPTY_EOF},
{"empty", CTRL_D_EMPTY_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;
}

View File

@@ -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_EOF (0) /* ^D only exits on virgin command lines */
#define CTRL_D_NEVER_EOF (1) /* ^D never exits, emacs binding meaning only */
#define CTRL_D_EMPTY_EOF (2) /* ^D always exits at start of line */
/*
* global configuration states and aliases

View File

@@ -285,6 +285,10 @@ H_SRC= ${CUSTOM_H_SRC}
DISTLIST= ${CUSTCALC_SRC} ${CUSTOM_CALC_FILES} ${CUSTOM_HELP} \
${INSTALL_H_SRC} CUSTOM_CAL HOW_TO_ADD ${MAKE_FILE}
# These files are used to make (but not built) a calc .a library
#
CALCLIBLIST= ${CUSTCALC_SRC} ${INSTALL_H_SRC} ${MAKE_FILE} HOW_TO_ADD
# complete list of targets
#
TARGETS= libcustcalc.a ${CUSTCALC_OBJ}
@@ -352,6 +356,13 @@ distlist: ${DISTLIST}
distdir:
${Q}echo custom
calcliblist: ${CALCLIBLIST}
${Q}for i in ${CALCLIBLIST} /dev/null; do \
if [ X"$$i" != X"/dev/null" ]; then \
echo custom/$$i; \
fi; \
done
##
#
# Home grown make dependency rules. Your system make not support
@@ -376,7 +387,7 @@ depend:
${Q}mkdir skel
${Q}mkdir skel/custom
-${Q}for i in ${C_SRC}; do \
${SED} -n '/^#[ ]*include[ ]*"/p' \
${SED} -n '/^#[ ]*include[ ]*"/p' \
"$$i" > "skel/custom/$$i"; \
done
-${Q}for i in /dev/null ${H_SRC}; do \
@@ -384,7 +395,7 @@ depend:
continue; \
fi; \
tag="`echo $$i | ${SED} 's/[\.+,:]/_/g'`"; \
echo "#ifndef $$tag" > "skel/custom/$$i"; \
echo "#if !defined($$tag)" > "skel/custom/$$i"; \
echo "#define $$tag" >> "skel/custom/$$i"; \
${SED} -n '/^#[ ]*include[ ]*"/p' "$$i" \
>> "skel/custom/$$i"; \
@@ -393,7 +404,7 @@ depend:
${Q}(cd ..; ${MAKE} hsrc)
${Q}for i in `cd ..; ${MAKE} h_list`; do \
tag="`echo $$i | ${SED} 's/[\.+,:]/_/g'`"; \
echo "#ifndef $$tag" > "skel/$$i"; \
echo "#if !defined($$tag)" > "skel/$$i"; \
echo "#define $$tag" >> "skel/$$i"; \
${SED} -n '/^#[ ]*include[ ]*"/p' "../$$i" \
>> "skel/$$i"; \
@@ -406,10 +417,8 @@ depend:
skel/custom/makedep.out
${Q}cd skel/custom; ${MAKEDEPEND} -w 1 -m -f makedep.out ${C_SRC}
-${Q}for i in ${C_SRC}; do \
echo "$$i" | \
${SED} 's/^\(.*\)\.c/\1.o: \1.c/' \
>> skel/custom/makedep.out; \
done
echo "$$i" | ${SED} 's/^\(.*\)\.c/\1.o: \1.c/'; \
done >> skel/custom/makedep.out
${Q}echo custom dependency list formed
${Q}echo forming new custom/Makefile
-${Q}rm -f Makefile.bak

20
func.c
View File

@@ -479,7 +479,7 @@ f_nprime(int count, NUMBER **vals)
/* determine the way we report problems */
if (count == 2) {
if (qisfrac(vals[1])) {
math_error("2nd nprime arg must be an integer");
math_error("2nd nextprime arg must be an integer");
/*NOTREACHED*/
}
err = vals[1];
@@ -492,7 +492,7 @@ f_nprime(int count, NUMBER **vals)
if (err) {
return qlink(err);
}
math_error("non-integral arg 1 for builtin function nprime");
math_error("non-integral arg 1 for builtin function nextprime");
/*NOTREACHED*/
}
@@ -507,7 +507,7 @@ f_nprime(int count, NUMBER **vals)
/* error return */
if (!err) {
math_error("nprime arg 1 is >= 2^32");
math_error("nextprime arg 1 is >= 2^32");
/*NOTREACHED*/
}
return qlink(err);
@@ -523,7 +523,7 @@ f_pprime(int count, NUMBER **vals)
/* determine the way we report problems */
if (count == 2) {
if (qisfrac(vals[1])) {
math_error("2nd pprime arg must be an integer");
math_error("2nd prevprime arg must be an integer");
/*NOTREACHED*/
}
err = vals[1];
@@ -536,7 +536,7 @@ f_pprime(int count, NUMBER **vals)
if (err) {
return qlink(err);
}
math_error("non-integral arg 1 for builtin function pprime");
math_error("non-integral arg 1 for builtin function prevprime");
/*NOTREACHED*/
}
@@ -551,10 +551,10 @@ f_pprime(int count, NUMBER **vals)
/* error return */
if (!err) {
if (prev_prime == 0) {
math_error("pprime arg 1 is <= 2");
math_error("prevprime arg 1 is <= 2");
/*NOTREACHED*/
} else {
math_error("pprime arg 1 is >= 2^32");
math_error("prevprime arg 1 is >= 2^32");
/*NOTREACHED*/
}
}
@@ -3589,7 +3589,7 @@ f_matdim(VALUE *vp)
switch(vp->v_type) {
case V_OBJ:
result.v_num = itoq(vp->v_obj->o_actions->count);
result.v_num = itoq(vp->v_obj->o_actions->oa_count);
break;
case V_MAT:
result.v_num = itoq((long) vp->v_mat->m_dim);
@@ -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;

77
hash.c
View File

@@ -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;
@@ -826,10 +837,11 @@ hash_value(int type, void *v, HASH *state)
/* hash the object name and then the element values */
state = hash_str(type, value->v_obj->o_actions->name, state);
state = hash_str(type, objtypename(
value->v_obj->o_actions->oa_index), state);
(state->chkpt)(state);
for (i=value->v_obj->o_actions->count, vp=value->v_obj->o_table;
for (i=value->v_obj->o_actions->oa_count, vp=value->v_obj->o_table;
i-- > 0;
vp++) {
@@ -884,12 +896,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 +915,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 +930,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 +952,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 +980,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 */

View File

@@ -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
@@ -147,6 +147,10 @@ DISTLIST= ${STD_HELP_FILES} ${DETAIL_HELP} ${MAKE_FILE} \
obj.file builtin.top builtin.end funclist.sed \
errorcodes.hdr errorcodes.sed
# These files are used to make (but not built) a calc .a library
#
CALCLIBLIST=
all: ${FULL_HELP_FILES} full ${DETAIL_HELP} ${DETAIL_CLONE} \
${SINGULAR_FILES} calc .all
@@ -171,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 $@
@@ -395,6 +387,13 @@ distlist: ${DISTLIST}
distdir:
${Q}echo help
calcliblist:
${Q}for i in ${CALCLIBLIST} /dev/null; do \
if [ X"$$i" != X"/dev/null" ]; then \
echo help/$$i; \
fi; \
done
# The BSDI cdrom makefile expects all help files to be pre-built. This rule
# creats these fils so that the release can be shipped off to BSDI. You can
# ignore this rule.

View File

@@ -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()

View File

@@ -74,7 +74,7 @@ DESCRIPTION
chunksize is created by C = blk(B, newlen, newchunk), only the first
min(len, newlen) octets being copied from B; later octets are
assigned zero value. If omitted, newlen and newchunk default to
the current datalen and chunk-size for B. The curent datalen,
the current datalen and chunk-size for B. The current datalen,
chunksize and number of allocated octets for B may be changed by:
B = blk(B, newlen, newchunk).

View File

@@ -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,80 @@ 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:
For calc that is using the calc binding (not GNU-readline) facility:
"off" "no" "n" "false" "f" "0" the number zero (0)
The "ctrl_d" controls the interactive meaning of ^D (Control D):
Examples of setting some parameters are:
"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.
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
"never_eof" The ^D never exits calc and only acts according
"nevereof" calc binding, which by default is a Emacs-style
"never" delete-char.
"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").
See the ``binding'' help for information on the default calc bindings.
The default "ctrl_d", without GNU-readline is "virgin_eof".
For calc that was compiled with the GNU-readline facility:
The "ctrl_d" controls the interactive meaning of ^D (Control D):
"virgin_eof" Same as "empty_eof"
"virgineof"
"virgin"
"default"
"never_eof" The ^D never exits calc and only acts according
"nevereof" calc binding, which by default is a Emacs-style
"never" delete-char.
"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
Where multiple strings are given, the first string listed is what
config("ctrl_d") will return.
The default "ctrl_d", with GNU-readline is effectively "empty_eof".
Literally it is "virgin_eof", but since "virgin_eof" is the
same as "empty_eof", the default is effectively "empty_eof".
Emacs users may find the default behavior objectionable, particularly
when using the GNU-readline facility. Such users may want to add the line:
config("ctrl_d", "never_eof"),;
to their ~/.calcrc startup file to prevent ^D from causing calc to exit.

View File

@@ -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.

View File

@@ -31,7 +31,7 @@ EXAMPLE
-1.1312+2.47173i -1.1312043838+2.471726672i
LIMITS
x < 100000
x < 693093
LIBRARY
NUMBER *qexp(NUMBER *x, NUMBER *eps)

View File

@@ -20,7 +20,7 @@ DESCRIPTION
Standard input, standard output and standard error are always opened
and cannot be closed.
The truth value of an closed file is FALSE.
The truth value of a closed file is FALSE.
The fclose function returns the numeric value of errno if
there had been an error using the file, or the null value if

View File

@@ -23,7 +23,7 @@ EXAMPLE
0
LIMITS
fd must be associaed with an open file
fd must be associated with an open file
LIBRARY
none

View File

@@ -10,7 +10,7 @@ TYPES
return nil
DESCRIPTION
This function forces and buffered output to the file associated with fd.
This function forces a buffered output to the file associated with fd.
EXAMPLE
> fd = fopen("/tmp/file", "w")
@@ -18,7 +18,7 @@ EXAMPLE
> fflush(fd)
LIMITS
fd must be associaed with an open file
fd must be associated with an open file
LIBRARY
none

View File

@@ -25,7 +25,7 @@ EXAMPLE
"c"
LIMITS
fd must be associaed with an open file
fd must be associated with an open file
LIBRARY
none

View File

@@ -41,7 +41,7 @@ EXAMPLE
123
LIMITS
fd must be associaed with an open file
fd must be associated with an open file
LIBRARY
none

View File

@@ -14,7 +14,7 @@ DESCRIPTION
the open file associated with fd. Unlike fgetline, the trailing
newline is included in the return string.
If a line is read, is returned, otherwise (EOF or ERROR) nil is returned.
If a line is read, it is returned, otherwise (EOF or ERROR) nil is returned.
EXAMPLE
> fd = fopen("/tmp/newfile", "w")
@@ -30,7 +30,7 @@ EXAMPLE
"chongo was here"
LIMITS
fd must be associaed with an open file
fd must be associated with an open file
LIBRARY
none

View File

@@ -14,7 +14,7 @@ DESCRIPTION
If the stream cannot be read, an error value is returned.
Otherwise the function retrurns the string of characters from the
Otherwise the function returns the string of characters from the
current file position to the first null character ('\0') (the file
position for further reading then being immediately after the '\0'),
or if no null character is encountered, the string of characters to

View File

@@ -10,7 +10,7 @@ TYPES
return files, int or null
DESCRIPTION
This function, then given the argument fnum, will use it as an
This function, when given the argument fnum, will use it as an
index into an internal table of open file and return a file value.
If that entry in the table is not in use, then the null value is
returned instead. When no args are given, the maximum number of

View File

@@ -13,7 +13,7 @@ TYPES
DESCRIPTION
This function opens the file named filename. A file can be
opened for either reading, writing, or appending. The mode
is controlled by the mode flag as folllows:
is controlled by the mode flag as follows:
"r" reading
"w" writing

View File

@@ -11,7 +11,7 @@ TYPES
return null value
DESCRIPTION
In forall(x,y), y is to the the name of a function; that function
In forall(x,y), y is the name of a function; that function
is performed in succession for all elements of x. This is similar
to modify(x, y) but x is not changed.

View File

@@ -22,7 +22,7 @@ EXAMPLE
"c"
LIMITS
fd must be associaed with an open file
fd must be associated with an open file
LIBRARY
none

View File

@@ -1,5 +1,5 @@
NAME
freeglobals - free memory used for values of global variabls
freeglobals - free memory used for values of global variables
SYNOPSIS
freeglobals()

View File

@@ -16,7 +16,7 @@ DESCRIPTION
Otherwise, until the terminating null character of fmt is encountered
or end-of-file for fs is reached, characters other than '%' and white
space are read from fmt and compared with the corresponding chracters
space are read from fmt and compared with the corresponding characters
read from fs. If the characters match, the reading continues. If they
do not match, an integer value is returned and the file position for
fs is the position of the non-matching character. If white space
@@ -72,7 +72,7 @@ DESCRIPTION
might be taken to suggest a number like +2345; 'r' might suggest
a representation like -27/49; 'e' might suggest a representation like
1.24e-7; 'f' might suggest a representation like 27.145. However, there
is no test that the the result conforms to the specifier. Whatever
is no test that the result conforms to the specifier. Whatever
the specifier in these cases, the result depends on the characters read
until a space or other exceptional character is read. The
characters read may include one or more occurrences of +, -, * as

View File

@@ -20,7 +20,7 @@ EXAMPLE
784
LIMITS
fd must be associaed with an open file
fd must be associated with an open file
LIBRARY
none

View File

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

View File

@@ -14,8 +14,8 @@ DESCRIPTION
If n is an integer less than 2^32, nextprime(n) returns the
first prime greater than n.
If n <= 2 or >= 2^32 or n is fractional, prevprime(n, err)
returns the value of err.
If n >= 2^32 or n is fractional, nextprime(n, err) returns the value
of err.
Other cases cause a runtime error.
@@ -27,7 +27,7 @@ EXAMPLE
-99 4294967311 -99
LIMITS
none
n <= 2^32
LIBRARY
FULL znprime(ZVALUE z)

View File

@@ -30,7 +30,7 @@ EXAMPLE
pprime arg 1 is <= 2
LIMITS
none
2 < n < 2^32
LIBRARY
FULL zpprime(ZVALUE z)

View File

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

67
hist.c
View File

@@ -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_EMPTY_EOF ||
(conf->ctrl_d == CTRL_D_VIRGIN_EOF && HS.virgin_line == TRUE))) {
quit_calc();
}
/*
* normal case: just forward_kill_char
*/
if (HS.end > HS.buf)
forward_kill_char();
}
@@ -1429,6 +1476,7 @@ memrcpy(char *dest, char *src, int len)
*dest-- = *src--;
}
#endif /* !USE_READLINE */
static void
quit_calc(void)
@@ -1439,7 +1487,7 @@ quit_calc(void)
exit(0);
}
#else /* USE_READLINE */
#if defined(USE_READLINE)
#define HISTORY_LEN (1024) /* number of entries to save */
@@ -1469,8 +1517,17 @@ hist_getline(char *prompt, char *buf, int len)
buf[0] = '\0';
line = readline(prompt);
if (!line)
return 0;
if (!line) {
switch (conf->ctrl_d) {
case CTRL_D_NEVER_EOF:
return 0;
case CTRL_D_VIRGIN_EOF:
case CTRL_D_EMPTY_EOF:
default:
quit_calc();
/*NOTREACHED*/
}
}
strncpy(buf, line, len - 1);
buf[len - 2] = '\0';
len = strlen(buf);
@@ -1530,7 +1587,7 @@ hist_saveline(char *line, int len)
if (prev != NULL && strcmp(prev, line) == 0)
return;
free (prev);
free(prev);
/* fail silently */
prev = strdup(line);

View File

@@ -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 \
@@ -51,6 +51,10 @@ CALC_FILES= README bigprime.cal deg.cal ellip.cal lucas.cal lucas_chk.cal \
#
DISTLIST= ${CALC_FILES} ${MAKE_FILE}
# These files are used to make (but not built) a calc .a library
#
CALCLIBLIST=
all: ${CALC_FILES} ${MAKE_FILE} .all
# used by the upper level Makefile to determine of we have done all
@@ -80,6 +84,13 @@ distlist: ${DISTLIST}
distdir:
${Q}echo lib
calcliblist:
${Q}for i in ${CALCLIBLIST} /dev/null; do \
if [ X"$$i" != X"/dev/null" ]; then \
echo lib/$$i; \
fi; \
done
clean:
clobber:

View File

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

View File

@@ -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)');

View File

@@ -44,7 +44,7 @@
*/
typedef struct {
char *name; /* name of configuration string */
int type; /* type for configuration */
long type; /* type for configuration */
} NAMETYPE;

75
obj.c
View File

@@ -158,16 +158,16 @@ objcall(int action, VALUE *v1, VALUE *v2, VALUE *v3)
math_error("Object routine called with non-object");
/*NOTREACHED*/
}
index = oap->actions[action];
if (index == 0) {
strcpy(name, oap->name);
index = oap->oa_indices[action];
if (index < 0) {
strcpy(name, namestr(&objectnames, oap->oa_index));
strcat(name, "_");
strcat(name, oip->name);
index = adduserfunc(name);
oap->actions[action] = index;
oap->oa_indices[action] = index;
}
fp = NULL;
if (index > 0)
if (index >= 0)
fp = findfunc(index);
if (fp == NULL) {
switch (oip->error) {
@@ -285,27 +285,6 @@ objcall(int action, VALUE *v1, VALUE *v2, VALUE *v3)
}
/*
* Routine called to clear the cache of known undefined functions for
* the objects. This changes negative indices back into positive ones
* so that they will all be checked for existence again.
*/
void
objuncache(void)
{
register long *ip;
long i, j;
i = objectnames.h_count;
while (--i >= 0) {
ip = objects[i]->actions;
for (j = OBJ_MAXFUNC; j-- >= 0; ip++)
if (*ip < 0)
*ip = -*ip;
}
}
/*
* Print the elements of an object in short and unambiguous format.
* This is the default routine if the user's is not defined.
@@ -319,8 +298,8 @@ objprint(OBJECT *op)
int count; /* number of elements */
int i; /* index */
count = op->o_actions->count;
math_fmt("obj %s {", op->o_actions->name);
count = op->o_actions->oa_count;
math_fmt("obj %s {", namestr(&objectnames, op->o_actions->oa_index));
for (i = 0; i < count; i++) {
if (i)
math_str(", ");
@@ -340,7 +319,7 @@ objtest(OBJECT *op)
{
int i; /* loop counter */
i = op->o_actions->count;
i = op->o_actions->oa_count;
while (--i >= 0) {
if (testvalue(&op->o_table[i]))
return TRUE;
@@ -361,7 +340,7 @@ objcmp(OBJECT *op1, OBJECT *op2)
if (op1->o_actions != op2->o_actions)
return TRUE;
i = op1->o_actions->count;
i = op1->o_actions->oa_count;
while (--i >= 0) {
if (comparevalue(&op1->o_table[i], &op2->o_table[i]))
return TRUE;
@@ -481,11 +460,11 @@ defineobject(char *name, int indices[], int count)
* new definition is exactly the same as the old one.
*/
oap = objects[index];
if (oap->count == count) {
if (oap->oa_count == count) {
for (index = 0; ; index++) {
if (index >= count)
return 0;
if (oap->elements[index] != indices[index])
if (oap->oa_elements[index] != indices[index])
break;
}
}
@@ -510,18 +489,18 @@ defineobject(char *name, int indices[], int count)
}
oap = (OBJECTACTIONS *) malloc(objectactionsize(count));
name = addstr(hp, name);
name = addstr(hp, name);
if ((oap == NULL) || (name == NULL)) {
math_error("Cannot allocate object type");
/*NOTREACHED*/
}
oap->name = name;
oap->count = count;
oap->oa_count = count;
for (index = OBJ_MAXFUNC; index >= 0; index--)
oap->actions[index] = 0;
oap->oa_indices[index] = -1;
for (index = 0; index < count; index++)
oap->elements[index] = indices[index];
oap->oa_elements[index] = indices[index];
index = findstr(hp, name);
oap->oa_index = index;
objects[index] = oap;
return 0;
}
@@ -606,8 +585,8 @@ objoffset(OBJECT *op, long index)
int offset; /* offset into value array */
oap = op->o_actions;
for (offset = oap->count - 1; offset >= 0; offset--) {
if (oap->elements[offset] == index)
for (offset = oap->oa_count - 1; offset >= 0; offset--) {
if (oap->oa_elements[offset] == index)
return offset;
}
return -1;
@@ -634,7 +613,7 @@ objalloc(long index)
math_error("Object type not defined");
/*NOTREACHED*/
}
i = oap->count;
i = oap->oa_count;
if (i < USUAL_ELEMENTS)
i = USUAL_ELEMENTS;
if (i == USUAL_ELEMENTS)
@@ -647,7 +626,7 @@ objalloc(long index)
}
op->o_actions = oap;
vp = op->o_table;
for (i = oap->count; i-- > 0; vp++) {
for (i = oap->oa_count; i-- > 0; vp++) {
vp->v_num = qlink(&_qzero_);
vp->v_type = V_NUM;
vp->v_subtype = V_NOSUBTYPE;
@@ -666,14 +645,14 @@ objfree(OBJECT *op)
int i;
vp = op->o_table;
for (i = op->o_actions->count; i-- > 0; vp++) {
for (i = op->o_actions->oa_count; i-- > 0; vp++) {
if (vp->v_type == V_NUM) {
qfree(vp->v_num);
} else {
freevalue(vp);
}
}
if (op->o_actions->count <= USUAL_ELEMENTS)
if (op->o_actions->oa_count <= USUAL_ELEMENTS)
free(op);
else
free((char *) op);
@@ -690,7 +669,7 @@ objcopy(OBJECT *op)
OBJECT *np;
int i;
i = op->o_actions->count;
i = op->o_actions->oa_count;
if (i < USUAL_ELEMENTS)
i = USUAL_ELEMENTS;
if (i == USUAL_ELEMENTS)
@@ -704,7 +683,7 @@ objcopy(OBJECT *op)
np->o_actions = op->o_actions;
v1 = op->o_table;
v2 = np->o_table;
for (i = op->o_actions->count; i-- > 0; v1++, v2++) {
for (i = op->o_actions->oa_count; i-- > 0; v1++, v2++) {
if (v1->v_type == V_NUM) {
v2->v_num = qlink(v1->v_num);
v2->v_type = V_NUM;
@@ -736,10 +715,10 @@ showobjtypes(void)
}
for (index = 0; index < hp->h_count; index++) {
oap = objects[index];
printf("\t%s\t{", oap->name);
for (i = 0; i < oap->count; i++) {
printf("\t%s\t{", namestr(&objectnames, index));
for (i = 0; i < oap->oa_count; i++) {
if (i) printf(",");
printf("%s", namestr(ep, oap->elements[i]));
printf("%s", namestr(ep, oap->oa_elements[i]));
}
printf("}\n");
}

View File

@@ -398,7 +398,7 @@ o_eleminit(FUNC *fp, long index)
oldvp = &vp->v_mat->m_table[index];
break;
case V_OBJ:
if (index < 0 || index >= vp->v_obj->o_actions->count) {
if (index < 0 || index >= vp->v_obj->o_actions->oa_count) {
math_error("Too many initializer values");
/*NOTREACHED*/
}
@@ -2381,7 +2381,7 @@ o_fiaddr(void)
vp = vp->v_addr;
switch (vp->v_type) {
case V_OBJ:
if (index >= vp->v_obj->o_actions->count) {
if (index >= vp->v_obj->o_actions->oa_count) {
math_error("Index out of bounds for object");
/*NOTREACHED*/
}

View File

@@ -292,7 +292,9 @@ objhash(OBJECT *op, QCKHASH val)
{
int i;
i = op->o_actions->count;
val = fnv(op->o_actions->oa_index, val);
i = op->o_actions->oa_count;
while (--i >= 0)
val = hashvalue(&op->o_table[i], val);
return val;
@@ -410,6 +412,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

View File

@@ -263,6 +263,10 @@ H_SRC= ${SAMPLE_H_SRC}
#
DISTLIST= ${C_SRC} ${H_SRC} ${MAKE_FILE} README_SAMPLE
# These files are used to make (but not built) a calc .a library
#
CALCLIBLIST= ${C_SRC} ${H_SRC} ${MAKE_FILE} README_SAMPLE
# complete list of targets
#
TARGETS= many_random test_random
@@ -327,6 +331,13 @@ distlist: ${DISTLIST}
distdir:
${Q}echo sample
calcliblist:
${Q}for i in ${CALCLIBLIST} /dev/null; do \
if [ X"$$i" != X"/dev/null" ]; then \
echo sample/$$i; \
fi; \
done
##
#
# Home grown make dependency rules. Your system make not support
@@ -351,13 +362,13 @@ depend:
${Q}mkdir skel
${Q}mkdir skel/sample
-${Q}for i in ${C_SRC}; do \
${SED} -n '/^#[ ]*include[ ]*"/p' \
${SED} -n '/^#[ ]*include[ ]*"/p' \
"$$i" > "skel/sample/$$i"; \
done
-${Q}for i in ${H_SRC} /dev/null; do \
if [ X"$$i" != X"/dev/null" ]; then \
tag="`echo $$i | ${SED} 's/[\.+,:]/_/g'`"; \
echo "#ifndef $$tag" > "skel/sample/$$i"; \
echo "#if !defined($$tag)" > "skel/sample/$$i"; \
echo "#define $$tag" >> "skel/sample/$$i"; \
${SED} -n '/^#[ ]*include[ ]*"/p' "$$i" \
>> "skel/sample/$$i"; \
@@ -367,7 +378,7 @@ depend:
${Q}(cd ..; ${MAKE} hsrc)
${Q}for i in `cd ..; ${MAKE} h_list`; do \
tag="`echo $$i | ${SED} 's/[\.+,:]/_/g'`"; \
echo "#ifndef $$tag" > "skel/$$i"; \
echo "#if !defined($$tag)" > "skel/$$i"; \
echo "#define $$tag" >> "skel/$$i"; \
${SED} -n '/^#[ ]*include[ ]*"/p' "../$$i" \
>> "skel/$$i"; \
@@ -380,10 +391,8 @@ depend:
skel/sample/makedep.out
${Q}cd skel/sample; ${MAKEDEPEND} -w 1 -m -f makedep.out -I.. ${C_SRC}
-${Q}for i in ${C_SRC}; do \
echo "$$i" | \
${SED} 's/^\(.*\)\.c/\1.o: \1.c/' \
>> skel/sample/makedep.out; \
done
echo "$$i" | ${SED} 's/^\(.*\)\.c/\1.o: \1.c/'; \
done >> skel/sample/makedep.out
${Q}echo sample dependency list formed
${Q}echo forming new sample/Makefile
-${Q}rm -f Makefile.bak

9
size.c
View File

@@ -68,7 +68,7 @@ elm_count(VALUE *vp)
result = vp->v_assoc->a_count;
break;
case V_OBJ:
result = vp->v_obj->o_actions->count;
result = vp->v_obj->o_actions->oa_count;
break;
case V_STR:
result = vp->v_str->s_len;
@@ -261,7 +261,7 @@ lsizeof(VALUE *vp)
break;
case V_OBJ:
oap = vp->v_obj->o_actions;
i = oap->count;
i = oap->oa_count;
p = vp->v_obj->o_table;
while (i-- > 0)
s += lsizeof(p++);
@@ -381,9 +381,8 @@ memsize(VALUE *vp)
case V_OBJ:
s = sizeof(OBJECT);
oap = vp->v_obj->o_actions;
s += (long)strlen(oap->name) + 1;
i = oap->count;
s += (i + 2) * sizeof(int);
i = oap->oa_count;
s += (i + 3) * sizeof(int);
p = vp->v_obj->o_table;
while (i-- > 0)
s += memsize(p++);

View File

@@ -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;
}

View File

@@ -249,8 +249,8 @@ printtype(VALUE *vp)
s = "association";
break;
case V_OBJ:
printf("%s ",
vp->v_obj->o_actions->name);
printf("%s ", objtypename(
vp->v_obj->o_actions->oa_index));
s = "object";
break;
case V_FILE:

View File

@@ -121,7 +121,7 @@ protectall(VALUE *vp, int sts)
break;
case V_OBJ:
vq = vp->v_obj->o_table;
i = vp->v_obj->o_actions->count;
i = vp->v_obj->o_actions->oa_count;
while (i-- > 0)
protectall(vq++, sts);
break;
@@ -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 */

View File

@@ -416,10 +416,10 @@ extern VALUE *associndex(ASSOC *ap, BOOL create, long dim, VALUE *indices);
* This is actually a varying sized structure.
*/
typedef struct {
char *name; /* name of object */
int count; /* number of elements defined */
long actions[OBJ_MAXFUNC+1]; /* function indices for actions */
int elements[1]; /* element indexes (MUST BE LAST) */
int oa_index; /* index of object type */
int oa_count; /* number of elements defined */
long oa_indices[OBJ_MAXFUNC+1]; /* function indices for actions */
int oa_elements[1]; /* element indices (MUST BE LAST) */
} OBJECTACTIONS;
#define objectactionsize(elements) \
@@ -444,7 +444,6 @@ extern OBJECT *objcopy(OBJECT *op);
extern OBJECT *objalloc(long index);
extern VALUE objcall(int action, VALUE *v1, VALUE *v2, VALUE *v3);
extern void objfree(OBJECT *op);
extern void objuncache(void);
extern int addelement(char *name);
extern int defineobject(char *name, int indices[], int count);
extern int checkobject(char *name);

View File

@@ -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" /* test number or empty string if no patch */
#define MINOR_PATCH "10.5.1" /* test number or empty string if no patch */
/*
* calc version constants

43
zmath.c
View File

@@ -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;
}
}
}