Compare commits

...

7 Commits

Author SHA1 Message Date
Landon Curt Noll
45a4b8469d Release calc version 2.11.0t7.3 2017-05-21 15:38:29 -07:00
Landon Curt Noll
9204d2fb8c Release calc version 2.11.0t7.2 2017-05-21 15:38:28 -07:00
Landon Curt Noll
35982c7cc8 Release calc version 2.11.0t7.1 2017-05-21 15:38:28 -07:00
Landon Curt Noll
4c0f2691e9 Release calc version 2.11.0t7 2017-05-21 15:38:28 -07:00
Landon Curt Noll
0d37ccb019 Release calc version 2.11.0t6.3 2017-05-21 15:38:28 -07:00
Landon Curt Noll
d7d31e9246 Release calc version 2.11.0t6.2 2017-05-21 15:38:28 -07:00
Landon Curt Noll
2dc364ee9f Release calc version 2.11.0t6.1 2017-05-21 15:38:28 -07:00
33 changed files with 1338 additions and 544 deletions

12
BUGS
View File

@@ -77,15 +77,3 @@ Known problems or mis-features:
* There is some places in the source with obscure variable names
and not much in the way of comments. We need some major cleanup
and documentation.
* On a Dec Alpha, using the Dec Alpha cc (not gcc) make check for
version 2.11.0t5.1 fails in the regression test:
From vandermj@molbio.sbphrd.com Tue Oct 5 04:06:52 1999
Subject: Re: oops, try calc version 2.10.0t5.1
Date: Tue, 05 Oct 1999 07:06:30 -0400
Regular cc on Dec alpha, 'make check' dies with:
1804: surd_value(a) == 2+3i
"": line 1706: Calling qfreenum with nozero links!!!

157
CHANGES
View File

@@ -1,4 +1,142 @@
Following is the change from calc version 2.11.0t1 to date:
Following is the change from calc version 2.11.0t7 to date:
Calc has some new command line flags / command line meaning:
(Thanks goes to Ernest Bowen <ernie@turing.une.edu.au>)
-i Go into interactive mode if possible.
-c Continue reading command lines even after an execution
error has caused the abandonment of a line
To understand the -i and -c effects, consider the following
file (call it myfile.cal) which has deliberate errors in it:
print 1;
mat A[1] = {2,3};
print 2;
epsilon(-1);
print 3;
calc read myfile
Reports an error on the 2nd line and exits; prints 1 only.
calc -c read myfile
Report errors on the 2nd and 4th lines and exits; prints 1,2 and 3.
calc -i read myfile
Report errors on the 2nd and gives you a prompt; prints 1 only.
calc -i -c read myfile
Report errors on the 2nd and 4th and gives you a prompt;
prints 1, 2 and 3.
cat myfile | calc
Reports an error on the 2nd line and exits; prints 1 only.
cat myfile | calc -c
Report errors on the 2nd and 4th lines and exits; prints 1,2 and 3.
Note that continuation refers to command lines, not to statements. So:
calc -c 'print "start"; mat A[1] = {2,3}; print "end";'
since it contains no newline, the whole string is compiled,
but execution is abandoned when the error is encountered and
the string ``end'' is not printed.
You can use your shell to supply newlines in your command line
arguments. For example in sh, ksh, bash:
calc -c 'print "start";
mat A[1] = {2,3};
print "end";'
will print both ``start'' and ``end''. C-shell users can do:
calc -c 'print "start"; \
mat A[1] = {2,3}; \
print "end";'
however sh, ksh, bash will not see ``end'' printed because their
shell will remove the internal newlines.
Added display(n) builtin which does almost the same as config("display",n)
except that rather than causing an execution with an out-of-range or
bad-type argument type, it simply writes a message to stderr. This
also now happens to the errmax() builtin.
Added qtime.cal to the standard calc library.
Added another command line flag to calc:
-d Disable display of the opening title and config("lib_debug",0)
The command:
calc 'read qtime; qtime(2)'
will output something like:
qtime(utc_hr_offset) defined
It's nearly ten past six.
whereas:
calc -d 'read qtime; qtime(2)'
will just say:
It's nearly ten past six.
A call of errmax(-1) will prevent errcount from aborting calc.
Add the function stoponerror(n) which, as the name implies, controls
if calc stop on an error based on the value of n:
n > 0 stop on error even if -c was given on the command line
n == 0 if -c, continue, without -c, stop
n < 0 continue on error, even if -c was given on the command line
Calc compilation now stops at the first scanerror.
Restored the feature where -p disables the printing of leading tabs
as of config("tab",0) had been executed. So using calc in a pipe:
calc -p 2+17 | whey
will write '19' instead of '\t17' to the whey command.
Updated calc man page and help/usage file to reflect recent
command line changes.
Converted start_done into a general calc run state enum called
run_state within the calc source.
Removed README.OLD.
Added the Makefile variable ${LCC} to invoke the local c compiler.
By default, ${CC} also run the ${LCC} compiler. The distinction is
useful when using something such as purify. In the case of ${LCC},
only the local C compiler is invoked. In the case of ${CC} a purify
compile is invoked. Only the source that must be compiled and run
on the local machine use ${LCC}; everything else uses ${CC}.
Fixed memory buffer ovreread problem in eatstring() in token.c.
Fixed memory leaks related to putenv().
Fixed memory leaks realted to srandom().
Misc calc man page fixes.
Following is the change from calc version 2.11.0t1 to 2.11.0t6.3:
Removed the makefile symbol MAIN. Now forcing all functions to correctly
be declared main. To satisfy some old broken compilers, a return 0;
@@ -35,8 +173,9 @@ Following is the change from calc version 2.11.0t1 to date:
Reordered cc Makefile variable sets in the main Makefile.
Fixed a bug and applied a fix that was reported by Ernest Bowen
<ernie@turing.une.edu.au>. Added regression tests 1103 to 1112.
Fixed a bug in hnrmod() and applied a fix that was reported by Ernest
Bowen <ernie@turing.une.edu.au>. Added regression tests 1103 to
1112 to confirm the fix.
Fixed a bug in version.c related to MINOR_PATCHs in both the
empty and non-empty MINOR_PATCH cases.
@@ -174,6 +313,18 @@ Following is the change from calc version 2.11.0t1 to date:
to correctly hash a V_STR value-type that has an \0 byte
inside it.
A patch from Ernest Bowen <ernie@turing.une.edu.au> now defines
special meaning to the first 2 bits of config("lib_debug"):
bit 0 set => messages printed when inputisterminal
bit 1 set => messages printed when reading from a file
The lib/regress.cal regression suite does:
config("lib_debug", -4);
to eliminate lib messages (both bit 0 and bit 1 are not set).
Fixed misc compile warnings and notices.

View File

@@ -50,3 +50,6 @@ Installing calc in 4 easy steps:
4) install calc:
make install
We suggest that you might want to read the README file and look at
the calc help subsystem. See the README file for details.

107
Makefile
View File

@@ -352,7 +352,7 @@ CALCPAGER= more
#CALCPAGER= cat
#CALCPAGER= less
# Debug/Optimize options for ${CC}
# Debug/Optimize options for ${CC} and ${LCC}
#
#DEBUG= -O
#DEBUG= -O -g
@@ -393,7 +393,7 @@ NO_SHARED=
#NO_SHARED= -non_shared
# On some systems where you are disabling dynamic shared libs, you may
# need to pass a special flag to ${CC} during linking stage.
# need to pass a special flag to ${CC} and ${LCC} during linking stage.
#
# System type NO_SHARED recommendation
#
@@ -522,7 +522,8 @@ ALLOW_CUSTOM= -DCUSTOM
# LDFLAGS are flags given to ${CC} for linking .o files
# ILDFLAGS are flags given to ${CC} for linking .o files for intermediate progs
#
# CC is how the the C compiler is invoked
# LCC how the the C compiler is invoked on locally executed intermediate progs
# CC is how the the C compiler is invoked (with an optional Purify)
#
###
#
@@ -546,7 +547,8 @@ LCFLAGS=
LDFLAGS= ${NO_SHARED} ${LD_NO_SHARED}
ILDFLAGS=
#
CC= ${PURIFY} gcc
LCC= gcc
CC= ${PURIFY} ${LCC}
#
###
#
@@ -568,8 +570,9 @@ CC= ${PURIFY} gcc
#LDFLAGS= ${NO_SHARED} ${LD_NO_SHARED}
#ILDFLAGS=
#
#CC= ${PURIFY} gcc
#CC= ${PURIFY} gcc2
#LCC= gcc
#LCC= gcc2
#CC= ${PURIFY} ${LCC}
#
###
#
@@ -588,7 +591,8 @@ CC= ${PURIFY} gcc
#LDFLAGS= ${NO_SHARED} ${LD_NO_SHARED}
#ILDFLAGS=
#
#CC= ${PURIFY} cc
#LCC= cc
#CC= ${PURIFY} ${LCC}
#
###
#
@@ -619,7 +623,8 @@ CC= ${PURIFY} gcc
#LDFLAGS= ${NO_SHARED} ${LD_NO_SHARED}
#ILDFLAGS=
#
#CC= ${PURIFY} cc -n32 -xansi
#LCC= cc -n32 -xansi
#CC= ${PURIFY} ${LCC}
#
###
#
@@ -644,7 +649,8 @@ CC= ${PURIFY} gcc
#LDFLAGS= ${NO_SHARED} ${LD_NO_SHARED}
#ILDFLAGS=
#
#CC= ${PURIFY} cc
#LCC= cc
#CC= ${PURIFY} ${LCC}
#
###
#
@@ -663,7 +669,8 @@ CC= ${PURIFY} gcc
#LDFLAGS= ${NO_SHARED} ${LD_NO_SHARED}
#ILDFLAGS=
#
#CC= ${PURIFY} cc
#LCC= cc
#CC= ${PURIFY} ${LCC}
#
###
#
@@ -688,7 +695,8 @@ CC= ${PURIFY} gcc
#LDFLAGS= ${NO_SHARED} ${LD_NO_SHARED}
#ILDFLAGS=
#
#CC= ${PURIFY} cc
#LCC= cc
#CC= ${PURIFY} ${LCC}
#
###
#
@@ -710,7 +718,8 @@ CC= ${PURIFY} gcc
#LDFLAGS= ${NO_SHARED} ${LD_NO_SHARED}
#ILDFLAGS=
#
#CC= ${PURIFY} gcc
#LCC= gcc
#CC= ${PURIFY} ${LCC}
#
###
#
@@ -732,7 +741,8 @@ CC= ${PURIFY} gcc
#LDFLAGS= ${NO_SHARED} ${LD_NO_SHARED}
#ILDFLAGS=
#
#CC= ${PURIFY} cc
#LCC= cc
#CC= ${PURIFY} ${LCC}
##############################################################################
#-=-=-=-=-=-=-=-=- Be careful if you change something below -=-=-=-=-=-=-=-=-#
@@ -887,6 +897,7 @@ CUSTOM_PASSDOWN= Q="${Q}" \
LCFLAGS="${LCFLAGS}" \
LDFLAGS="${LDFLAGS}" \
ILDFLAGS="${ILDFLAGS}" \
LCC="${LCC}" \
CC="${CC}" \
MAKE_FILE=${MAKE_FILE} \
SED=${SED} \
@@ -914,6 +925,7 @@ SAMPLE_PASSDOWN= Q="${Q}" \
LDFLAGS="${LDFLAGS}" \
ILDFLAGS="${ILDFLAGS}" \
CALC_LIBS="../libcalc.a ../custom/libcustcalc.a" \
LCC="${LCC}" \
CC="${CC}" \
MAKE_FILE=${MAKE_FILE} \
SED=${SED} \
@@ -931,7 +943,7 @@ 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 README.OLD HOWTO.INSTALL ${UTIL_MISC_SRC}
calc.man lint.sed HOWTO.INSTALL ${UTIL_MISC_SRC}
# complete list of .o files
#
@@ -1379,8 +1391,8 @@ longlong.h: longlong.c have_stdlib.h have_string.h ${MAKE_FILE}
${Q}echo '' >> longlong.h
${Q}echo '/* do we have/want to use a long long type? */' >> longlong.h
-${Q}rm -f longlong.o longlong
-${Q}${CC} ${CCMAIN} longlong.c -c 2>/dev/null; true
-${Q}${CC} ${ILDFLAGS} longlong.o -o longlong 2>/dev/null; true
-${Q}${LCC} ${CCMAIN} longlong.c -c 2>/dev/null; true
-${Q}${LCC} ${ILDFLAGS} longlong.o -o longlong 2>/dev/null; true
-${Q}${SHELL} -c "./longlong ${LONGLONG_BITS} > ll_tmp 2>/dev/null" \
>/dev/null 2>&1; true
-${Q}if [ -s ll_tmp ]; then \
@@ -1418,8 +1430,8 @@ have_fpos.h: have_fpos.c ${MAKE_FILE}
${Q}echo '' >> have_fpos.h
${Q}echo '/* do we have fgetpos & fsetpos functions? */' >> have_fpos.h
-${Q}rm -f have_fpos.o have_fpos
-${Q}${CC} ${HAVE_FPOS} ${CCMAIN} have_fpos.c -c 2>/dev/null; true
-${Q}${CC} ${ILDFLAGS} have_fpos.o -o have_fpos 2>/dev/null; true
-${Q}${LCC} ${HAVE_FPOS} ${CCMAIN} have_fpos.c -c 2>/dev/null; true
-${Q}${LCC} ${ILDFLAGS} have_fpos.o -o have_fpos 2>/dev/null; true
-${Q}${SHELL} -c "./have_fpos > fpos_tmp 2>/dev/null" \
>/dev/null 2>&1; true
-${Q}if [ -s fpos_tmp ]; then \
@@ -1459,8 +1471,8 @@ fposval.h: fposval.c have_fpos.h have_offscl.h have_posscl.h \
${Q}echo '' >> fposval.h
${Q}echo '/* what are our file position & size types? */' >> fposval.h
-${Q}rm -f fposval.o fposval
-${Q}${CC} ${CCMAIN} fposval.c -c 2>/dev/null; true
-${Q}${CC} ${ILDFLAGS} fposval.o -o fposval 2>/dev/null; true
-${Q}${LCC} ${CCMAIN} fposval.c -c 2>/dev/null; true
-${Q}${LCC} ${ILDFLAGS} fposval.o -o fposval 2>/dev/null; true
${Q}${SHELL} -c "./fposval fposv_tmp >> fposval.h 2>/dev/null" \
>/dev/null 2>&1; true
${Q}echo '' >> fposval.h
@@ -1492,8 +1504,8 @@ have_const.h: have_const.c ${MAKE_FILE}
${Q}echo '' >> have_const.h
${Q}echo '/* do we have or want const? */' >> have_const.h
-${Q}rm -f have_const.o have_const
-${Q}${CC} ${CCMAIN} ${HAVE_CONST} have_const.c -c 2>/dev/null; true
-${Q}${CC} ${ILDFLAGS} have_const.o -o have_const 2>/dev/null; true
-${Q}${LCC} ${CCMAIN} ${HAVE_CONST} have_const.c -c 2>/dev/null; true
-${Q}${LCC} ${ILDFLAGS} have_const.o -o have_const 2>/dev/null; true
-${Q}${SHELL} -c "./have_const > const_tmp 2>/dev/null" \
>/dev/null 2>&1; true
-${Q}if [ -s const_tmp ]; then \
@@ -1531,8 +1543,8 @@ have_offscl.h: have_offscl.c ${MAKE_FILE}
${Q}echo '' >> have_offscl.h
${Q}echo '' >> have_offscl.h
-${Q}rm -f have_offscl.o have_offscl
-${Q}${CC} ${CCMAIN} ${HAVE_OFFSCL} have_offscl.c -c 2>/dev/null; true
-${Q}${CC} ${ILDFLAGS} have_offscl.o -o have_offscl 2>/dev/null; true
-${Q}${LCC} ${CCMAIN} ${HAVE_OFFSCL} have_offscl.c -c 2>/dev/null; true
-${Q}${LCC} ${ILDFLAGS} have_offscl.o -o have_offscl 2>/dev/null; true
-${Q}${SHELL} -c "./have_offscl > offscl_tmp 2>/dev/null" \
>/dev/null 2>&1; true
-${Q}if [ -s offscl_tmp ]; then \
@@ -1569,8 +1581,8 @@ have_posscl.h: have_posscl.c have_fpos.h ${MAKE_FILE}
${Q}echo '' >> have_posscl.h
${Q}echo '' >> have_posscl.h
-${Q}rm -f have_posscl.o have_posscl
-${Q}${CC} ${CCMAIN} ${HAVE_POSSCL} have_posscl.c -c 2>/dev/null; true
-${Q}${CC} ${ILDFLAGS} have_posscl.o -o have_posscl 2>/dev/null; true
-${Q}${LCC} ${CCMAIN} ${HAVE_POSSCL} have_posscl.c -c 2>/dev/null; true
-${Q}${LCC} ${ILDFLAGS} have_posscl.o -o have_posscl 2>/dev/null; true
-${Q}${SHELL} -c "./have_posscl > posscl_tmp 2>/dev/null" \
>/dev/null 2>&1; true
-${Q}if [ -s posscl_tmp ]; then \
@@ -1621,8 +1633,8 @@ align32.h: align32.c longbits.h have_unistd.h ${MAKE_FILE}
fi
-${Q}if [ X = X${ALIGN32} ]; then \
rm -f align32.o align32; \
${CC} ${CCMAIN} ${ALIGN32} align32.c -c 2>/dev/null; \
${CC} ${ILDFLAGS} align32.o -o align32 2>/dev/null; \
${LCC} ${CCMAIN} ${ALIGN32} align32.c -c 2>/dev/null; \
${LCC} ${ILDFLAGS} align32.o -o align32 2>/dev/null; \
${SHELL} -c "./align32 >align32_tmp 2>/dev/null" >/dev/null 2>&1; \
if [ -s align32_tmp ]; then \
cat align32_tmp >> align32.h; \
@@ -1662,8 +1674,8 @@ have_uid_t.h: have_uid_t.c have_unistd.h ${MAKE_FILE}
${Q}echo '' >> have_uid_t.h
${Q}echo '/* do we have or want uid_t? */' >> have_uid_t.h
-${Q}rm -f have_uid_t.o have_uid_t
-${Q}${CC} ${CCMAIN} ${HAVE_UID_T} have_uid_t.c -c 2>/dev/null; true
-${Q}${CC} ${ILDFLAGS} have_uid_t.o -o have_uid_t 2>/dev/null; true
-${Q}${LCC} ${CCMAIN} ${HAVE_UID_T} have_uid_t.c -c 2>/dev/null; true
-${Q}${LCC} ${ILDFLAGS} have_uid_t.o -o have_uid_t 2>/dev/null; true
-${Q}${SHELL} -c "./have_uid_t > uid_tmp 2>/dev/null" \
>/dev/null 2>&1; true
-${Q}if [ -s uid_tmp ]; then \
@@ -1701,8 +1713,8 @@ have_newstr.h: have_newstr.c ${MAKE_FILE}
${Q}echo '/* do we have or want memcpy(), memset() & strchr()? */' \
>> have_newstr.h
-${Q}rm -f have_newstr.o have_newstr
-${Q}${CC} ${CCMAIN} ${HAVE_NEWSTR} have_newstr.c -c 2>/dev/null; true
-${Q}${CC} ${ILDFLAGS} have_newstr.o -o have_newstr 2>/dev/null; true
-${Q}${LCC} ${CCMAIN} ${HAVE_NEWSTR} have_newstr.c -c 2>/dev/null; true
-${Q}${LCC} ${ILDFLAGS} have_newstr.o -o have_newstr 2>/dev/null; true
-${Q}${SHELL} -c "./have_newstr > newstr_tmp 2>/dev/null" \
>/dev/null 2>&1; true
-${Q}if [ -s newstr_tmp ]; then \
@@ -1739,8 +1751,8 @@ have_memmv.h: have_memmv.c ${MAKE_FILE}
${Q}echo '' >> have_memmv.h
${Q}echo '/* do we have or want memmove()? */' >> have_memmv.h
-${Q}rm -f have_memmv.o have_memmv
-${Q}${CC} ${CCMAIN} ${HAVE_MEMMOVE} have_memmv.c -c 2>/dev/null; true
-${Q}${CC} ${ILDFLAGS} have_memmv.o -o have_memmv 2>/dev/null; true
-${Q}${LCC} ${CCMAIN} ${HAVE_MEMMOVE} have_memmv.c -c 2>/dev/null; true
-${Q}${LCC} ${ILDFLAGS} have_memmv.o -o have_memmv 2>/dev/null; true
-${Q}${SHELL} -c "./have_memmv > newstr_tmp 2>/dev/null" \
>/dev/null 2>&1; true
-${Q}if [ -s newstr_tmp ]; then \
@@ -1776,8 +1788,8 @@ args.h: have_stdvs.c have_varvs.c have_string.h have_unistd.h have_string.h
${Q}echo '' >> args.h
${Q}echo '' >> args.h
-${Q}rm -f have_stdvs.o have_stdvs
-${Q}${CC} ${CCMAIN} ${HAVE_VSPRINTF} have_stdvs.c -c 2>/dev/null; true
-${Q}${CC} ${ILDFLAGS} have_stdvs.o -o have_stdvs 2>/dev/null; true
-${Q}${LCC} ${CCMAIN} ${HAVE_VSPRINTF} have_stdvs.c -c 2>/dev/null; true
-${Q}${LCC} ${ILDFLAGS} have_stdvs.o -o have_stdvs 2>/dev/null; true
-${Q}if ./have_stdvs >>args.h 2>/dev/null; then \
touch have_args; \
else \
@@ -1785,8 +1797,8 @@ args.h: have_stdvs.c have_varvs.c have_string.h have_unistd.h have_string.h
fi
-${Q}if [ ! -f have_args ] && [ X"${HAVE_VSPRINTF}" = X ]; then \
rm -f have_stdvs.o have_stdvs have_varvs.o have_varvs; \
${CC} ${CCMAIN} -DDONT_HAVE_VSPRINTF have_varvs.c -c 2>/dev/null; \
${CC} ${ILDFLAGS} have_varvs.o -o have_varvs 2>/dev/null; \
${LCC} ${CCMAIN} -DDONT_HAVE_VSPRINTF have_varvs.c -c 2>/dev/null; \
${LCC} ${ILDFLAGS} have_varvs.o -o have_varvs 2>/dev/null; \
if ./have_varvs >>args.h 2>/dev/null; then \
touch have_args; \
else \
@@ -1865,17 +1877,17 @@ calc_errno.h: calc_errno.c ${MAKE_FILE}
echo 'extern int sys_nerr; ' \
'/* number of system errors */' >> calc_errno.h; \
else \
${CC} ${CCMAIN} -DTRY_ERRNO_NO_DECL \
${LCC} ${CCMAIN} -DTRY_ERRNO_NO_DECL \
calc_errno.c -o calc_errno 2>calc_errno_tmp; \
if [ -x ./calc_errno ]; then \
./calc_errno >> calc_errno.h; \
else \
${CC} ${CCMAIN} -DTRY_ERRNO_STD_DECL \
${LCC} ${CCMAIN} -DTRY_ERRNO_STD_DECL \
calc_errno.c -o calc_errno 2>calc_errno_tmp; \
if [ -x ./calc_errno ]; then \
./calc_errno >> calc_errno.h; \
else \
${CC} ${CCMAIN} -DTRY_ERRNO_OLD_DECL \
${LCC} ${CCMAIN} -DTRY_ERRNO_OLD_DECL \
calc_errno.c -o calc_errno 2>calc_errno_tmp; \
if [ -x ./calc_errno ]; then \
./calc_errno >> calc_errno.h; \
@@ -1971,16 +1983,16 @@ calcerr.c: calcerr.tbl calcerr_c.sed calcerr_c.awk ${MAKE_FILE}
##
endian.o: endian.c have_unistd.h
${CC} ${CCMAIN} endian.c -c
${LCC} ${CCMAIN} endian.c -c
endian: endian.o
${CC} ${ILDFLAGS} endian.o -o endian
${LCC} ${ILDFLAGS} endian.o -o endian
longbits.o: longbits.c longlong.h have_unistd.h
${CC} ${CCMAIN} longbits.c -c
${LCC} ${CCMAIN} longbits.c -c
longbits: longbits.o
${CC} ${ILDFLAGS} longbits.o -o longbits
${LCC} ${ILDFLAGS} longbits.o -o longbits
##
#
@@ -2259,11 +2271,11 @@ bsdilist: ${DISTLIST} ${BUILD_H_SRC} calc.1
##
check: all ./lib/regress.cal ${REGRESS_CAL}
${CALC_ENV} ./calc -i -q read regress
${CALC_ENV} ./calc -d -q read regress
chk: ./lib/regress.cal ${REGRESS_CAL}
${V} echo '=-=-=-=-= start of $@ rule =-=-=-=-='
${CALC_ENV} ./calc -i -q read regress 2>&1 | ${AWK} -f check.awk
${CALC_ENV} ./calc -d -q read regress 2>&1 | ${AWK} -f check.awk
${V} echo '=-=-=-=-= end of $@ rule =-=-=-=-='
##
@@ -2336,6 +2348,7 @@ env:
@echo "LCFLAGS=${LCFLAGS}"; echo ""
@echo "LDFLAGS=${LDFLAGS}"; echo ""
@echo "ILDFLAGS=${ILDFLAGS}"; echo ""
@echo "LCC=${LCC}"; echo ""
@echo "CC=${CC}"; echo ""
@echo "SHELL=${SHELL}"; echo ""
@echo "MAKE=${MAKE}"; echo ""

33
README
View File

@@ -24,6 +24,39 @@ If you run into problems, see the BUGS file.
=-=
Calc is distributed with an extensive collection of help files that
are accessible from the command line. The following assume that you
are running calc from the distribution directory or that you have
installed calc. In these examples, the ">" is the calc prompt, not
something that you type in.
For list of help topics:
> help
For overview of calc overview:
> help intro
> help overview
> help command
> help define
> help statement
> help variable
For list of builtin functions:
> help builtin
C programmers should note some unexpected differences in the calc syntax:
> help unexpected
Calc is shipped with a library of calc scripts. For a list see:
> help stdlib
=-=
See the file:
help/todo

View File

@@ -1,73 +0,0 @@
# Copyright (c) 1997 David I. Bell
# Permission is granted to use, distribute, or modify this source,
# provided that this copyright notice remains intact.
#
# Arbitrary precision calculator.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
NOTE: This is an old historic README. We recommend that
you read README and HOWTO.INSTALL for more info.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
I am allowing this calculator to be freely distributed for your enjoyment.
Like all multi-precision programs, you should not depend absolutely on
its results, since bugs in such programs can be insidious and only rarely
show up.
-dbell-
p.s. By Landon Curt Noll:
Building calc in 3 easy steps:
1) Look at the makefile, and adjust it to suit your needs.
Here are some Makefile hints:
In the past, some people have had to adjust the VARARG or
TERMCONTROL because the Makefile cannot always guess
correctly for certain systems. You may need to play with
these values if you experience problems.
The default compiler used is 'cc'. The default compiler flag
is '-O'. If you have gcc, or gcc v2 (or better) you should use
that instead. Some compilers allow for optimization beyond
just -O (gcc v2 has -O2, mips cc has -O3). You should select
the best flag for speed optimization. Calc can be cpu intensive
so selecting a quality compiler and good optimization level can
really pay off.
2) build calc:
make all
3) test calc:
make check
==>>>If you run into problems, follow the instructions in the BUGS file<<<==
=-=
For further reading:
LIBRARY
explains how programs can use libcalc.a to take advantage
of the calc multi-precision routines.
help/todo
current wish list for calc
CHANGES
recent changes to calc
BUGS
known bugs, mis-features and how to report problems
help/full
full set of calc documentation
=-=
David I. Bell dbell@auug.org.au
chongo <Landon Curt Noll> /\../\

11
addop.c
View File

@@ -164,7 +164,8 @@ endfunc(void)
size += dumpop(&fp->f_opcodes[size]);
}
}
if (inputisterminal() || conf->lib_debug >= 0) {
if ((inputisterminal() && conf->lib_debug & 1) ||
(!inputisterminal() && conf->lib_debug & 2)) {
printf("%s(", fp->f_name);
for (index = 0; index < fp->f_paramcount; index++) {
if (index)
@@ -237,7 +238,8 @@ rmuserfunc(char *name)
return;
freenumbers(functions[index]);
free(functions[index]);
if (inputisterminal() && conf->lib_debug >= 0)
if ((inputisterminal() && conf->lib_debug & 1) ||
(!inputisterminal() && conf->lib_debug & 2))
printf("%s() undefined\n", name);
functions[index] = NULL;
}
@@ -447,6 +449,11 @@ addop(long op)
case OP_GLOBALADDR:
diff = 1 + PTR_SIZE;
break;
case OP_UNDEF:
fp->f_opcodecount -= 1;
oldop = OP_NOP;
oldoldop = OP_NOP;
return;
default:
cut = FALSE;
}

166
calc.c
View File

@@ -11,7 +11,6 @@
#include <pwd.h>
#include <sys/types.h>
#include <ctype.h>
#include <setjmp.h>
#define CALC_C
#include "calc.h"
@@ -37,33 +36,11 @@
#include <stdlib.h>
#endif
/*
* external definitions and functions
*/
extern int abortlevel; /* current level of aborts */
extern BOOL inputwait; /* TRUE if in a terminal input wait */
extern jmp_buf jmpbuf; /* for errors */
extern int isatty(int tty); /* TRUE if fd is a tty */
extern int p_flag; /* TRUE => pipe mode */
extern int q_flag; /* TRUE => don't execute rc files */
extern int u_flag; /* TRUE => unbuffer stdin and stdout */
extern char *pager; /* $PAGER or default */
extern int stdin_tty; /* TRUE if stdin is a tty */
extern int interactive; /* TRUE if interactive session (no cmd args) */
extern char *program; /* our name */
extern char cmdbuf[]; /* command line expression */
extern char *version(void); /* return version string */
/*
* static definitions and functions
*/
static char *usage = "usage: %s [-C] [-e] [-h] [-i] [-m mode] [-n] [-p]\n"
"\t[-q] [-u] [[--] calc_cmd ...]\n";
static char *usage = "usage: %s [-c] [-C] [-d] [-e] [-h] [-i] [-m mode]\n"
"\t[-n] [-p] [-q] [-u] [-v] [[--] calc_cmd ...]\n";
static void intint(int arg); /* interrupt routine */
@@ -84,7 +61,7 @@ main(int argc, char **argv)
* parse args
*/
program = argv[0];
while ((c = getopt(argc, argv, "Cehim:npquv")) != -1) {
while ((c = getopt(argc, argv, "Cehim:npquvcd")) != -1) {
switch (c) {
case 'C':
#if defined(CUSTOM)
@@ -107,7 +84,7 @@ main(int argc, char **argv)
want_defhelp = 1;
break;
case 'i':
ign_errmax = TRUE;
i_flag = TRUE;
break;
case 'm':
if (optarg[1] == '\0' || *optarg<'0' || *optarg>'7') {
@@ -136,6 +113,12 @@ main(int argc, char **argv)
case 'u':
u_flag = TRUE;
break;
case 'c':
c_flag = TRUE;
break;
case 'd':
d_flag = TRUE;
break;
case 'v':
/*
* we are too early in processing to call
@@ -152,7 +135,7 @@ main(int argc, char **argv)
exit(1);
}
}
interactive = (optind >= argc);
havecommands = (optind < argc);
/*
* look at the length of any trailing command args
@@ -201,8 +184,7 @@ main(int argc, char **argv)
* initialize
*/
libcalc_call_me_first();
stdin_tty = TRUE; /* assume internactive default */
conf->tab_ok = TRUE; /* assume internactive default */
stdin_tty = isatty(0); /* assume stdin is on fd 0 */
if (want_defhelp) {
givehelp(DEFAULTCALCHELP);
libcalc_call_me_last();
@@ -212,22 +194,13 @@ main(int argc, char **argv)
/*
* if allowed or needed, print version and setup bindings
*/
if (interactive) {
/*
* check for pipe mode and/or non-tty stdin
*/
if (!p_flag) {
stdin_tty = isatty(0); /* assume stdin is on fd 0 */
}
/*
* if tty, setup bindings
*/
if (stdin_tty) {
if (!havecommands && stdin_tty) {
if (!d_flag) {
printf("%s (version %s)\n", CALC_TITLE, version());
printf("[%s]\n\n",
"Type \"exit\" to exit, or \"help\" for help.");
switch (hist_init(calcbindings)) {
}
switch (hist_init(calcbindings)) {
case HIST_NOFILE:
fprintf(stderr,
"%s: Cannot open bindings file \"%s\", "
@@ -240,7 +213,6 @@ main(int argc, char **argv)
"%s: Cannot set terminal modes, "
"fancy editing disabled\n", program);
break;
}
}
}
@@ -252,53 +224,87 @@ main(int argc, char **argv)
/*
* reset/initialize the computing environment
*/
if (post_init) {
if (post_init)
initialize();
} else {
/* initialize already done, jmpbuf is ready */
post_init = TRUE;
}
/*
* if arg mode or non-tty mode, just do the work and be gone
*/
if (!interactive || !stdin_tty) {
if (q_flag == FALSE && allow_read) {
runrcfiles();
q_flag = TRUE;
}
if (interactive)
(void) openterminal();
else
(void) openstring(cmdbuf);
start_done = TRUE;
getcommands(FALSE);
libcalc_call_me_last();
exit(0);
}
}
/* if in arg mode, we should not get here */
if (!interactive) {
libcalc_call_me_last();
exit(1);
post_init = TRUE;
}
/*
* process commands
* (re)establish the interrupt handler
*/
if (!start_done) {
reinitialize();
}
(void) signal(SIGINT, intint);
start_done = TRUE;
getcommands(TRUE);
/*
* execute calc code based on the run state
*/
if (run_state == RUN_PRE_BEGIN) {
if (!q_flag && allow_read) {
run_state = RUN_PRE_RCFILES;
runrcfiles();
}
run_state = RUN_POST_RCFILES;
}
if (run_state == RUN_PRE_RCFILES) {
fprintf(stderr, "Execution error in rcfiles\n");
if ((c_flag && !stoponerror) || stoponerror < 0) {
getcommands(FALSE);
run_state = RUN_POST_RCFILES;
} else {
if ((havecommands && !i_flag) || !stdin_tty)
run_state = RUN_STOP_ON_ERROR;
else if (havecommands)
run_state = RUN_POST_CMD_ARGS;
else
run_state = RUN_POST_RCFILES;
}
}
if (run_state == RUN_POST_RCFILES) {
if (havecommands) {
run_state = RUN_PRE_CMD_ARGS;
(void) openstring(cmdbuf);
getcommands(FALSE);
}
run_state = RUN_POST_CMD_ARGS;
}
if (run_state == RUN_PRE_CMD_ARGS) {
fprintf(stderr, "Execution error in commands\n");
if ((c_flag && !stoponerror) || stoponerror < 0) {
getcommands(FALSE);
run_state = RUN_POST_CMD_ARGS;
} else {
closeinput();
if (!stdin_tty || !i_flag)
run_state = RUN_STOP_ON_ERROR;
else
run_state = RUN_POST_CMD_ARGS;
}
}
if (run_state == RUN_POST_CMD_ARGS) {
if (stdin_tty && ((havecommands && !i_flag) || p_flag))
run_state = RUN_NOT_TOP_LEVEL;
else
openterminal();
} else if (run_state == RUN_TOP_LEVEL) {
if (!stdin_tty && (!c_flag || stoponerror) &&
stoponerror >= 0) {
run_state = RUN_STOP_ON_ERROR;
} else if ((c_flag && !stoponerror) || stoponerror < 0)
getcommands(FALSE);
else
reinitialize();
}
if (run_state < RUN_NOT_TOP_LEVEL) {
run_state = RUN_TOP_LEVEL;
getcommands(TRUE);
}
/*
* all done
*/
libcalc_call_me_last();
/* exit(0); */
return 0;
return (run_state == RUN_STOP_ON_ERROR ||
run_state == RUN_UNKNOWN) ? 1 : 0;
}

48
calc.h
View File

@@ -10,6 +10,7 @@
#if !defined(__CALC_H__)
#define __CALC_H__
#include <setjmp.h>
#include "value.h"
@@ -58,6 +59,8 @@
#define ABORT_MATH 3 /* abort on any math operation */
#define ABORT_NOW 4 /* abort right away */
#define ERRMAX 20 /* default errmax value */
/*
* File ids corresponding to standard in, out, error, and when not in use.
*/
@@ -124,7 +127,6 @@ extern long linenumber(void);
extern void runrcfiles(void);
extern void closeinput(void);
/*
* Other routines.
*/
@@ -138,21 +140,39 @@ extern void libcalc_call_me_first(void);
extern void libcalc_call_me_last(void);
extern void showerrors(void);
/*
* Initialization
*/
extern void initialize(void);
extern void reinitialize(void);
extern int isatty(int tty); /* TRUE if fd is a tty */
extern char *version(void); /* return version string */
extern int post_init; /* TRUE => setjmp for math_error is ready */
/*
* Global data definitions.
* global flags and definitions
*/
extern int abortlevel; /* current level of aborts */
extern BOOL inputwait; /* TRUE if in a terminal input wait */
extern jmp_buf jmpbuf; /* for errors */
extern int p_flag; /* TRUE => pipe mode */
extern int q_flag; /* TRUE => don't execute rc files */
extern int u_flag; /* TRUE => unbuffer stdin and stdout */
extern int d_flag; /* TRUE => disable heading, lib_debug == 0 */
extern int c_flag; /* TRUE => continue after error if permitted */
extern int i_flag; /* TRUE => try to go interactive after error */
extern int stoponerror; /* >0 => stop, <0 => continue, ==0 => use -c */
extern char *pager; /* $PAGER or default */
extern int stdin_tty; /* TRUE if stdin is a tty */
extern int havecommands; /* TRUE if have cmd args) */
extern char *program; /* our name */
extern char cmdbuf[]; /* command line expression */
extern int abortlevel; /* current level of aborts */
extern BOOL inputwait; /* TRUE if in a terminal input wait */
extern VALUE *stack; /* execution stack */
extern int start_done; /* TRUE => start up processing finished */
extern int dumpnames; /* TRUE => dump names rather than indices */
extern char *calcpath; /* $CALCPATH or default */
@@ -163,14 +183,28 @@ extern char *shell; /* $SHELL or default */
extern char *program; /* our name (argv[0]) */
extern int no_env; /* TRUE (-e) => ignore env vars on startup */
extern int ign_errmax; /* TRUE (-i) => ignore when errcount exceeds errmax */
extern int errmax; /* if >= 0, error when errcount exceeds errmax */
extern int new_std; /* TRUE (-n) => use newstd configuration */
extern int allow_read; /* FALSE => may not open any files for reading */
extern int allow_write; /* FALSE => may not open any files for writing */
extern int allow_exec; /* FALSE => may not execute any commands */
extern int post_init; /* TRUE => setjmp for math_error is ready */
/*
* calc startup and run state
*/
typedef enum {
RUN_UNKNOWN = -1, /* unknown or unset start state */
RUN_PRE_BEGIN = 0, /* pre-startup state, calc execution started */
RUN_PRE_RCFILES = 1, /* rc files about to or are being evaluated */
RUN_POST_RCFILES = 2, /* rc files have been evaluated */
RUN_PRE_CMD_ARGS = 3, /* cmd_args about to or are being evaluated */
RUN_POST_CMD_ARGS = 4, /* cmd_args have been evaluated */
RUN_TOP_LEVEL = 5, /* running at the top interactive level */
RUN_NOT_TOP_LEVEL = 6, /* running not at the top interactive level */
RUN_STOP_ON_ERROR = 7 /* we need to stop due to errors */
} run;
extern run run_state;
/*

535
calc.man
View File

@@ -1,190 +1,356 @@
.\"
.\" Copyright (c) 1994 David I. Bell and Landon Curt Noll
.\" Copyright (c) 1993 David I. Bell and Landon Curt Noll
.\" Original man page dated 15nov93
.\" Copyright (c) 1999 David I. Bell and Landon Curt Noll
.\" Permission is granted to use, distribute, or modify this source,
.\" provided that this copyright notice remains intact.
.\"
.\" calculator by David I. Bell
.\" man page by Landon Noll
.TH calc 1 "^..^" "15nov93"
.TH calc 1 "^..^" "15Oct1999"
.SH NAME
calc \- arbitrary precision calculator
.SH SYNOPSIS
\fIcalc\fP
[\fI\-h\fP]
[\fI\-m mode\fP]
[\fI\-p\fP]
[\fI\-q\fP]
[\fI\-u\fP]
[\fI\-v\fP]
[\fIcalc_cmd \&.\|.\|.\fp]
.RB [ \-c ]
.RB [ \-C ]
.RB [ \-d ]
.RB [ \-e ]
.RB [ \-h ]
.RB [ \-i ]
.RB [ \-m\ \&mode ]
.br
.in +5n
.RB [ \-n ]
.RB [ \-p ]
.RB [ \-q ]
.RB [ \-u ]
.RB [ \-v ]
.RB [ calc_cmd\ \&.\|.\|. ]
.in -5n
.SH DESCRIPTION
\&
.br
CALC COMMAND LINE
.PP
.TP
\fI\-h\fP
Print a help message.
This option implies \fI \-q\fP.
This is equivalent to the calc command \fIhelp help\fP.
The help facility is disabled unless the \fImode\fP is 5 or 7.
See \fI\-m\fP below.
.sp
.TP
\fI\-m mode\fP
This flag sets the permission mode of calc.
It controls the ability for \fIcalc\fP to open files
and execute programs.
\fIMode\fP may be a number from 0 to 7.
.sp
The \fImode\fP value is interpreted in a way similar
to that of the \fRchmod(1)\fP octal mode:
.sp
.in +0.5i
.B \-c
Continue reading command lines even after an execution
error has caused the abandonment of a line.
.sp 1
For example:
.sp 1
.in +5n
.nf
0 do not open any file, do not execute progs
1 do not open any file
2 do not open files for reading, do not execute progs
3 do not open files for reading
4 do not open files for writing, do not execute progs
5 do not open files for writing
6 do not execute any program
7 allow everything (default mode)
calc read many_errors.cal
.fi
.in -0.5i
.sp
If one wished to run calc from a privledged user, one might
want to use \fI\-m 0\fP in an effort to make calc more secure.
.sp
\fIMode\fP bits for reading and writing apply only on an open.
.in -5n
.sp 1
will cause
.B calc
to abort on the first error, whereas:
.sp 1
.in +5n
.nf
calc -c read many_errors.cal
.fi
.in -5n
.sp 1
will
cause
.B calc
to try to process each line being read
despite the errors that it encounters.
.TP
.B \-C
Permit the execution of custom builtin functions. Without
this flag, calling the custom() builtin function will
simply generate an error.
.sp 1
Use if this flag may cause
.B calc
to execute functions that
are non-standard and that are not portable. Custom builtin
functions are disabled by default for this reason.
.TP
.B \-d
Disable the printing of the opening title. The printing
of library debug and informational messages is also disabled
as if \fBconfig("lib_debug", 0)\fP had been executed.
.sp 1
For example:
.sp 1
.in +5n
calc 'read qtime; qtime(2)'
.in -5n
.sp 1
will output something like:
.sp 1
.in +5n
.nf
qtime(utc_hr_offset) defined
It's nearly ten past six.
.fi
.in -5n
.sp 1
whereas:
.sp 1
.in +5n
.nf
calc -d 'read qtime; qtime(2)'
.fi
.in -5n
.sp 1
will just say:
.sp 1
.in +5n
.nf
It's nearly ten past six.
.fi
.in -5n
.sp 1
.TP
.B \-e
Ignore any environment variables on startup.
The getenv() builtin will still return values, however.
.TP
.B \-h
Print a help message. This option implies
.BR \-q .
This
is equivalent to the
.B calc
command help help.
The help facility is disabled unless the mode is 5 or 7.
See
.BR \-m .
.TP
.B \-i
Become interactive if possible.
Be default, if
.I calc_cmd
args are given,
.B calc
will execute them and exit.
This flag args are given,
.B calc
will execute them and exit.
This flag will cause
.B calc
to drop into interactive mode after the
commands are executed.
.sp 1
For example:
.sp 1
.in +5n
.nf
calc 2+5
.fi
.in -5n
.sp 1
will print the value 7 and exit whereas:
.sp 1
.in +5n
.nf
calc -i 2+5
.fi
.in -5n
.sp 1
will print the value 7 and prompt the user for more
.B calc
commands.
.TP
.BR \-m " mode"
This flag sets the permission mode of
.BR calc .
It controls the ability for
.B calc
to open files and execute programs.
Mode may be a number from 0 to 7.
.sp 1
The mode value is interpreted in a way similar to that
of the
.BR chmod (1)
octal mode:
.sp 1
.in +5n
.nf
0 do not open any file, do not execute progs
1 do not open any file
2 do not open files for reading, do not execute progs
3 do not open files for reading
4 do not open files for writing, do not execute progs
5 do not open files for writing
6 do not execute any program
7 allow everything (default mode)
.fi
.in -5n
.sp 1
If one wished to run
.B calc
from a privileged user, one might want to use
.B \-m
0 in an effort to make
.B calc
somewhat more secure.
.sp 1
Mode bits for reading and writing apply only on an
open.
Files already open are not effected.
Thus if one wanted to use the \fI\-m 0\fP in an effort to make
\fIcalc\fP more secure, but still wanted to read and write a specific
file, one might want to do:
.sp
.in +0.5i
Thus if one wanted to use the
.B \-m
0 in an effort to make
.B calc
somewhat more secure, but still wanted to read and write a specific
file, one might want to do in
.BR sh (1),
.BR ksh (1),
.BR bash (1)-like
shells:
.sp 1
.in +5n
.nf
\fRcalc \-m 0 3<a.file\fP
calc -m 0 3<a.file
.fi
.in -0.5i
.sp
Files presented to \fIcalc\fP in this way are opened in an unknown mode.
\fICalc\fP will attempt to read or write them if directed.
.sp
If the \fImode\fP disables opening of files for reading, then
the startup library scripts are disabled as of \fI\-q\fP was given.
The reading of key bindings is also disabled when the \fImode\fP
disables opening of files for reading.
.in -5n
.sp 1
Files presented to
.B calc
in this way are opened in an
unknown mode.
.B Calc
will attempt to read or write them if directed.
.sp 1
If the mode disables opening of files for reading, then
the startup library scripts are disabled as of
.B \-q
was given.
The reading of key bindings is also disabled
when the mode disables opening of files for reading.
.TP
\fI \-p\fP
Pipe processing is enabled by use of \-p. For example:
.sp
.in +0.5i
.B \-n
Use the new configuration defaults instead of the old
default classic defaults.
This flag as the same effect
as executing \fBconfig("all", "newcfg")\fP at startup time.
.TP
.B \-p
Pipe processing is enabled by use of
.BR \-p .
For example:
.sp 1
.in +5n
.nf
\fRecho "print 2^21701\-1, 2^23209\-1" | calc \-p | fizzbin\fP
calc -p '2^21701-1' | fizzbin
.fi
.in -0.5i
.sp
In pipe mode, \fIcalc\fP does not prompt, does not print leading tabs
and does not print the initial header.
.in -5n
.sp 1
In pipe mode,
.B calc
does not prompt, does not print leading
tabs and does not print the initial header.
The
.B \-p
flag overrides
.BR \-i .
.TP
\fI \-q\fP
Disable the use of the \fI$CALCRC\fP startup scripts.
.B \-q
Disable the use of the $CALCRC startup scripts.
.TP
\fI \-u\fP
.B \-u
Disable buffering of stdin and stdout.
.TP
\fI \-v\fP
Print the version and exit.
.B \-v
Print the
.B calc
version number and exit.
.PP
Without \fIcalc_cmd\fPs, \fIcalc\fP operates interactively.
If one or more \fIcalc_cmd\fPs are given on the command line,
\fIcalc\fP will execute them and exit.
The printing of leading tabs on output is disabled
as if \fIconfig("tab",0)\fP had been executed.
Without
.IR calc_cmd ,
.B calc
operates interactively.
If one or more
.I calc_cmd
are given on the command line,
.B calc
will execute them and exit.
If
.B \-i
is given,
.B calc
will attempt to become interactive
even of one or more
.I calc_cmd
are given on the command line.
.PP
Normally on startup, \fIcalc\fP attempts to execute a collection
of library scripts.
The environment variable \fI$CALCRC\fP (if non-existent then
a compiled in value) contains a \fI:\fP separated list of
startup library scripts.
No error conditions are produced if these startup library scripts
are not found.
Normally on startup,
.B calc
attempts to execute a collection of
library scripts.
The environment variable $CALCRC (if non-existent
then a compiled in value) contains a : separated list of startup
library scripts.
No error conditions are produced if these startup
library scripts are not found.
.PP
If the \fImode\fP disables opening of files for reading, then
the startup library scripts are disabled as of \fI\-q\fP was given
and \fI$CALCRC\fP as well as the default compiled in value are ignored.
If the mode disables opening of files for reading, then the startup
library scripts are disabled as of
.B \-q
was given and $CALCRC as well
as the default compiled in value are ignored.
.PP
Filenames are subject to ``~'' expansion (see below).
The environment variable \fI$CALCPATH\fP (if non-existent then
a compiled in value) contains a \fI:\fP separated list of search
directories.
If a file does not begin with \fI/\fP, \fI~\fP or \fI./\fP,
then it is searched for under each directory listed in the \fI$CALCPATH\fP.
It is an error if no such readable file is found.
The
environment variable $CALCPATH (if non-existent then a compiled in
value) contains a : separated list of search directories.
If a
file does not begin with /, ~ or ./, then it is searched for under
each directory listed in the $CALCPATH.
It is an error if no such
readable file is found.
.PP
Calc treats all open files, other than stdin, stdout and stderr
as files available for reading and writing.
One may present calc with an already open file in the following way:
.sp
.in +0.5i
.B Calc
treats all open files, other than stdin, stdout and
stderr as files available for reading and writing.
One may
present
.B calc
with an already open file using
.BR sh (1),
.BR ksh (1),
.BR bash (1)-like
shells is to:
.sp 1
.in +5n
calc 3<open_file 4<open_file2
.in -5n
.sp 1
For more information use the following
.B calc
commands:
.sp 1
.in +5n
.nf
\fRcalc 3<open_file 4<open_file2\fP
.fi
.in -0.5i
.PP
For more information use the following calc commands:
.PP
.in 1.0i
help usage
.br
help help
.br
help overview
help usage
help environment
.in -1.0i
.PP
OVERVIEW
.PP
\fICalc\fP is arbitrary precision arithmetic system that uses
a C-like language.
\fICalc\fP is useful as a calculator, an algorithm prototyped
and as a mathematical research tool.
More importantly, \fIcalc\fP provides one with a machine
independent means of computation.
.PP
\fICalc\fP comes with a rich set of builtin mathematical
and programmatic functions.
.PP
\fICalc\fP is distributed with library of scripts.
Written in the same C-like language, library scripts may be
read in and executed during a \fIcalc\fP session.
These library scripts are also provided because they are
useful and to serve as examples of the \fIcalc\fP language.
One may further extend \fIcalc\fP thru the
use of user defined scripts.
.PP
Internally calc represents numeric values as fractions reduced to their
lowest terms.
The numerators and denominators of these factions may grow to
arbitrarily large values.
Numeric values read in are automatically converted into rationals.
The user need not be aware of this internal representation.
.PP
For more information use the following calc commands:
.PP
.in 1.0i
help intro
.br
help builtin
.br
help stdlib
.br
help define
.br
show builtins
.br
show functions
.in -1.0i
help config
.fi
.in -5n
.sp 1
.PP
DATA TYPES
.PP
@@ -199,7 +365,9 @@ multiplication, division, negation, squaring, modulus,
rounding, exponentiation, equality, comparison, printing
and so on.
.PP
For more information use the following calc commands:
For more information use the following
.B calc
commands:
.PP
.in 1.0i
help types
@@ -220,7 +388,9 @@ procedure.
Values may be grouped together in a matrix, or into a
a list that permits stack and queue style operations.
.PP
For more information use the following calc commands:
For more information use the following
.B calc
commands:
.PP
.in 1.0i
help variable
@@ -256,7 +426,9 @@ For example:
~chongo/lib/fft_multiply.cal
.in -1.0i
.PP
For more information use the following calc command:
For more information use the following
.B calc
command:
.PP
.in 1.0i
help file
@@ -275,7 +447,9 @@ These include commands such as function definition, help,
reading in library scripts, dump files to a file, error notification,
configuration control and status.
.PP
For more information use the following calc command:
For more information use the following
.B calc
command:
.PP
.in 1.0i
help command
@@ -295,7 +469,8 @@ help config
.PD 0
.TP 20
${LIBDIR}/*.cal
library scripts shipped with calc
library scripts shipped with
.B calc
.br
.sp
.TP 20
@@ -323,7 +498,9 @@ Default value: ${CALCPATH}
.TP 5
CALCRC
On startup (unless \-h or \-q was given on the command
line), calc searches for files along this :-separated
line),
.B calc
searches for files along this :-separated
environment variable.
.br
.sp
@@ -333,7 +510,9 @@ Default value: ${CALCRC}
.TP 5
CALCBINDINGS
On startup (unless \fI\-h\fP or \fI\-q\fP was given on the command
line, or \fI\-m\fP disallows opening files for reading), calc reads
line, or \fI\-m\fP disallows opening files for reading),
.B calc
reads
key bindings from the filename specified
by this environment variable.
.br
@@ -343,9 +522,12 @@ Default value: ${CALCBINDINGS}
.SH CREDIT
\&
.br
The majority of calc was written by David I. Bell.
The majority of
.B calc
was written by David I. Bell.
.sp
Calc archives and calc-tester mailing list maintained by Landon Curt Noll.
.B Calc
archives and calc-tester mailing list maintained by Landon Curt Noll.
.sp
Thanks for suggestions and encouragement from Peter Miller,
Neil Justusson, and Landon Noll.
@@ -378,30 +560,27 @@ Copyright (c) 19xx Ernest Bowen and Landon Curt Noll
Permission is granted to use, distribute, or modify this source,
provided that this copyright notice remains intact.
.sp
Send calc comments, suggestions, bug fixes, enhancements
and interesting calc scripts that you would like you see included
Send comments, suggestions, bug fixes, enhancements
and interesting
.B calc
scripts that you would like you see included
in future distributions to:
.sp
.in +0.5i
dbell@auug.org.au
.br
chongo@toad.com
calc-tester-request@postofc.corp.sgi.com
.in -0.5i
.sp
Landon Noll maintains the official calc ftp archive at:
Landon Noll maintains the the
.B calc
web site is located at:
.sp
.in +0.5i
ftp://ftp.uu.net/pub/calc
http://reality.sgi.com/chongo/calc
.in -0.5i
.sp
Alpha test versions, complete with bugs, untested code and
experimental features may be fetched (if you are brave) under:
.sp
.in +0.5i
http://reality.sgi.com/chongo/calc/
.in -0.5i
.sp
One may join the calc testing group by sending a request to:
One may join the
.B calc
testing group by sending a request to:
.sp
.in +0.5i
calc-tester-request@postofc.corp.sgi.com
@@ -410,14 +589,14 @@ calc-tester-request@postofc.corp.sgi.com
Your message body (not the subject) should consist of:
.sp
.in +0.5i
.nf
subscribe calc-tester address
.br
end
.br
name your_full_name
.fi
.in -0.5i
.sp
where "address" is your EMail address and "your_full_name"
is your full name.
.in -0.5i
.sp
Enjoy!
Share and Enjoy! :\-)

View File

@@ -261,6 +261,8 @@ getfunction(void)
{
char *name; /* parameter name */
int type; /* type of token read */
LABEL label;
long index;
(void) tokenmode(TM_DEFAULT);
if (gettoken() != T_SYMBOL) {
@@ -276,9 +278,11 @@ getfunction(void)
beginfunc(name, FALSE);
enterfuncscope();
if (gettoken() != T_LEFTPAREN) {
scanerror(T_SEMICOLON, "Left parenthesis expected for function");
scanerror(T_SEMICOLON,
"Left parenthesis expected for function");
return;
}
index = 0;
for (;;) {
type = gettoken();
if (type == T_RIGHTPAREN)
@@ -292,12 +296,22 @@ getfunction(void)
case SYM_UNDEFINED:
case SYM_GLOBAL:
case SYM_STATIC:
(void) addparam(name);
index = addparam(name);
break;
default:
scanerror(T_NULL, "Parameter \"%s\" is already defined", name);
}
type = gettoken();
if (type == T_ASSIGN) {
clearlabel(&label);
addopone(OP_PARAMADDR, index);
addoplabel(OP_JUMPNN, &label);
getopassignment();
addop(OP_ASSIGNPOP);
setlabel(&label);
type = gettoken();
}
if (type == T_RIGHTPAREN)
break;
if (type != T_COMMA) {
@@ -598,25 +612,25 @@ getstatement(LABEL *contlabel, LABEL *breaklabel, LABEL *nextcaselabel, LABEL *d
scanerror(T_SEMICOLON, "CONTINUE not within FOR, WHILE, or DO");
return;
}
addoplabel(OP_JUMPNE, contlabel);
addoplabel(OP_JUMPNZ, contlabel);
break;
case T_BREAK:
if (breaklabel == NULL_LABEL) {
scanerror(T_SEMICOLON, "BREAK not within FOR, WHILE, or DO");
return;
}
addoplabel(OP_JUMPNE, breaklabel);
addoplabel(OP_JUMPNZ, breaklabel);
break;
case T_GOTO:
if (gettoken() != T_SYMBOL) {
scanerror(T_SEMICOLON, "Missing label in goto");
return;
}
addop(OP_JUMPNE);
addop(OP_JUMPNZ);
addlabel(tokensymbol());
break;
default:
addoplabel(OP_JUMPEQ, &label1);
addoplabel(OP_JUMPZ, &label1);
rescantoken();
getstatement(contlabel, breaklabel, NULL_LABEL, NULL_LABEL);
if (gettoken() != T_ELSE) {
@@ -667,7 +681,7 @@ getstatement(LABEL *contlabel, LABEL *breaklabel, LABEL *nextcaselabel, LABEL *d
contlabel = &label1;
rescantoken();
(void) getexprlist();
addoplabel(OP_JUMPNE, &label3);
addoplabel(OP_JUMPNZ, &label3);
addoplabel(OP_JUMP, breaklabel);
if (gettoken() != T_SEMICOLON) {
(void) tokenmode(oldmode);
@@ -708,7 +722,7 @@ getstatement(LABEL *contlabel, LABEL *breaklabel, LABEL *nextcaselabel, LABEL *d
clearlabel(breaklabel);
setlabel(contlabel);
getcondition();
addoplabel(OP_JUMPEQ, breaklabel);
addoplabel(OP_JUMPZ, breaklabel);
getstatement(contlabel, breaklabel, NULL_LABEL, NULL_LABEL);
addoplabel(OP_JUMP, contlabel);
setlabel(breaklabel);
@@ -731,7 +745,7 @@ getstatement(LABEL *contlabel, LABEL *breaklabel, LABEL *nextcaselabel, LABEL *d
}
setlabel(contlabel);
getcondition();
addoplabel(OP_JUMPNE, &label3);
addoplabel(OP_JUMPNZ, &label3);
setlabel(breaklabel);
(void) tokenmode(oldmode);
return;
@@ -815,6 +829,8 @@ getstatement(LABEL *contlabel, LABEL *breaklabel, LABEL *nextcaselabel, LABEL *d
printeol = TRUE;
for (;;) {
switch (gettoken()) {
case T_RIGHTPAREN:
case T_RIGHTBRACKET:
case T_RIGHTBRACE:
case T_NEWLINE:
case T_EOF:
@@ -1377,6 +1393,21 @@ getassignment (void)
{
int type; /* type of expression */
switch(gettoken()) {
case T_COMMA:
case T_SEMICOLON:
case T_NEWLINE:
case T_RIGHTPAREN:
case T_RIGHTBRACKET:
case T_RIGHTBRACE:
case T_EOF:
addop(OP_UNDEF);
rescantoken();
return EXPR_RVALUE;
}
rescantoken();
type = getaltcond();
switch (gettoken()) {
@@ -1441,7 +1472,7 @@ getaltcond(void)
}
clearlabel(&donelab);
clearlabel(&altlab);
addoplabel(OP_JUMPEQ, &altlab);
addoplabel(OP_JUMPZ, &altlab);
type = getaltcond();
if (gettoken() != T_COLON) {
scanerror(T_SEMICOLON, "Missing colon for conditional expression");

View File

@@ -93,7 +93,7 @@ CONFIG oldstd = { /* backward compatible standard configuration */
FALSE, /* skip duplicate block output lines */
BLK_BASE_HEX, /* block octet print base */
BLK_FMT_HD_STYLE, /* block output format */
0, /* calc library debug level */
3, /* calc library debug level */
0, /* internal calc debug level */
0 /* user defined debug level */
};
@@ -128,7 +128,7 @@ CONFIG newstd = { /* new non-backward compatible configuration */
FALSE, /* skip duplicate block output lines */
BLK_BASE_HEX, /* block octet print base */
BLK_FMT_HD_STYLE, /* block output format */
0, /* calc library debug level */
3, /* calc library debug level */
0, /* internal calc debug level */
0 /* user defined debug level */
};

View File

@@ -85,7 +85,7 @@
/*
* config defult symbols
* config default symbols
*/
#define DISPLAY_DEFAULT 20 /* default digits for float display */
#define EPSILON_DEFAULT "1e-20" /* allowed error for float calculations */
@@ -95,8 +95,6 @@
#define MAXPRINT_DEFAULT 16 /* default number of elements printed */
#define MAXSCANCOUNT 20 /* default max scan errors before an abort */
#define ERRMAX 20 /* default errmax value */
/*
* configuration object

View File

@@ -58,7 +58,7 @@ c_pzasusb8(char *name, int count, VALUE **vals)
*/
h = (USB8 *) z.v;
for (i=0; i < half_cnt; ++i) {
printf("%d:\t", i);
printf("%ld:\t", i);
for (j=0; j < half_len; ++j) {
printf("%02x", (int)(*h++));
}

View File

@@ -76,5 +76,5 @@ main(void)
exit(1);
}
/* exit(0); */
return 0;
return 0;
}

234
func.c
View File

@@ -72,6 +72,7 @@ static int strscan(char *s, int count, VALUE **vals);
static int filescan(FILEID id, int count, VALUE **vals);
static VALUE f_eval(VALUE *vp);
static VALUE f_fsize(VALUE *vp);
static int malloced_putenv(char *str);
@@ -84,6 +85,21 @@ extern void matrandperm(MATRIX *M);
extern void listrandperm(LIST *lp);
extern int idungetc(FILEID id, int ch);
extern int stoponerror;
/*
* malloced environment storage
*/
#define ENV_POOL_CHUNK 10 /* env_pool elements to allocate at a time */
struct env_pool {
char *getenv; /* what getenv() would return, NULL => unused */
char *putenv; /* pointer given to putenv() */
};
static int env_pool_cnt = 0; /* number of env_pool elements in use */
static int env_pool_max = 0; /* number of env_pool elements allocated */
static struct env_pool *e_pool = NULL; /* env_pool elements */
/*
* if HZ & CLK_TCK are not defined, pick typical values, hope for the best
@@ -209,6 +225,28 @@ f_prompt(VALUE *vp)
}
static VALUE
f_display(int count, VALUE **vals)
{
long oldvalue;
VALUE res;
oldvalue = conf->outdigits;
if (count > 0) {
if (vals[0]->v_type != V_NUM || qisfrac(vals[0]->v_num) ||
qisneg(vals[0]->v_num) || zge31b(vals[0]->v_num->num))
fprintf(stderr,
"Out-of-range arg for display ignored\n");
else
conf->outdigits = qtoi(vals[0]->v_num);
}
res.v_type = V_NUM;
res.v_num = itoq(oldvalue);
return res;
}
/*ARGSUSED*/
static VALUE
f_null(int count, VALUE **vals)
@@ -4392,11 +4430,7 @@ f_errno(int count, VALUE **vals)
math_error("errno argument out of range");
/*NOTREACHED*/
}
newerr = z1tol(vp->v_num->num);
if (newerr >= 32768) {
math_error("errno argument out of range");
/*NOTREACHED*/
}
newerr = (int) ztoi(vp->v_num->num);
}
olderr = set_errno(newerr);
@@ -4423,7 +4457,7 @@ f_errcount(int count, VALUE **vals)
math_error("errcount argument out of range");
/*NOTREACHED*/
}
newcount = z1tol(vp->v_num->num);
newcount = (int) ztoi(vp->v_num->num);
}
oldcount = set_errcount(newcount);
@@ -4436,23 +4470,21 @@ f_errcount(int count, VALUE **vals)
static VALUE
f_errmax(int count, VALUE **vals)
{
int newmax, oldmax;
int oldmax;
VALUE *vp;
VALUE result;
newmax = -1;
oldmax = errmax;
if (count > 0) {
vp = vals[0];
/* arg must be an integer */
if (vp->v_type != V_NUM || qisfrac(vp->v_num) ||
qisneg(vp->v_num) || zge31b(vp->v_num->num)) {
math_error("errcount argument out of range");
/*NOTREACHED*/
}
newmax = z1tol(vp->v_num->num);
zge31b(vp->v_num->num))
fprintf(stderr,
"Out-of-range arg for errmax ignored\n");
else
errmax = (int) ztoi(vp->v_num->num);
}
oldmax = set_errmax(newmax);
result.v_type = V_NUM;
result.v_num = itoq((long) oldmax);
@@ -4460,6 +4492,30 @@ f_errmax(int count, VALUE **vals)
}
static VALUE
f_stoponerror(int count, VALUE **vals)
{
int oldval;
VALUE *vp;
VALUE result;
oldval = stoponerror;
if (count > 0) {
vp = vals[0];
if (vp->v_type != V_NUM || qisfrac(vp->v_num) ||
zge31b(vp->v_num->num))
fprintf(stderr,
"Out-of-range arg for stoponerror ignored\n");
else
stoponerror = (int) ztoi(vp->v_num->num);
}
result.v_type = V_NUM;
result.v_num = itoq((long) oldval);
return result;
}
static VALUE
f_fclose(int count, VALUE **vals)
{
@@ -5935,8 +5991,7 @@ f_putenv(int count, VALUE **vals)
/* return putenv result */
result.v_type = V_NUM;
result.v_num = itoq((long) putenv(putenv_str));
free(putenv_str);
result.v_num = itoq((long) malloced_putenv(putenv_str));
return result;
}
@@ -6806,6 +6861,8 @@ static CONST struct builtin builtins[] = {
"digit at specified decimal place of number"},
{"digits", 1, 1, 0, OP_NOP, f_digits, 0,
"number of digits in number"},
{"display", 0, 1, 0, OP_NOP, 0, f_display,
"number of decimal digits for displaying numbers"},
{"dp", 2, 2, 0, OP_NOP, 0, f_dp,
"dot product of two vectors"},
{"epsilon", 0, 1, 0, OP_SETEPSILON, 0, 0,
@@ -7188,6 +7245,8 @@ static CONST struct builtin builtins[] = {
"seed the random() function"},
{"ssq", 1, IN, 0, OP_NOP, 0, f_ssq,
"sum of squares of values"},
{"stoponerror", 0, 1, 0, OP_NOP, 0, f_stoponerror,
"assign value to stoponerror flag"},
{"str", 1, 1, 0, OP_NOP, 0, f_str,
"simple value converted to string"},
{"strcat", 1,IN, 0, OP_NOP, 0, f_strcat,
@@ -7476,4 +7535,145 @@ showerrors(void)
}
/*
* malloced_putenv - Keep track of malloced environment variable storage
*
* given:
* str a malloced string which will be given to putenv
*
* returns:
* putenv() return value
*
* NOTE: The caller MUST pass a string that the caller has previously malloced.
*/
static int
malloced_putenv(char *str)
{
char *value; /* location of the value part of the str argument */
char *old_val; /* previously stored (or inherited) env value */
int found_cnt; /* number of active env_pool entries found */
struct env_pool *new; /* new e_pool */
int i;
/*
* firewall
*/
if (str == NULL) {
math_error("malloced_putenv given a NULL pointer!!");
/*NOTREACHED*/
}
if (str[0] == '=') {
math_error("malloced_putenv = is first character in string!!");
/*NOTREACHED*/
}
/*
* determine the place where getenv would return
*/
value = strchr(str, '=');
if (value == NULL) {
math_error("malloced_putenv = not found in string!!");
/*NOTREACHED*/
}
++value;
/*
* lookup for an existing environment value
*/
*(value-1) = '\0';
old_val = getenv(str);
*(value-1) = '=';
/*
* If we have the value in our environment, look for a
* previously malloced string and free it
*/
if (old_val != NULL && env_pool_cnt > 0) {
for (i=0, found_cnt=0;
i < env_pool_max && found_cnt < env_pool_cnt;
++i) {
/* skip an unused entry */
if (e_pool[i].getenv == NULL) {
continue;
}
++found_cnt;
/* look for the 1st match */
if (e_pool[i].getenv == value) {
/* found match, free the storage */
if (e_pool[i].putenv != NULL) {
free(e_pool[i].putenv);
}
e_pool[i].getenv = NULL;
--env_pool_cnt;
break;
}
}
}
/*
* ensure that we have room in the e_pool
*/
if (env_pool_max == 0) {
/* allocate an initial pool (with one extra guard value) */
new = (struct env_pool *)malloc((ENV_POOL_CHUNK+1) *
sizeof(struct env_pool));
if (new == NULL) {
math_error("malloced_putenv malloc failed");
/*NOTREACHED*/
}
e_pool = new;
env_pool_max = ENV_POOL_CHUNK;
for (i=0; i <= ENV_POOL_CHUNK; ++i) {
e_pool[i].getenv = NULL;
}
} else if (env_pool_cnt >= env_pool_max) {
/* expand the current pool (with one extra guard value) */
new = (struct env_pool *)realloc(e_pool,
(env_pool_max+ENV_POOL_CHUNK+1) *
sizeof(struct env_pool));
if (new == NULL) {
math_error("malloced_putenv realloc failed");
/*NOTREACHED*/
}
e_pool = new;
for (i=env_pool_max; i <= env_pool_max + ENV_POOL_CHUNK; ++i) {
e_pool[i].getenv = NULL;
}
env_pool_max += ENV_POOL_CHUNK;
}
/*
* store our data into the first e_pool entry
*/
for (i=0; i < env_pool_max; ++i) {
/* skip used entries */
if (e_pool[i].getenv != NULL) {
continue;
}
/* store in this free entry and stop looping */
e_pool[i].getenv = value;
e_pool[i].putenv = str;
++env_pool_cnt;
break;
}
if (i >= env_pool_max) {
math_error("malloced_putenv missed unused entry!!");
/*NOTREACHED*/
}
/*
* finally, do the putenv action
*/
return putenv(str);
}
#endif /* FUNCLIST */

2
hash.c
View File

@@ -604,7 +604,7 @@ hash_str(int type, char *str, HASH *state)
*/
return state;
}
/*
* hash_STR - hash a STRING

View File

@@ -8,7 +8,7 @@ Environment variables
If this variable does not exist, a compiled value
is used. Typically compiled in value is:
.:./lib:~/lib:${LIBDIR}/calc
.:./lib:~/lib:${LIBDIR}/calc:${LIBDIR}/custom
where ${LIBDIR} is usually:

View File

@@ -44,7 +44,7 @@
for and overview of the help system. The command:
help builtins
help builtin
provides information on built-in mathematical functions, whereas:
@@ -67,6 +67,10 @@
It contains information about differences between C and calc
that may surprize you.
To learn about calc library files that are shipped with calc, try:
help stdlib
A full and extensive overview of calc may be obtained by:
help full

View File

@@ -2,7 +2,22 @@ Calc command line
Calc has the following command line:
calc [-C] [-e] [-h] [-i] [-m mode] [-n] [-p] [-q] [-u] [calc_cmd ...]
calc [-c] [-C] [-d] [-e] [-h] [-i] [-m mode]
[-n] [-p] [-q] [-u] [-v] [calc_cmd ...]
-c Continue reading command lines even after an execution
error has caused the abandonment of a line.
For example:
calc read many_errors.cal
will cause calc to abort on the first error, whereas:
calc -c read many_errors.cal
will cause calc to try to process each line being read
despite the errors that it encounters.
-C Permit the execution of custom builtin functions. Without
this flag, calling the custom() builtin function will
@@ -12,6 +27,27 @@ Calc command line
are non-standard and that are not portable. Custom builtin
functions are disabled by default for this reason.
-d Disable the printing of the opening title. The printing
of library debug and informational messages is also disabled
as if config("lib_debug",0) had been executed.
For example:
calc 'read qtime; qtime(2)'
will output something like:
qtime(utc_hr_offset) defined
It's nearly ten past six.
whereas:
calc -d 'read qtime; qtime(2)'
will just say:
It's nearly ten past six.
-e Ignore any environment variables on startup. The
getenv() builtin will still return values, however.
@@ -19,7 +55,21 @@ Calc command line
is equivalent to the calc command help help. The help
facility is disabled unless the mode is 5 or 7. See -m.
-i Do not about if the error count exceeds maxerr().
-i Become interactive if possible. Be default, if calc_cmd
args are given, calc will execute them and exit. This flag
will cause calc to drop into interactive mode after the
commands are executed.
For example:
calc 2+5
will print the value 7 and exit whereas:
calc -i 2+5
will print the value 7 and prompt the user for more
calc commands.
-m mode
This flag sets the permission mode of calc. It
@@ -38,7 +88,7 @@ Calc command line
6 do not execute any program
7 allow everything (default mode)
If one wished to run calc from a privledged user, one
If one wished to run calc from a privileged user, one
might want to use -m 0 in an effort to make calc more
secure.
@@ -46,7 +96,7 @@ Calc command line
open. Files already open are not effected. Thus if one
wanted to use the -m 0 in an effort to make calc more
secure, but still wanted to read and write a specific
file, one might want to do:
file, one might want to do in sh, ksh, bash-like shells:
calc -m 0 3<a.file
@@ -59,25 +109,28 @@ Calc command line
given. The reading of key bindings is also disabled
when the mode disables opening of files for reading.
-n Use the new configutation defaults instead of the old
-n Use the new configuration defaults instead of the old
default classic defaults. This flag as the same effect
as executing config("all", "newcfg") at startup time.
-p Pipe processing is enabled by use of -p. For example:
echo "print 2^21701-1, 2^23209-1" | calc -p | fizzbin
calc -p '2^21701-1' | fizzbin
In pipe mode, calc does not prompt, does not print
leading tabs and does not print the initial header.
In pipe mode, calc does not prompt, does not print leading
tabs and does not print the initial header. The -p flag
overrides -i.
-q Disable the use of the $CALCRC startup scripts.
-u Disable buffering of stdin and stdout.
-v Print calc version number and exit.
Without `calc_cmd', calc operates interactively. If one or more
`calc_cmd' are given on the command line, calc will execute them and
exit. The printing of leading tabs on output is disabled as if
config("tab",0) had been executed.
exit. If -i is given, calc will attempt to become interactive
even of one or more `calc_cmd' are given on the command line.
Normally on startup, calc attempts to execute a collection of
library scripts. The environment variable $CALCRC (if non-existent
@@ -98,7 +151,8 @@ Calc command line
Calc treats all open files, other than stdin, stdout and
stderr as files available for reading and writing. One may
present calc with an already open file in the following way:
present calc with an already open file using sh, ksh or bash-like
shells is to:
calc 3<open_file 4<open_file2

View File

@@ -311,7 +311,7 @@ f_open(char *name, char *mode)
*/
if (!allow_read && !allow_write) {
/* no reads and no writes means no opens! */
if (start_done) {
if (run_state > RUN_PRE_BEGIN) {
fprintf(stderr,
"open of %s mode %s - %s\n", name, mode,
"open for read or write disallowed by -m\n");
@@ -319,7 +319,7 @@ f_open(char *name, char *mode)
return NULL;
} else if (!allow_read && strchr(mode, 'r') != NULL) {
/* reading new files disallowed */
if (start_done) {
if (run_state > RUN_PRE_BEGIN) {
fprintf(stderr,
"open of %s mode %s - %s\n", name, mode,
"open for read disallowed by -m\n");
@@ -330,7 +330,7 @@ f_open(char *name, char *mode)
strchr(mode, 'a') != NULL ||
strchr(mode, '+') != NULL)) {
/* writing new files disallowed */
if (start_done) {
if (run_state > RUN_PRE_BEGIN) {
fprintf(stderr,
"open of %s mode %s - %s\n", name, mode,
"open for write disallowed by -m\n");

View File

@@ -44,7 +44,7 @@ CALC_FILES= README bigprime.cal deg.cal ellip.cal lucas.cal lucas_chk.cal \
test2700.cal test3100.cal test3300.cal test3400.cal prompt.cal \
test3500.cal seedrandom.cal test4000.cal test4100.cal test4600.cal \
beer.cal hello.cal test5100.cal test5200.cal randombitrun.cal \
randomrun.cal xx_print.cal natnumset.cal
randomrun.cal xx_print.cal natnumset.cal qtime.cal
# These files are found (but not built) in the distribution
#

View File

@@ -1,10 +1,35 @@
# Copyright (c) 1999 David I. Bell and Landon Curt Noll
# Permission is granted to use, distribute, or modify this source,
# provided that this copyright notice remains intact.
To load a library, try:
The following calc library files are provided because they serve as
examples of how use the calc language, and/or because the authors thought
them to be useful!
read filename
You to not need to add the .cal extension to the filename. Calc
will search along the $CALCPATH (see ``help environment'').
Normally a library will simply define some functions. By default,
most libraries will print out a short message when thei are read.
For example:
> read lucas
lucas(h,n) defined
gen_u0(h,n,v1) defined
gen_v1(h,n) defined
ldebug(funct,str) defined
will cause calc to load and execute the 'lucas.cal' library.
Executing the library will cause several functions to be defined.
Executing the lucas function
> lucas(149,60)
1
> lucas(146,61)
0
shows that 149*2^60-1 is prime whereas 146*2^61-1 is not.
=-=
Calc library files are provided because they serve as examples of how use
the calc language, and/or because the authors thought them to be useful!
If you write something that you think is useful, please send it to:
@@ -12,7 +37,7 @@ If you write something that you think is useful, please send it to:
By convention, a lib file only defines and/or initializes functions,
objects and variables. (The regress.cal and testxxx.cal regression test
suite is an exception.) Also by convention, an additional usage message
suite is an exception.) Also by convention, an additional usage message
regarding important object and functions is printed.
If a lib file needs to load another lib file, it should use the -once
@@ -63,6 +88,10 @@ something like:
=-=
The following is a brief description of some of the calc library files
that are shipped with calc. See above for example of how to read in
and execute these files.
beer.cal
Calc's contribution to the 99 Bottles of Beer web page:
@@ -282,6 +311,13 @@ psqrt.cal
Calculate square roots modulo a prime
qtime.cal
qtime(utc_hr_offset)
Print the time as English sentence given the hours offset from UTC.
quat.cal
quat(a, b, c, d)
@@ -537,7 +573,7 @@ test3500.cal
testh(str, n, N, verbose)
test3500(verbose, n, N)
This script is used by regress.cal to test the functions frem,
This script is used by regress.cal to test the functions frem,
fcnt, gcdrem.
test4000.cal
@@ -648,3 +684,9 @@ xx_print.cal
error_print(a) defined
Demo for the xx_print object routines.
=-=
# Copyright (c) 1999 David I. Bell and Landon Curt Noll
# Permission is granted to use, distribute, or modify this source,
# provided that this copyright notice remains intact.

60
lib/qtime.cal Normal file
View File

@@ -0,0 +1,60 @@
/*
* qtime - Display time as English sentence
*
* usage:
* qtime(utc_hr_offset)
*
* utc_hr_offset Offset from UTC in hours.
*
* Written by: Klaus Alexander Seistrup <kseis@magnetic-ink.dk>
* With minor mods by: Landon Curt Noll <chongo@toad.com>
*
* See:
* http://www.magnetic-ink.dk/download/qtime.html
*
* for examples of qtime() written on other languages.
*/
/*
* qtime - Display time as English sentence
*/
define qtime(utc_hr_offset)
{
static mat hr[12] = {
"twelve", "one", "two", "three", "four", "five",
"six", "seven", "eight", "nine", "ten", "eleven"
};
static mat mn[7] = {
"", "five ", "ten ", "a quarter ", "twenty ", "twenty-five ", "half "
};
static mat ny[5] = {
"nearly ", "almost ", "", "just after ", "after "
};
static mat up[3] = {
"to ", "", "past "
};
local adj_mins = (((time() + utc_hr_offset*3600) % 86400) + 30) // 60 + 27;
local hours = (adj_mins // 60) % 12;
local minutes = adj_mins % 60;
local almost = minutes % 5;
local divisions = (minutes // 5) - 5;
local to_past_idx = divisions > 0 ? 1 : 0;
if (divisions < 0) {
divisions = -divisions;
to_past_idx = -1;
}
++to_past_idx;
/*
* Print the English sentence
*
* We avoid forward and back quotes just to show that the char()
* builtin function can be used in conjunction with a printf.
*/
printf("It%cs %s%s%s%s",
char(0x27), ny[almost], mn[divisions], up[to_past_idx], hr[hours]);
if (divisions == 0)
printf(" o%cclock", char(0x27));
printf (".\n");
}

View File

@@ -22,13 +22,13 @@ prob = 0; /* clear problem counter */
global junk; /* throw away value */
junk = errcount(0); /* clear error count */
junk = errmax(0x7fffffff); /* set maximum error very high */
junk = errmax(-1); /* prevent errcount from abouting */
global ecnt; /* expected value of errcount() */
ecnt = 0; /* clear expected errcount() value */
initcfg = config("all", "oldstd"); /* set config to startup default */
initcfg = config("lib_debug", -1); /* disable lib startup messages */
initcfg = config("lib_debug", -4); /* disable lib startup messages */
initcfg = config("calc_debug", 1); /* enable more internal debugging */
initcfg = config("all"); /* save state for later use */
@@ -4223,7 +4223,7 @@ define test_random()
/* test range interface some more */
tmp = srandom(state1);
print '5369: tmp = srandom(0)';
print '5369: tmp = srandom(state1)';
vrfy(random(-46,46) == -0x7, '5370: random(-46,46) == -0x7');
vrfy(random(21701,23209) == 23061,
'5371: random(21701,23209) == 23061');
@@ -7468,7 +7468,9 @@ read -once unitfrac;
print '9826: read -once unitfrac';
read -once varargs;
print '9827: read -once varargs';
print '9828: Ending read of selected calc libs';
read -once qtime;
print '9828: read -once qtime';
print '9829: Ending read of selected calc libs';
/*

View File

@@ -63,8 +63,8 @@ int new_std = FALSE; /* TRUE (-n) => use newstd configuration */
int abortlevel; /* current level of aborts */
BOOL inputwait; /* TRUE if in a terminal input wait */
jmp_buf jmpbuf; /* for errors */
int start_done = FALSE; /* TRUE => start up processing finished */
char *program = "calc"; /* our name */
run run_state = RUN_UNKNOWN; /* calc startup and run state */
char *program = "calc"; /* our name */
char cmdbuf[MAXCMD+1+1+1]; /* command line expression + "\n\0" + guard */
@@ -82,7 +82,9 @@ int allow_exec = TRUE; /* FALSE => may not execute any commands */
int p_flag = FALSE; /* TRUE => pipe mode */
int q_flag = FALSE; /* TRUE => don't execute rc files */
int u_flag = FALSE; /* TRUE => unbuffer stdin and stdout */
int d_flag = FALSE; /* TRUE => disable heading, lib_debug == 0 */
int c_flag = FALSE; /* TRUE => continue on error if permitted */
int i_flag = FALSE; /* TRUE => go interactive if permitted */
/*
* global values
@@ -94,11 +96,12 @@ char *home; /* $HOME or default */
char *pager; /* $PAGER or default */
char *shell; /* $SHELL or default */
int stdin_tty = FALSE; /* TRUE if stdin is a tty */
int interactive = FALSE; /* TRUE if interactive session (no cmd args) */
int post_init = FALSE; /* TRUE setjmp for math_error is readready */
int havecommands = FALSE; /* TRUE if have one or more cmd args */
int stoponerror = FALSE; /* >0 => stop, <0 => continue on error */
int post_init = FALSE; /* TRUE setjmp for math_error is ready */
int no_env = FALSE; /* TRUE (-e) => ignore env vars on startup */
int ign_errmax = FALSE; /* TRUE (-i) => ignore when errcount exceeds errmax */
int errmax = ERRMAX; /* if >= 0, maximum value for errcount */
NUMBER *epsilon_default; /* default allowed error for float calcs */
@@ -155,6 +158,20 @@ libcalc_call_me_first(void)
conf = config_copy(&oldstd);
}
/*
* -d turns off lib_debug
*/
if (d_flag) {
conf->lib_debug = 0;
}
/*
* -p turns off tab
*/
if (p_flag) {
conf->tab_ok = 0;
}
/*
* initialize
*/
@@ -163,6 +180,7 @@ libcalc_call_me_first(void)
/*
* ready to rock & roll ..
*/
run_state = RUN_PRE_BEGIN;
init_done = 1;
return;
}
@@ -229,10 +247,6 @@ reinitialize(void)
math_setfp(stdout);
resetscopes();
resetinput();
if (q_flag == FALSE && allow_read) {
q_flag = TRUE;
runrcfiles();
}
(void) openterminal();
}

View File

@@ -32,7 +32,6 @@ static VALUE oldvalue; /* previous calculation value */
static BOOL saveval = TRUE; /* to enable or disable saving */
static int calc_errno; /* most recent error-number */
static int errcount; /* counts calls to error_value */
static int errmax = ERRMAX; /* maximum for errcount without abort */
static BOOL go;
/*
@@ -2467,7 +2466,7 @@ o_return(void)
/*ARGSUSED*/
static void
o_jumpeq(FUNC *fp, BOOL *dojump)
o_jumpz(FUNC *fp, BOOL *dojump)
{
VALUE *vp;
int i; /* result of comparison */
@@ -2491,7 +2490,7 @@ o_jumpeq(FUNC *fp, BOOL *dojump)
/*ARGSUSED*/
static void
o_jumpne(FUNC *fp, BOOL *dojump)
o_jumpnz(FUNC *fp, BOOL *dojump)
{
VALUE *vp;
int i; /* result of comparison */
@@ -2513,6 +2512,20 @@ o_jumpne(FUNC *fp, BOOL *dojump)
}
/*
* jumpnn invokes a jump if top value points to a null value
*/
/*ARGSUSED*/
static void
o_jumpnn(FUNC *fp, BOOL *dojump)
{
if (stack->v_addr->v_type) {
*dojump = TRUE;
stack--;
}
}
/*ARGSUSED*/
static void
o_condorjump(FUNC *fp, BOOL *dojump)
@@ -3111,7 +3124,8 @@ o_quit(FUNC *fp, long index)
s = findstring(index);
cp = s->s_str;
}
if ((fp->f_name[0] == '*') && (fp->f_name[1] == '\0')) {
if (inputisterminal() && (fp->f_name[0] == '*')
&& (fp->f_name[1] == '\0')) {
if (cp)
printf("%s\n", cp);
hist_term();
@@ -3126,6 +3140,8 @@ o_quit(FUNC *fp, long index)
printf("%s\n", cp);
else
printf("Quit statement executed\n");
if (!inputisterminal() && fp->f_name[0] == '*')
closeinput();
go = FALSE;
}
@@ -3243,7 +3259,7 @@ error_value(int e)
calc_errno = e;
if (e > 0)
errcount++;
if (errcount > errmax && !ign_errmax) {
if (errmax >= 0 && errcount > errmax) {
math_error("Error %d caused errcount to exceed errmax", e);
/*NOTREACHED*/
}
@@ -3281,21 +3297,6 @@ set_errcount(int e)
}
/*
* set_errno - return and set errno
*/
int
set_errmax(int e)
{
int res;
res = errmax;
if (e >= 0)
errmax = e;
return res;
}
/*
* Fill a newly created matrix at v1 with copies of value at v2.
*/
@@ -3427,8 +3428,8 @@ static struct opcode opcodes[MAX_OPCODE+1] = {
{o_duplicate, OPNUL, "DUPLICATE"}, /* duplicate top value */
{o_pop, OPNUL, "POP"}, /* pop top value */
{o_return, OPRET, "RETURN"}, /* return value of function */
{o_jumpeq, OPJMP, "JUMPEQ"}, /* jump if value zero */
{o_jumpne, OPJMP, "JUMPNE"}, /* jump if value nonzero */
{o_jumpz, OPJMP, "JUMPZ"}, /* jump if value zero */
{o_jumpnz, OPJMP, "JUMPNZ"}, /* jump if value nonzero */
{o_jump, OPJMP, "JUMP"}, /* jump unconditionally */
{o_usercall, OPTWO, "USERCALL"}, /* call a user function */
{o_getvalue, OPNUL, "GETVALUE"}, /* convert address to value */
@@ -3531,7 +3532,8 @@ static struct opcode opcodes[MAX_OPCODE+1] = {
{o_hashop, OPNUL, "HASHOP"}, /* binary hash op */
{o_backslash, OPNUL, "BACKSLASH"}, /* unary backslash op */
{o_setminus, OPNUL, "SETMINUS"}, /* binary backslash op */
{o_plus, OPNUL, "PLUS"} /* unary + op */
{o_plus, OPNUL, "PLUS"}, /* unary + op */
{o_jumpnn, OPJMP, "JUMPNN"} /* jump if non-null */
};
@@ -3695,7 +3697,8 @@ calculate(FUNC *fp, int argcount)
freevalue(&locals[i]);
if (locals != localtable)
free(locals);
printf("\t\"%s\": line %ld\n", funcname, funcline);
if (conf->calc_debug & 2)
printf("\t\"%s\": line %ld\n", funcname, funcline);
while (stack > beginstack)
freevalue(stack--);
funcname = oldname;
@@ -3751,11 +3754,11 @@ dumpop(unsigned long *pc)
case OP_INDEXADDR:
printf(" %ld %ld\n", pc[0], pc[1]);
return 3;
case OP_PRINT: case OP_JUMPEQ: case OP_JUMPNE: case OP_JUMP:
case OP_PRINT: case OP_JUMPZ: case OP_JUMPNZ: case OP_JUMP:
case OP_CONDORJUMP: case OP_CONDANDJUMP: case OP_CASEJUMP:
case OP_INITSTATIC: case OP_MATCREATE: case OP_OBJCREATE:
case OP_SHOW: case OP_ELEMINIT: case OP_ELEMADDR:
case OP_ELEMVALUE:
case OP_ELEMVALUE: case OP_JUMPNN:
printf(" %ld\n", *pc);
return 2;
case OP_NUMBER: case OP_IMAGINARY:

View File

@@ -38,8 +38,8 @@
#define OP_DUPLICATE 23L /* duplicate top value on stack */
#define OP_POP 24L /* pop top value from stack */
#define OP_RETURN 25L /* return value of function */
#define OP_JUMPEQ 26L /* jump if top value is zero */
#define OP_JUMPNE 27L /* jump if top value is nonzero */
#define OP_JUMPZ 26L /* jump if top value is zero */
#define OP_JUMPNZ 27L /* jump if top value is nonzero */
#define OP_JUMP 28L /* jump unconditionally */
#define OP_USERCALL 29L /* call a user-defined function */
#define OP_GETVALUE 30L /* convert address to value */
@@ -143,7 +143,8 @@
#define OP_BACKSLASH 128L /* unary backslash */
#define OP_SETMINUS 129L /* binary backslash */
#define OP_PLUS 130L /* unary + */
#define MAX_OPCODE 130L /* highest legal opcode */
#define OP_JUMPNN 131L /* jump if top value is non-null */
#define MAX_OPCODE 131L /* highest legal opcode */
/*

View File

@@ -1142,7 +1142,7 @@ initstrings(void)
/*
* addstring is called only from token.c
* When called, len is length if string including '\0'
* When called, len is length of string including '\0'
*/
long
addstring(char *str, long len)

View File

@@ -458,6 +458,7 @@ eatstring(int quotechar)
}
memcpy(str + totlen, buf, len);
totlen += len;
len = 0;
}
}
curtoken.t_strindex = addstring(str, totlen + len);
@@ -643,6 +644,10 @@ scanerror(int skip, char *fmt, ...)
va_end(ap);
fprintf(stderr, "%s\n", buf);
/* bail out if continuation not permitted */
if ((!c_flag && !stoponerror) || stoponerror > 0)
longjmp(jmpbuf, 1);
/* bail out if too many errors */
if (conf->maxscancount > 0 && errorcount > conf->maxscancount) {
fputs("Too many scan errors, compilation aborted.\n", stderr);

View File

@@ -213,7 +213,6 @@ extern BOOL precvalue(VALUE *v1, VALUE *v2);
extern VALUE error_value(int e);
extern int set_errno(int e);
extern int set_errcount(int e);
extern int set_errmax(int e);
extern long countlistitems(LIST *lp);
extern void addlistitems(LIST *lp, VALUE *vres);
extern void addlistinv(LIST *lp, VALUE *vres);

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997 David I. Bell
* Copyright (c) 1999 David I. Bell
* Permission is granted to use, distribute, or modify this source,
* provided that this copyright notice remains intact.
*
@@ -12,7 +12,7 @@
#define MAJOR_VER 2 /* major version */
#define MINOR_VER 11 /* minor version */
#define MAJOR_PATCH 0 /* patch level or 0 if no patch */
#define MINOR_PATCH "6" /* test number or empty string if no patch */
#define MINOR_PATCH "7.3" /* test number or empty string if no patch */
/*
* calc version constants
@@ -80,7 +80,3 @@ version(void)
*/
return stored_version;
}
/* END CODE */

106
zrandom.c
View File

@@ -1571,6 +1571,12 @@ static RANDOM random_pregen[BLUM_PREGEN] = {
};
/*
* forward static declarations
*/
static void zfree_random(ZVALUE z);
/*
* zsrandom1 - seed the Blum generator 1 arg style
*
@@ -1647,7 +1653,7 @@ zsrandom1(CONST ZVALUE seed, BOOL need_ret)
do {
/* free temp storage */
if (last_r.v != NULL) {
zfree(last_r);
zfree_random(last_r);
}
/*
@@ -1657,10 +1663,10 @@ zsrandom1(CONST ZVALUE seed, BOOL need_ret)
last_r = r;
zsquaremod(last_r, blum.n, &r);
} while (zrel(r, last_r) > 0);
zfree(blum.r);
zfree_random(blum.r);
blum.r = r;
/* free temp storage */
zfree(last_r);
zfree_random(last_r);
/*
* reserved seed
@@ -1741,7 +1747,7 @@ zsrandom2(CONST ZVALUE seed, CONST ZVALUE newn)
math_error("srandom small newn must be [1,20]");
/*NOTREACHED*/
}
zfree(blum.n);
zfree_random(blum.n);
zcopy(random_pregen[set-1].n, &blum.n);
blum.loglogn = random_pregen[set-1].loglogn;
blum.mask = random_pregen[set-1].mask;
@@ -1750,7 +1756,7 @@ zsrandom2(CONST ZVALUE seed, CONST ZVALUE newn)
* reset initial seed as well if seed is 0
*/
if (ziszero(seed)) {
zfree(blum.r);
zfree_random(blum.r);
zcopy(random_pregen[set-1].r, &blum.r);
/*
@@ -1785,7 +1791,7 @@ zsrandom2(CONST ZVALUE seed, CONST ZVALUE newn)
* of two primes.
*/
/* load modulus */
zfree(blum.n);
zfree_random(blum.n);
zcopy(newn, &blum.n);
/*
@@ -1894,11 +1900,11 @@ zsrandom4(CONST ZVALUE seed, CONST ZVALUE ip, CONST ZVALUE iq, long trials)
/*
* form the Blum modulus
*/
zfree(blum.n);
zfree_random(blum.n);
zmul(p, q, &blum.n);
/* free temp storage */
zfree(p);
zfree(q);
zfree_random(p);
zfree_random(q);
/*
* form the loglogn and mask
@@ -2045,7 +2051,7 @@ zrandomskip(long cnt)
/* turn the Blum-Blum-Shub crank */
zsquaremod(blum.r, blum.n, &new_r);
zfree(blum.r);
zfree_random(blum.r);
blum.r = new_r;
cnt -= blum.loglogn;
}
@@ -2057,7 +2063,7 @@ zrandomskip(long cnt)
/* turn the Blum-Blum-Shub crank */
zsquaremod(blum.r, blum.n, &new_r);
zfree(blum.r);
zfree_random(blum.r);
blum.r = new_r;
/* fill the buffer with the unused bits */
@@ -2197,7 +2203,7 @@ zrandom(long cnt, ZVALUE *res)
* turn the Blum-Blum-Shub crank
*/
zsquaremod(blum.r, blum.n, &new_r);
zfree(blum.r);
zfree_random(blum.r);
blum.r = new_r;
/* peal off the bottom loglogn bits */
blum.buffer = (blum.r.v[0] & mask);
@@ -2228,7 +2234,7 @@ zrandom(long cnt, ZVALUE *res)
*/
/* turn the Blum-Blum-Shub crank */
zsquaremod(blum.r, blum.n, &new_r);
zfree(blum.r);
zfree_random(blum.r);
blum.r = new_r;
/* peal off the bottom loglogn bits */
blum.buffer = (blum.r.v[0] & mask);
@@ -2282,13 +2288,13 @@ zrandomrange(CONST ZVALUE low, CONST ZVALUE high, ZVALUE *res)
*/
zsub(high, low, &range);
if (zisone(range)) {
zfree(range);
zfree_random(range);
*res = low;
return;
}
zsub(range, _one_, &rangem1);
bitlen = 1+zhighbit(rangem1);
zfree(rangem1);
zfree_random(rangem1);
/*
* generate a random value between [0, diff)
@@ -2302,7 +2308,7 @@ zrandomrange(CONST ZVALUE low, CONST ZVALUE high, ZVALUE *res)
rval.v = NULL;
do {
if (rval.v != NULL) {
zfree(rval);
zfree_random(rval);
}
zrandom(bitlen, &rval);
} while (zrel(rval, range) >= 0);
@@ -2312,8 +2318,8 @@ zrandomrange(CONST ZVALUE low, CONST ZVALUE high, ZVALUE *res)
* which is the range [low, high)
*/
zadd(rval, low, res);
zfree(rval);
zfree(range);
zfree_random(rval);
zfree_random(range);
}
@@ -2341,8 +2347,8 @@ irandom(long s)
itoz(s, &z1);
zrandomrange(_zero_, z1, &z2);
res = ztoi(z2);
zfree(z1);
zfree(z2);
zfree_random(z1);
zfree_random(z2);
return res;
}
@@ -2377,12 +2383,20 @@ randomcopy(CONST RANDOM *state)
if (state->r.v == NULL) {
ret->r.v = NULL;
} else {
zcopy(state->r, &ret->r);
if (state->r.v == h_rdefvec) {
ret->r.v = state->r.v;
} else {
zcopy(state->r, &ret->r);
}
}
if (state->n.v == NULL) {
ret->n.v = NULL;
} else {
zcopy(state->n, &ret->n);
if (state->n.v == h_ndefvec) {
ret->n.v = state->n.v;
} else {
zcopy(state->n, &ret->n);
}
}
/*
@@ -2414,12 +2428,8 @@ randomfree(RANDOM *state)
}
/* free the values */
if (state->n.v != h_ndefvec) {
zfree(state->n);
}
if (state->r.v != h_rdefvec) {
zfree(state->r);
}
zfree_random(state->n);
zfree_random(state->r);
/* free it if it is not pre-defined */
state->seeded = 0;
@@ -2505,9 +2515,43 @@ randomprint(CONST RANDOM *state, int flags)
void
random_libcalc_cleanup(void)
{
/* free if we are seeded now */
if (blum.seeded) {
randomfree(&blum);
/* free our state - let zfree_random protect the default state */
randomfree(&blum);
return;
}
/*
* zfree_random - perform a zfree if we are not trying to free static data
*
* given:
* z the ZVALUE to zfree(z) if not pointing to static data
*/
static void
zfree_random(ZVALUE z)
{
if (z.v != h_ndefvec && z.v != h_rdefvec && z.v != h_rdefvec_2 &&
z.v != h_nvec01 && z.v != h_rvec01 &&
z.v != h_nvec02 && z.v != h_rvec02 &&
z.v != h_nvec03 && z.v != h_rvec03 &&
z.v != h_nvec04 && z.v != h_rvec04 &&
z.v != h_nvec05 && z.v != h_rvec05 &&
z.v != h_nvec06 && z.v != h_rvec06 &&
z.v != h_nvec07 && z.v != h_rvec07 &&
z.v != h_nvec08 && z.v != h_rvec08 &&
z.v != h_nvec09 && z.v != h_rvec09 &&
z.v != h_nvec10 && z.v != h_rvec10 &&
z.v != h_nvec11 && z.v != h_rvec11 &&
z.v != h_nvec12 && z.v != h_rvec12 &&
z.v != h_nvec13 && z.v != h_rvec13 &&
z.v != h_nvec14 && z.v != h_rvec14 &&
z.v != h_nvec15 && z.v != h_rvec15 &&
z.v != h_nvec16 && z.v != h_rvec16 &&
z.v != h_nvec17 && z.v != h_rvec17 &&
z.v != h_nvec18 && z.v != h_rvec18 &&
z.v != h_nvec19 && z.v != h_rvec19 &&
z.v != h_nvec20 && z.v != h_rvec20) {
zfree(z);
}
return;
}