Compare commits

..

51 Commits

Author SHA1 Message Date
Landon Curt Noll
f3913609ea Release calc version 2.11.0t10.5 2017-05-21 15:38:36 -07:00
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
Landon Curt Noll
025b5e58d6 Release calc version 2.11.0t10.3 2017-05-21 15:38:35 -07:00
Landon Curt Noll
160f4102ab Release calc version 2.11.0t10.2 2017-05-21 15:38:34 -07:00
Landon Curt Noll
306e031f03 Release calc version 2.11.0t10.1.4 2017-05-21 15:38:34 -07:00
Landon Curt Noll
6cfe9696ce Release calc version 2.11.0t10.1.3 2017-05-21 15:38:34 -07:00
Landon Curt Noll
97ed812cb9 Release calc version 2.11.0t10.1.2 2017-05-21 15:38:34 -07:00
Landon Curt Noll
6254c4a14c Release calc version 2.11.0t10.1.1 2017-05-21 15:38:34 -07:00
Landon Curt Noll
c7c0de97f2 Release calc version 2.11.0t10.1 2017-05-21 15:38:34 -07:00
Landon Curt Noll
96c34adee3 Release calc version 2.11.0t10 2017-05-21 15:38:33 -07:00
Landon Curt Noll
86c8e6dcf1 Release calc version 2.11.0t9.4.5 2017-05-21 15:38:33 -07:00
Landon Curt Noll
58d32c68f9 Release calc version 2.11.0t9.4.4 2017-05-21 15:38:33 -07:00
Landon Curt Noll
7d0b761de3 Release calc version 2.11.0t9.4.3 2017-05-21 15:38:33 -07:00
Landon Curt Noll
82ff31f246 Release calc version 2.11.0t9.4.2 2017-05-21 15:38:32 -07:00
Landon Curt Noll
7cb0a77c25 Release calc version 2.11.0t9.4.1 2017-05-21 15:38:32 -07:00
Landon Curt Noll
afb0e5c32a Release calc version 2.11.0t9.4 2017-05-21 15:38:32 -07:00
Landon Curt Noll
df32e3956d Release calc version 2.11.0t9.3.1 2017-05-21 15:38:32 -07:00
Landon Curt Noll
75e742c716 Release calc version 2.11.0t9.2 2017-05-21 15:38:32 -07:00
Landon Curt Noll
1b42111665 Release calc version 2.11.0t9.1.1 2017-05-21 15:38:32 -07:00
Landon Curt Noll
ea6b3904be Release calc version 2.11.0t9.1 2017-05-21 15:38:31 -07:00
Landon Curt Noll
f3fceff1b6 Release calc version 2.11.0t9 2017-05-21 15:38:31 -07:00
Landon Curt Noll
69d4a17187 Release calc version 2.11.0t8.10 2017-05-21 15:38:31 -07:00
Landon Curt Noll
a99a3400e7 Release calc version 2.11.0t8.9.1 2017-05-21 15:38:31 -07:00
Landon Curt Noll
9b6c308b42 Release calc version 2.11.0t8.9 2017-05-21 15:38:31 -07:00
Landon Curt Noll
8927373965 Release calc version 2.11.0t8.8 2017-05-21 15:38:30 -07:00
Landon Curt Noll
478d68fca9 Release calc version 2.11.0t8.7 2017-05-21 15:38:30 -07:00
Landon Curt Noll
e6e2556893 Release calc version 2.11.0t8.6 2017-05-21 15:38:30 -07:00
Landon Curt Noll
a7e363da8b Release calc version 2.11.0t8.5 2017-05-21 15:38:30 -07:00
Landon Curt Noll
8db10967e8 Release calc version 2.11.0t8.4 2017-05-21 15:38:30 -07:00
Landon Curt Noll
49be672338 Release calc version 2.11.0t8.3 2017-05-21 15:38:30 -07:00
Landon Curt Noll
a7d401cd65 Release calc version 2.11.0t8.2 2017-05-21 15:38:29 -07:00
Landon Curt Noll
5cc680fe42 Release calc version 2.11.0t8.1 2017-05-21 15:38:29 -07:00
Landon Curt Noll
2c72ea9339 Release calc version 2.11.0t8 2017-05-21 15:38:29 -07:00
Landon Curt Noll
0ffc341b10 Release calc version 2.11.0t7.5 2017-05-21 15:38:29 -07:00
Landon Curt Noll
2251281027 Release calc version 2.11.0t7.4 2017-05-21 15:38:29 -07:00
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
Landon Curt Noll
b54d8fc510 Release calc version 2.11.0t6 2017-05-21 15:38:27 -07:00
Landon Curt Noll
8cabbd6fb4 Release calc version 2.11.0t5.2 2017-05-21 15:38:27 -07:00
Landon Curt Noll
ea64a95b90 Release calc version 2.11.0t5.1 2017-05-21 15:38:27 -07:00
Landon Curt Noll
f60cbd24b2 Release calc version 2.11.0t5 2017-05-21 15:38:27 -07:00
Landon Curt Noll
97e9429000 Release calc version 2.11.0t4 2017-05-21 15:38:27 -07:00
342 changed files with 12249 additions and 6449 deletions

195
BUGS
View File

@@ -20,34 +20,30 @@ configuration, try backing them out and see if things get better.
To be sure that your version of calc is up to date, check out:
http://reality.sgi.com/chongo/calc/calc-download.html
http://reality.sgi.com/chongo/tech/comp/calc/calc-download.html
The calc web site is located at:
http://reality.sgi.com/chongo/calc
http://reality.sgi.com/chongo/tech/comp/calc/index.html
=-=
If you have tried all of the above and things still are not right,
then it may be time to send in a bug report. You can send bug reports to:
calc-tester@postofc.corp.sgi.com
calc-bugs at postofc dot corp dot sgi dot com
[[ Replace 'at' with @, 'dot' is with . and remove the spaces ]]
When you send your report, please include the following information:
* a description of the problem
* the version of calc you are using (if you cannot get calc
it to run, then send us the 4 #define lines from version.c)
* if you modified calc from an official patch, send me the mods you made
* the type of system you were using
* the type of compiler you were using
* any compiler warnings or erros that you saw
* any compiler warnings or errors that you saw
* cd to the calc source directory, and type:
make debug > debug.out 2>&1 (sh, ksh, bash users)
@@ -62,89 +58,130 @@ Stack traces from core dumps are useful to send as well.
Send any comments, compiler warning messages, suggestions and most
importantly, fixes (in the form of a context diff patch) to:
calc-tester@postofc.corp.sgi.com
calc-tester at postofc dot corp dot sgi dot com
[[ Replace 'at' with @, 'dot' is with . and remove the spaces ]]
You should use the above calc-bugs address for bug reports, if you are
not currently a member of the calc-tester mailing list.
=-=
Known problems or mis-features:
Known bugs:
* Many of and SEE ALSO sections of help files
for builtins are either inconsistent or missing information.
* Calc does not support the #! exec method. For example of the
following is placed in an executable file (assume the path to
calc is correct) called /tmp/xyzzy:
* Many of the LIBRARY sections are incorrect now that libcalc.a
contains most of the calc system.
#!/usr/local/bin/calc
/*
* comment
*/
print 2+3;
* 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.
Will result in '"tmp" is undefined' and '"xyzzy" is undefined'
error messages because calc considers $0 as an expression to
evaluate.
* On a Dec Alpha, make check for version 2.11.0t1 core dumps:
* The following file:
From vandermj@molbio.sbphrd.com Fri Sep 24 06:15:28 1999
Subject: Re: calc version 2.11.0t1
Date: Fri, 24 Sep 1999 09:15:02 -0400
/* this is bugdemo.cal */
x = eval(prompt(">>> "));
print x;
It dies as follows:
when executed as:
calc read bugdemo.cal
will obtain a prompt from the terminal, print the value but leave
the terminal in a 'bad' state, as if stty -icanon -echo -echoe
had been executed.
* 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.
=-=
Problems with known work-a-rounds:
* There is a bug in gcc-2.95 that causes calc, when compiled with -O2,
to fail the regression test. The work-a-round is to compile with -O
or to use gcc-2.96 or later.
* Solaris cc somtimes barfs while compiling zrand.c. In particular, calc
barfs on on the SVAL macro. The work-a-round is to use the Solaric cc
Makefile set sets -DFORCE_STDC. I.e,:
CCWARN=
CCOPT= ${DEBUG} ${NO_SHARED}
CCMISC= -DFORCE_STDC
#
CFLAGS= ${CCWARN} ${CCOPT} ${CCMISC}
ICFLAGS= ${CCWARN} ${CCMISC}
#
LCFLAGS=
LDFLAGS= ${NO_SHARED} ${LD_NO_SHARED}
ILDFLAGS=
#
LCC= cc
CC= ${PURIFY} ${LCC}
* There is a bug in some versions of the Dec/Compaq cc for the Alpha
where the following:
#include <stdio.h>
#define SVAL(a,b) (unsigned long)(0x ## a ## b ## ULL)
main(){SVAL(b8a8aeb0,8168eadc);}
fails because it puts a space inside the concatenated hex. Calc
has code that is affected by this bug. This bug has been reported
to Compaq and may be fixed in the future. A work-a-round is to
compile with cc -std0 or to use a later version of their compiler.
* On a Digital UNIX V4.0F (Rev. 1229) on a 500 Mhz 21264, make check
dies a horrible death starting in test 600 and 622 gives 100s of
messages for calc version 2.11.0t9.4 using the Dec's cc with -O2:
600: Beginning test_bignums
601: muldivcheck 1
**** abc != acb: 602: muldivcheck 2
**** acb != bac: 602: muldivcheck 2
...
**** t4 != a4: 622: algcheck 1
**** t5 != a5: 622: algcheck 1
**** t6 != a6: 622: algcheck 1
**** t4 != a4: 622: algcheck 1
...
1802: a = surd(2,3)
1803: a == surd(2,3)
1804: surd_value(a) == 2+3i
Segmentation fault
dbx shows:
signal Segmentation fault at [objcall:155 +0xc,0x1200507b4] index = oap->actions[action];
(dbx) where
> 0 objcall(action = 14, v1 = 0x1400203d0, v2 = 0x1400203e0, v3 = (nil)) ["obj.c":155, 0x1200507b4]
1 comparevalue(v1 = 0x1400203d0, v2 = 0x1400203e0) ["value.c":2329, 0x12007f250]
2 o_eq() ["opcodes.c":2659, 0x12003728c]
3 calculate(fp = 0x14007fce0) ["opcodes.c":3614, 0x12003942c]
4 o_usercall(fp = 0x14007fce0, index = 39, argcount = 0) ["opcodes.c":2602, 0x120037080]
5 calculate(fp = 0x14003bfa0) ["opcodes.c":3622, 0x120039488]
6 evaluate(nestflag = 14) ["codegen.c":210, 0x120028768]
7 getcommands(toplevel = 536864560) ["codegen.c":158, 0x1200285bc]
8 getcommands(toplevel = 536864560) ["codegen.c":122, 0x1200284dc]
9 main() ["calc.c":279, 0x12001f61c]
it finally hangs at test 2000.
Michel van der List reports that he was using the Dec compiler.
The work-a-round is to compile calc without the optimizer. If this
happens to you, try compiling without -O and without -O2. I.e., in
the Makefile, set:
However On 25-Sep-99 9:18, Ernest Bowen wrote:
DEBUG= -g
Last night I downloaded 2.11.0t1 and without changing Makefile
or anything else did a make and make check. Absolutely no
reported errors or warnings and the check "passed all tests".
The machine I'm using is a Dec 20 alpha running Digitial
UNIX V4.0B (Rev 564).
* 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.
Ernest Bowen was using gcc.
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:
We definitely want to hunt down this Dec's cc compiler issue. It
could very well be that gcc is letting something slide where as
Dec's cc compiler is compiling it faithfully into core dumping code.
The fault could very well be the calc code and not the compiler.
Any more information on calc core dumps compiled with Dec's cc compiler
would be most appreciated!
* To compile calc using the Solaris cc, the -Xc flag is required.
Unfortunately this change results in the loss of 'long long' and
the resulting code runs slower.
Dr.D.J.Picton <dave@aps5.ph.bham.ac.uk> reports that -Xc is
required for at compiling zrand.c.
* Calc compiled with Solaris cc -Xc results in some test failures:
CALCPATH=./lib ./calc -i -q read regress 2>&1 | nawk -f check.awk
**** Non-true result (0): 7120: sha(sha(isqrt(2e1000)==0x6db8d9cf0b018b8f9cbbf5aa1edb8066d19e1bb0
**** Non-true result (0): 7122: sha(sha("this is", 7^19-8, ..., "hash")) == 0x21e4...
**** Non-true result (0): 7124: sha(z) == 0x36dcca3e51865c30a2cf738023cda446f1368340
**** Non-true result (0): 7209: sha1(sha1("this is",7^19-8,"a composit",3i+4.5,"hash")) == ...
**** Non-true result (0): 7211: sha1(z) == 0xc19e7317675dbf71e293b4c41e117169e9da5b6f
**** Non-true result (0): 7227: sha1(sha1(isqrt(2e1000)))==0x6852a1365c51050c3d039e3c5d9cf29c12283ef4
**** Non-true result (0): 7310: md5(md5("this is", 7^19-8, "a composit", 3i+4.5, "hash")) == ...
**** Non-true result (0): 7312: md5(z) == 0x63d2b2fccae2de265227c30b05abb6b5
**** Non-true result (0): 7328: md5(md5(isqrt(2e1000))) == 0xe56ac4b8cad869e738a04fedc97058f3
**** 9 error(s) found \/++\/
9999: Ending regression tests
LCC="cc -xarch=v9"
CCWARN="-DFORCE_STDC -w"
DEBUG="-fast -xarch=v9"

909
CHANGES

File diff suppressed because it is too large Load Diff

View File

@@ -4,13 +4,11 @@ Installing calc in 4 easy steps:
Here are some Makefile hints:
Select a compiler set by commenting in the appropriate
set of cc options. As shipped the Makefile assumes
a gcc-like environment such as Linux.
If a more appropriate cc set if found below, comment
out the Linux set and comment in that set or edit
the gcc set or the common cc set as needed.
Select a compiler set by commenting in the appropriate set
of cc options. As shipped the Makefile assumes a gcc-like
environment such as Linux. If a more appropriate cc set if
found below, comment out the Linux set and comment in that
set or edit the gcc set or the common cc set as needed.
You may or may not need RANLIB when building libraries.
As shipped the Makefile assumes RANLIB is needed.
@@ -21,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.
@@ -40,14 +33,18 @@ Installing calc in 4 easy steps:
make all
==> We are interested in any compiler warnings (and errors) that
you may find. See the BUGS file if you find any.
you may find. See the BUGS file if you find any compiler
warning or errors.
3) test calc:
make check
==> If you run into problems, follow the instructions in the BUGS file
==> If you run into problems, follow the BUGS file instructions.
4) install calc:
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.

1042
Makefile

File diff suppressed because it is too large Load Diff

135
README
View File

@@ -1,73 +1,100 @@
# 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.
Dear calc user,
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
NOTE: This is an old historic README. We recommend that you
read README.FIRST and HOWTO.INSTALL for more info.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
See the HOWTO.INSTALL file for information on how to build and install calc.
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.
To be sure that your version of calc is up to date, check out:
-dbell-
http://reality.sgi.com/chongo/tech/comp/calc/calc-download.html
p.s. By Landon Curt Noll:
We are interested in any/all feedback on recent versions of calc.
In particular we would like to hear about:
Building calc in 3 easy steps:
* compiler warnings
* compile problems
* regression test problems (try: make check)
* special compile flags/options that you needed
* Makefile problems
* help file problems
* misc nits and typos
1) Look at the makefile, and adjust it to suit your needs.
We would like to offer a clean compile across a wide verity of platforms,
so if you can test on several, so much the better!
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<<<==
If you run into problems, see the BUGS file.
=-=
For further reading:
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.
LIBRARY
explains how programs can use libcalc.a to take advantage
of the calc multi-precision routines.
For list of help topics:
> help
For overview of calc overview:
> help intro
> help overview
> help command
> help define
> help statement
> help variable
> help usage
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
current wish list for calc
help/wishlist
CHANGES
recent changes to calc
or run:
BUGS
known bugs, mis-features and how to report problems
calc help todo
calc help wishlist
help/full
full set of calc documentation
for a wish/todo list. Code contributions are welcome.
=-=
David I. Bell dbell@auug.org.au
chongo@toad.com <Landon Curt Noll -- chongo@toad.com> /\../\
To join the calc-tester mailing list. Send a request to:
calc-tester-request at postofc dot corp dot sgi dot com
[[ Replace 'at' with @, 'dot' is with . and remove the spaces ]]
Your message body (not the subject) should consist of:
subscribe calc-tester address
end
name your_full_name
where ``address'' is your EMail address and ``your_full_name'' is
your full name.
Calc bug reports, however should be sent to:
calc-bugs at postofc dot corp dot sgi dot com
[[ Replace 'at' with @, 'dot' is with . and remove the spaces ]]
but see the BUGS file first.
The calc web site is located at:
http://reality.sgi.com/chongo/tech/comp/calc/

View File

@@ -1,54 +0,0 @@
Dear calc user,
See the HOWTO.INSTALL file for information on how to build and install calc.
To be sure that your version of calc is up to date, check out:
http://reality.sgi.com/chongo/calc/calc-download.html
We are interested in any/all feedback on recent versions of calc.
In particular we would like to hear about:
* compiler warnings
* compile problems
* regression test problems (try: make check)
* special compile flags/options that you needed
* Makefile problems
* help file problems
* misc nits and typos
We would like to offer a clean compile across a wide verity of platforms,
so if you can test on several, so much the better!
If you run into problems, see the BUGS file.
=-=
See the file:
help/todo
or run:
calc 'help todo'
for a wish/todo list. Code contributions are welcome.
=-=
To join the calc-tester mailing list. Send a request to:
calc-tester-request@postofc.corp.sgi.com
Your message body (not the subject) should consist of:
subscribe calc-tester address
end
name your_full_name
where ``address'' is your EMail address and ``your_full_name'' is
your full name.
The calc web site is located at:
http://reality.sgi.com/chongo/calc

117
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 (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;
if (count++ == 0) {
printf("Name Arguments\n---- ---------\n");
}
printf("%-12s %-2d\n", fp->f_name, fp->f_paramcount);
count++;
math_fmt("%-12s\t%-2d\n", namestr(&funcnames,
index), 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");
}
}
@@ -114,7 +138,9 @@ beginfunc(char *name, BOOL newflag)
fp->f_localcount = 0;
fp->f_opcodecount = 0;
fp->f_savedvalue.v_type = V_NULL;
fp->f_name = namestr(&funcnames, newindex);
fp->f_savedvalue.v_subtype = V_NOSUBTYPE;
newname = namestr(&funcnames, newindex);
fp->f_name = newname;
curfunc = fp;
initlocals();
initlabels();
@@ -135,15 +161,17 @@ endfunc(void)
{
register FUNC *fp; /* function just finished */
unsigned long size; /* size of just created function */
long index;
if (oldop != OP_RETURN) {
addop(OP_UNDEF);
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;
}
@@ -163,16 +191,24 @@ endfunc(void)
size += dumpop(&fp->f_opcodes[size]);
}
}
if ((inputisterminal() && conf->lib_debug & LIBDBG_STDIN_FUNC) ||
(!inputisterminal() && conf->lib_debug & LIBDBG_FILE_FUNC)) {
printf("%s(", newname);
for (index = 0; index < fp->f_paramcount; index++) {
if (index)
putchar(',');
printf("%s", paramname(index));
}
printf(") ");
if (functions[newindex])
printf("re");
printf("defined\n");
}
if (functions[newindex]) {
freenumbers(functions[newindex]);
free(functions[newindex]);
if (inputisterminal() || conf->lib_debug >= 0)
printf("%s() redefined\n", fp->f_name);
}
else if (inputisterminal() || conf->lib_debug >= 0)
printf("%s() defined\n", fp->f_name);
functions[newindex] = fp;
objuncache();
}
@@ -220,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;
}
@@ -228,7 +264,8 @@ rmuserfunc(char *name)
return;
freenumbers(functions[index]);
free(functions[index]);
if (!inputisterminal() && conf->lib_debug >= 0)
if ((inputisterminal() && conf->lib_debug & LIBDBG_STDIN_FUNC) ||
(!inputisterminal() && conf->lib_debug & LIBDBG_FILE_FUNC))
printf("%s() undefined\n", name);
functions[index] = NULL;
}
@@ -240,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);
@@ -261,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;
}
}
}
@@ -438,6 +490,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;
}
@@ -445,7 +502,8 @@ addop(long op)
fp->f_opcodecount -= diff;
oldop = OP_NOP;
oldoldop = OP_NOP;
fprintf(stderr, "%ld: unused value ignored\n",
fprintf(stderr,
"Line %ld: unused value ignored\n",
linenumber());
return;
}
@@ -518,8 +576,7 @@ addop(long op)
qfree(q);
fp->f_opcodes[count - 2] = OP_ZERO;
fp->f_opcodecount--;
}
else if (qisone(q)) {
} else if (qisone(q)) {
qfree(q);
fp->f_opcodes[count - 2] = OP_ONE;
fp->f_opcodecount--;
@@ -622,5 +679,3 @@ addoplabel(long op, LABEL *label)
addop(op);
uselabel(label);
}
/* END CODE */

View File

@@ -3,7 +3,10 @@
*
* This file was written by:
*
* Landon Curt Noll (chongo@toad.com) chongo <was here> /\../\
* Landon Curt Noll
* http://reality.sgi.com/chongo/
*
* chongo <was here> /\../\
*
* This code has been placed in the public domain. Please do not
* copyright this code.

View File

@@ -17,7 +17,7 @@
#ifdef HAVE_MALLOC_H
# include <malloc.h>
#else
# if defined(__STDC__) && __STDC__ != 0
#if defined(FORCE_STDC) || (defined(__STDC__) && __STDC__ != 0) || defined(__cplusplus)
extern void *malloc();
extern void *realloc();
extern void free();
@@ -36,7 +36,7 @@
# if defined(HAVE_NEWSTR)
extern void *memcpy();
extern void *memset();
# if defined(__STDC__) && __STDC__ != 0
#if defined(FORCE_STDC) || (defined(__STDC__) && __STDC__ != 0) || defined(__cplusplus)
extern size_t strlen();
# else
extern long strlen();
@@ -65,7 +65,7 @@ extern int strcmp();
#if !defined(HAVE_MEMMOVE)
# undef CALC_SIZE_T
# if defined(__STDC__) && __STDC__ != 0
#if defined(FORCE_STDC) || (defined(__STDC__) && __STDC__ != 0) || defined(__cplusplus)
# define CALC_SIZE_T size_t
# else
# define CALC_SIZE_T long

View File

@@ -47,8 +47,8 @@ associndex(ASSOC *ap, BOOL create, long dim, VALUE *indices)
QCKHASH hash;
int i;
if (dim <= 0) {
math_error("No dimensions for indexing association");
if (dim < 0) {
math_error("Negative dimension for indexing association");
/*NOTREACHED*/
}
@@ -57,7 +57,7 @@ associndex(ASSOC *ap, BOOL create, long dim, VALUE *indices)
* so that we can first select the correct hash chain, and
* also so we can quickly compare each element for a match.
*/
hash = (QCKHASH)0;
hash = FNV1_32_BASIS;
for (i = 0; i < dim; i++)
hash = hashvalue(&indices[i], hash);
@@ -80,6 +80,7 @@ associndex(ASSOC *ap, BOOL create, long dim, VALUE *indices)
*/
if (!create) {
val.v_type = V_NULL;
val.v_subtype = V_NOSUBTYPE;
return &val;
}
@@ -216,6 +217,27 @@ assocfindex(ASSOC *ap, long index)
}
/*
* Returns the list of indices for an association element with specified
* double-bracket index.
*/
LIST *
associndices(ASSOC *ap, long index)
{
ASSOCELEM *ep;
LIST *lp;
int i;
ep = elemindex(ap, index);
if (ep == NULL)
return NULL;
lp = listalloc();
for (i = 0; i < ep->e_dim; i++)
insertlistlast(lp, &ep->e_indices[i]);
return lp;
}
/*
* Compare two associations to see if they are identical.
* Returns TRUE if they are different.
@@ -244,8 +266,7 @@ assoccmp(ASSOC *ap1, ASSOC *ap2)
hash = ep1->e_hash;
dim = ep1->e_dim;
for (ep2 = ap2->a_table[hash % size2]; ;
ep2 = ep2->e_next)
{
ep2 = ep2->e_next) {
if (ep2 == NULL)
return TRUE;
if (ep2->e_hash != hash)
@@ -282,8 +303,7 @@ assoccopy(ASSOC *oldap)
for (oldhi = 0; oldhi < oldap->a_size; oldhi++) {
for (oldep = oldap->a_table[oldhi]; oldep;
oldep = oldep->e_next)
{
oldep = oldep->e_next) {
ep = (ASSOCELEM *) malloc(ELEMSIZE(oldep->e_dim));
if (ep == NULL) {
math_error("Cannot allocate association element");
@@ -292,6 +312,7 @@ assoccopy(ASSOC *oldap)
ep->e_dim = oldep->e_dim;
ep->e_hash = oldep->e_hash;
ep->e_value.v_type = V_NULL;
ep->e_value.v_subtype = V_NOSUBTYPE;
for (i = 0; i < ep->e_dim; i++)
copyvalue(&oldep->e_indices[i], &ep->e_indices[i]);
copyvalue(&oldep->e_value, &ep->e_value);
@@ -447,8 +468,7 @@ assocprint(ASSOC *ap, long max_print)
((ap->a_count == 1) ? "" : "s"));
for (index = 0; ((index < max_print) && (index < ap->a_count));
index++)
{
index++) {
ep = elemindex(ap, index);
if (ep == NULL)
continue;
@@ -489,5 +509,3 @@ compareindices(VALUE *v1, VALUE *v2, long dim)
return TRUE;
}
/* END CODE */

View File

@@ -4,7 +4,7 @@
* provided that this copyright notice remains intact.
*
* By: Ernest Bowen and Landon Curt Noll
* ernie@neumann.une.edu.au and chongo@toad.com
* ernie@neumann.une.edu.au and http://reality.sgi.com/chongo/
*/
#include <stdio.h>
@@ -330,6 +330,7 @@ copyblk2mat(BLOCK *blk, long ssi, long num, MATRIX *dmat, long dsi)
i = num;
while (i-- > 0) {
vp->v_type = V_NUM;
vp->v_subtype = V_NOSUBTYPE;
vp->v_num = itoq((long) *op++);
vp++;
}

35
block.c
View File

@@ -28,11 +28,9 @@
* Happy bit twiddling,
*
* Landon Curt Noll
* http://reality.sgi.com/chongo/
*
* chongo@toad.com
* ...!{pyramid,sun,uunet}!hoptoad!chongo
*
* chongo was here /\../\
* chongo <was here> /\../\
*/
@@ -106,7 +104,7 @@ blkalloc(int len, int chunk)
/*
* return BLOCK
*/
if (conf->calc_debug > 0) {
if (conf->calc_debug & CALCDBG_BLOCK) {
blkchk(nblk);
}
return nblk;
@@ -147,13 +145,11 @@ blk_free(BLOCK *blk)
* debug time, we plan to call this function often. Once we are satisfied,
* we will normally call this code only in a few places.
*
* This function is normally called whenever the following builtins are called:
* If "calc_debug" has the bit corresponding to CALCDBG_BLOCK set, this
* function is called during execution of the following builtins:
*
* alloc(), realloc(), free()
*
* unless the "calc_debug" is set to -1. If "calc_debug" is > 0, then
* most blk builtins will call this function.
*
* given:
* blk - the BLOCK to check
*
@@ -168,7 +164,7 @@ blkchk(BLOCK *blk)
/*
* firewall - general sanity check
*/
if (conf->calc_debug == -1) {
if ((conf->calc_debug & CALCDBG_BLOCK) == 0) {
/* do nothing when debugging is disabled */
return;
}
@@ -233,7 +229,7 @@ blkrealloc(BLOCK *blk, int newlen, int newchunk)
/*
* firewall
*/
if (conf->calc_debug != -1) {
if (conf->calc_debug & CALCDBG_BLOCK) {
blkchk(blk);
}
@@ -292,7 +288,7 @@ blkrealloc(BLOCK *blk, int newlen, int newchunk)
memset(blk->data, 0, blk->maxsize);
}
blk->datalen = 0;
if (conf->calc_debug > 0) {
if (conf->calc_debug & CALCDBG_BLOCK) {
blkchk(blk);
}
return blk;
@@ -323,7 +319,7 @@ blkrealloc(BLOCK *blk, int newlen, int newchunk)
/*
* return realloced type
*/
if (conf->calc_debug > 0) {
if (conf->calc_debug & CALCDBG_BLOCK) {
blkchk(blk);
}
return blk;
@@ -351,7 +347,7 @@ blktrunc(BLOCK *blk)
/*
* firewall
*/
if (conf->calc_debug != -1) {
if (conf->calc_debug & CALCDBG_BLOCK) {
blkchk(blk);
}
@@ -372,7 +368,7 @@ blktrunc(BLOCK *blk)
/*NOTREACHED*/
}
blk->data[0] = (USB8)0;
if (conf->calc_debug > 0) {
if (conf->calc_debug & CALCDBG_BLOCK) {
blkchk(blk);
}
return;
@@ -483,7 +479,7 @@ blk_print(BLOCK *blk)
BOOL havetail;
USB8 *ptr;
/* XXX - use the config parameters for better print control */
/* XXX - should use the config parameters for better print control */
printf("chunksize = %d, maxsize = %d, datalen = %d\n\t",
(int)blk->blkchunk, (int)blk->maxsize, (int)blk->datalen);
@@ -516,10 +512,10 @@ nblock_print(NBLOCK *nblk)
printf("chunksize = %d, maxsize = %d, datalen = %d\n\t",
(int)blk->blkchunk, (int)blk->maxsize, (int)blk->datalen);
printf("NULL");
}
else
} else {
blk_print(blk);
}
}
/*
@@ -560,8 +556,7 @@ reallocnblock(int id, int len, int chunk)
math_error("Allocation failed");
/*NOTREACHED*/
}
}
else if (newsize != oldsize) {
} else if (newsize != oldsize) {
newdata = realloc(blk->data, newsize);
if (newdata == NULL) {
math_error("Reallocation failed");

View File

@@ -28,11 +28,9 @@
* Happy bit twiddling,
*
* Landon Curt Noll
* http://reality.sgi.com/chongo/
*
* chongo@toad.com
* ...!{pyramid,sun,uunet}!hoptoad!chongo
*
* chongo was here /\../\
* chongo <was here> /\../\
*/

574
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,31 +36,17 @@
#include <stdlib.h>
#endif
/*
* external and static 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 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 char *program; /* our name */
extern char cmdbuf[]; /* command line expression */
extern char *version(void); /* return version string */
#include "have_strdup.h"
#if !defined(HAVE_STRDUP)
# define strdup(x) calc_strdup((CONST char *)(x))
#endif /* HAVE_STRDUP */
/*
* forward static functions
* static definitions and functions
*/
static void intint(int arg); /* interrupt routine */
static void script_args(int *argc, char ***argv, char **shellfile);
/*
@@ -70,31 +55,39 @@ static void intint(int arg); /* interrupt routine */
int
main(int argc, char **argv)
{
static char *str; /* current option string or expression */
int want_defhelp = 0; /* 1=> we only want the default help */
long i;
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 */
char *p;
long i;
/*
* parse args
*/
program = argv[0];
argc--;
argv++;
while ((argc > 0) && (**argv == '-')) {
for (str = &argv[0][1]; *str; str++) switch (*str) {
/* 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)
allow_custom = TRUE;
break;
#else
fprintf(stderr,
"Calc was built with custom functions "
"disabled, -C usage is disallowed\n");
#else /* CUSTOM */
/*
* we are too early in processing to call
* libcalc_call_me_last() - nothing to cleanup
*/
fprintf(stderr,
"%s: calc was built with custom functions "
"disabled, -C usage is disallowed\n", program);
exit(1);
#endif /* CUSTOM */
case 'e':
@@ -104,36 +97,22 @@ main(int argc, char **argv)
want_defhelp = 1;
break;
case 'i':
ign_errmax = TRUE;
i_flag = TRUE;
break;
case 'm':
if (argv[0][2]) {
p = &argv[0][2];
} else if (argc > 1) {
p = argv[1];
argc--;
argv++;
} else {
fprintf(stderr, "-m requires an arg\n");
if (optarg[1] != '\0' || *optarg<'0' || *optarg>'7') {
/*
* we are too early in processing to
* call libcalc_call_me_last()
* nothing to cleanup
*/
fprintf(stderr,
"%s: unknown -m arg\n", program);
exit(1);
}
if (p[1] != '\0' || *p < '0' || *p > '7') {
fprintf(stderr, "unknown -m arg\n");
/*
* we are too early in processing to
* call libcalc_call_me_last()
* nothing to cleanup
*/
exit(1);
}
allow_read = (((*p-'0') & 04) > 0);
allow_write = (((*p-'0') & 02) > 0);
allow_exec = (((*p-'0') & 01) > 0);
allow_read = (((*optarg-'0') & 04) > 0);
allow_write = (((*optarg-'0') & 02) > 0);
allow_exec = (((*optarg-'0') & 01) > 0);
break;
case 'n':
new_std = TRUE;
@@ -147,47 +126,97 @@ 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':
printf("%s (version %s)\n",
CALC_TITLE, version());
/*
* we are too early in processing to call
* libcalc_call_me_last() - nothing to cleanup
*/
printf("%s (version %s)\n", CALC_TITLE, version());
exit(0);
default:
case 'D':
/*
* parse the -D optarg
*
* Could be calc_debug
* or calc_debug:lib_debug
* or calc_debug:lib_debug:user_debug
*/
calc_debug = optarg;
p = strchr(optarg, ':');
if (p != NULL) {
*p = '\0';
lib_debug = p+1;
p = strchr(lib_debug, ':');
if (p != NULL) {
*p = '\0';
user_debug = p+1;
}
}
break;
case 's':
/*
* we are too early in processing to call
* libcalc_call_me_last() - nothing to cleanup
*/
fprintf(stderr,
"usage: %s [-C] [-e] [-h] [-i] [-m mode] [-n] [-p]\n",
"%s: -s may only be used in a calc shell script\n",
program);
fprintf(stderr, "\t[-q] [-u] [calc_cmd ...]\n");
exit(1);
default:
/*
* we are too early in processing to call
* libcalc_call_me_last() - nothing to cleanup
*/
fprintf(stderr,
"usage: %s [-c] [-C] [-d] [-e] [-h] [-i] [-m mode]\n"
"\t[-D calc_debug[:lib_debug:[user_debug]]]\n"
"\t[-n] [-p] [-q] [-u] [-v] [[--] calc_cmd ...]\n",
program);
exit(1);
}
argc--;
argv++;
}
havecommands = (optind < argc);
/*
* look at the length of any trailing command args
*
* We make room for the trailing '\0\n' as well as an extra guard byte.
*/
for (cmdlen=0, i=optind; i < argc; ++i) {
/* argument + space separator */
cmdlen += strlen(argv[i]) + 1;
}
if (i > MAXCMD) {
/*
* we are too early in processing to call
* libcalc_call_me_last() - nothing to cleanup
*/
fprintf(stderr,
"%s: command in arg list is too long\n", program);
exit(1);
}
/*
* We will form a command the remaining args separated by spaces.
*/
cmdbuf[0] = '\0';
str = cmdbuf;
while (--argc >= 0) {
i = (long)strlen(*argv);
if (i+3 >= MAXCMD) {
fprintf(stderr, "command in arg list too long\n");
/*
* we are too early in processing to call
* libcalc_call_me_last() - nothing to cleanup
*/
exit(1);
if (optind < argc) {
strcpy(cmdbuf, argv[optind]);
cmdlen = strlen(argv[optind]);
for (i=optind+1; i < argc; ++i) {
cmdbuf[cmdlen++] = ' ';
strcpy(cmdbuf+cmdlen, argv[i]);
cmdlen += strlen(argv[i]);
}
*str++ = ' ';
strcpy(str, *argv++);
str += i;
str[0] = '\n';
str[1] = '\0';
cmdbuf[cmdlen++] = '\n';
cmdbuf[cmdlen] = '\0';
}
str = cmdbuf;
/*
* unbuffered mode
@@ -201,8 +230,9 @@ 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 (conf->calc_debug & CALCDBG_TTY)
printf("DEBUG: stdin_tty is %d\n", stdin_tty);
if (want_defhelp) {
givehelp(DEFAULTCALCHELP);
libcalc_call_me_last();
@@ -212,41 +242,27 @@ main(int argc, char **argv)
/*
* if allowed or needed, print version and setup bindings
*/
if (*str == '\0') {
/*
* check for pipe mode and/or non-tty stdin
*/
if (!p_flag) {
stdin_tty = isatty(0); /* assume stdin is on fd 0 */
}
/*
* empty string arg is no string
*/
str = NULL;
/*
* 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)) {
case HIST_NOFILE:
fprintf(stderr,
"Cannot open bindings file \"%s\", %s.\n",
calcbindings, "fancy editing disabled");
"%s: Cannot open bindings file \"%s\", "
"fancy editing disabled.\n",
program, calcbindings);
break;
case HIST_NOTTY:
fprintf(stderr,
"Cannot set terminal modes, %s.\n",
"fancy editing disabled");
"%s: Cannot set terminal modes, "
"fancy editing disabled\n", program);
break;
}
}
}
/*
* establish error longjump point with initial conditions
@@ -256,53 +272,164 @@ 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
* (re)establish the interrupt handler
*/
if (str || !stdin_tty) {
if (q_flag == FALSE && allow_read) {
runrcfiles();
q_flag = TRUE;
}
if (str)
(void) openstring(str);
else
(void) openterminal();
start_done = TRUE;
getcommands(FALSE);
libcalc_call_me_last();
exit(0);
}
}
/* if in arg mode, we should not get here */
if (str) {
libcalc_call_me_last();
exit(1);
}
(void) signal(SIGINT, intint);
/*
* process commands
* execute calc code based on the run state
*/
if (!start_done) {
reinitialize();
if (run_state == RUN_BEGIN) {
if (!q_flag && allow_read) {
if (conf->calc_debug & CALCDBG_RUNSTATE)
printf("DEBUG: run_state from %s to %s\n",
run_state_name(run_state),
run_state_name(RUN_RCFILES));
run_state = RUN_RCFILES;
runrcfiles();
}
(void) signal(SIGINT, intint);
start_done = TRUE;
if (conf->calc_debug & CALCDBG_RUNSTATE)
printf("DEBUG: run_state from %s to %s\n",
run_state_name(run_state),
run_state_name(RUN_PRE_CMD_ARGS));
run_state = RUN_PRE_CMD_ARGS;
}
while (run_state == RUN_RCFILES) {
fprintf(stderr, "Error in rcfiles\n");
if ((c_flag && !stoponerror) || stoponerror < 0) {
getcommands(FALSE);
if (inputlevel() == 0) {
closeinput();
runrcfiles();
if (conf->calc_debug & CALCDBG_RUNSTATE)
printf("DEBUG: run_state from %s to %s\n",
run_state_name(run_state),
run_state_name(RUN_PRE_CMD_ARGS));
run_state = RUN_PRE_CMD_ARGS;
} else {
closeinput();
}
} else {
if ((havecommands && !i_flag) || !stdin_tty) {
if (conf->calc_debug & CALCDBG_RUNSTATE)
printf("DEBUG: run_state from %s to %s\n",
run_state_name(run_state),
run_state_name(RUN_EXIT_WITH_ERROR));
run_state = RUN_EXIT_WITH_ERROR;
} else {
if (conf->calc_debug & CALCDBG_RUNSTATE)
printf("DEBUG: run_state from %s to %s\n",
run_state_name(run_state),
run_state_name(RUN_PRE_CMD_ARGS));
run_state = RUN_PRE_CMD_ARGS;
}
}
}
/* XXX - if shellfile != NULL process shellfile here */
if (run_state == RUN_PRE_CMD_ARGS) {
if (havecommands) {
if (conf->calc_debug & CALCDBG_RUNSTATE)
printf("DEBUG: run_state from %s to %s\n",
run_state_name(run_state),
run_state_name(RUN_CMD_ARGS));
run_state = RUN_CMD_ARGS;
(void) openstring(cmdbuf, (long) strlen(cmdbuf));
getcommands(FALSE);
closeinput();
}
if (conf->calc_debug & CALCDBG_RUNSTATE)
printf("DEBUG: run_state from %s to %s\n",
run_state_name(run_state),
run_state_name(RUN_PRE_TOP_LEVEL));
run_state = RUN_PRE_TOP_LEVEL;
}
while (run_state == RUN_CMD_ARGS) {
fprintf(stderr, "Error in commands\n");
if ((c_flag && !stoponerror) || stoponerror < 0) {
getcommands(FALSE);
if (inputlevel() == 0)
if (conf->calc_debug & CALCDBG_RUNSTATE)
printf("DEBUG: run_state from %s to %s\n",
run_state_name(run_state),
run_state_name(RUN_PRE_TOP_LEVEL));
run_state = RUN_PRE_TOP_LEVEL;
closeinput();
} else {
closeinput();
if (!stdin_tty || !i_flag || p_flag) {
if (conf->calc_debug & CALCDBG_RUNSTATE)
printf("DEBUG: run_state from %s to %s\n",
run_state_name(run_state),
run_state_name(RUN_EXIT_WITH_ERROR));
run_state = RUN_EXIT_WITH_ERROR;
} else {
if (conf->calc_debug & CALCDBG_RUNSTATE)
printf("DEBUG: run_state from %s to %s\n",
run_state_name(run_state),
run_state_name(RUN_PRE_TOP_LEVEL));
run_state = RUN_PRE_TOP_LEVEL;
}
}
}
if (run_state == RUN_PRE_TOP_LEVEL) {
if (stdin_tty && ((havecommands && !i_flag) || p_flag)) {
if (conf->calc_debug & CALCDBG_RUNSTATE)
printf("DEBUG: run_state from %s to %s\n",
run_state_name(run_state),
run_state_name(RUN_EXIT));
run_state = RUN_EXIT;
} else {
if (stdin_tty) {
reinitialize();
} else {
resetinput();
openterminal();
}
if (conf->calc_debug & CALCDBG_RUNSTATE)
printf("DEBUG: run_state from %s to %s\n",
run_state_name(run_state),
run_state_name(RUN_TOP_LEVEL));
run_state = RUN_TOP_LEVEL;
getcommands(TRUE);
}
}
while (run_state == RUN_TOP_LEVEL) {
if ((c_flag && !stoponerror) || stoponerror < 0) {
getcommands(TRUE);
if (!inputisterminal())
closeinput();
} else {
if (stdin_tty) {
reinitialize();
getcommands(TRUE);
} else {
if (conf->calc_debug & CALCDBG_RUNSTATE)
printf("DEBUG: run_state from %s to %s\n",
run_state_name(run_state),
run_state_name(RUN_EXIT_WITH_ERROR));
run_state = RUN_EXIT_WITH_ERROR;
}
}
}
/*
* all done
*/
libcalc_call_me_last();
/* exit(0); */
return 0;
return (run_state == RUN_EXIT_WITH_ERROR ||
run_state == RUN_UNKNOWN) ? 1 : 0;
}
@@ -339,7 +466,8 @@ math_error(char *fmt, ...)
if (funcname && (*funcname != '*'))
fprintf(stderr, "\"%s\": ", funcname);
if (funcline && ((funcname && (*funcname != '*')) || !inputisterminal()))
if (funcline && ((funcname && (*funcname != '*')) ||
!inputisterminal()))
fprintf(stderr, "line %ld: ", funcline);
va_start(ap, fmt);
vsprintf(buf, fmt, ap);
@@ -349,7 +477,8 @@ math_error(char *fmt, ...)
if (post_init) {
longjmp(jmpbuf, 1);
} else {
fprintf(stderr, "no jmpbuf jumpback point - ABORTING!!!\n");
fprintf(stderr, "It is too early provide a command line prompt "
"so we must simply exit. Sorry!\n");
/*
* don't call libcalc_call_me_last() -- we might loop
* and besides ... this is an unusual internal error case
@@ -357,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;
}

64
calc.h
View File

@@ -10,23 +10,27 @@
#if !defined(__CALC_H__)
#define __CALC_H__
#include <setjmp.h>
#include "value.h"
#include "have_const.h"
/*
* Configuration definitions
*/
#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 */
#define PATHSIZE 1024 /* maximum length of path name */
#define MAX_CALCRC 1024 /* maximum length of $CALCRC */
#define HOMECHAR '~' /* char which indicates home directory */
#define DOTCHAR '.' /* char which indicates current directory */
#define PATHCHAR '/' /* char which separates path components */
@@ -37,7 +41,6 @@
#define SYMBOLSIZE 256 /* maximum symbol name size */
#define MAXINDICES 20 /* maximum number of indices for objects */
#define MAXLABELS 100 /* maximum number of user labels in function */
#define MAXOBJECTS 10 /* maximum number of object types */
#define MAXSTRING 1024 /* maximum size of string constant */
#define MAXSTACK 1000 /* maximum depth of evaluation stack */
#define MAXFILES 20 /* maximum number of opened files */
@@ -58,6 +61,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.
*/
@@ -110,7 +115,7 @@ extern void trimconstants(void);
/*
* Input routines.
*/
extern int openstring(char *str);
extern int openstring(char *str, long num);
extern int openterminal(void);
extern int opensearchfile(char *name, char *pathlist, char *exten, int reopen_ok);
extern char *nextline(void);
@@ -119,12 +124,13 @@ extern void reread(void);
extern void resetinput(void);
extern void setprompt(char *);
extern BOOL inputisterminal(void);
extern int inputlevel(void);
extern long calclevel(void);
extern char *inputname(void);
extern long linenumber(void);
extern void runrcfiles(void);
extern void closeinput(void);
/*
* Other routines.
*/
@@ -137,22 +143,42 @@ extern void givehelp(char *type);
extern void libcalc_call_me_first(void);
extern void libcalc_call_me_last(void);
extern void showerrors(void);
extern char *calc_strdup(CONST char *);
/*
* 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 BOOL abort_now; /* TRUE => try to go interactive */
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,15 +189,29 @@ 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_BEGIN = 0, /* calc execution starts */
RUN_RCFILES = 1, /* rc files being evaluated */
RUN_PRE_CMD_ARGS = 2, /* prepare to evaluate cmd args */
RUN_CMD_ARGS = 3, /* cmd args being evaluated */
RUN_PRE_TOP_LEVEL = 4, /* prepare to start top level activity */
RUN_TOP_LEVEL = 5, /* running at top level */
RUN_EXIT = 6, /* normal exit from calc */
RUN_EXIT_WITH_ERROR = 7 /* exit with error */
} run;
extern run run_state;
extern char *run_state_name(run state);
/*
* calc version information

596
calc.man
View File

@@ -1,46 +1,226 @@
.\"
.\" 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 [ -D\ \&calc_debug[:lib_debug:[user_debug]] ]
.br
.in +5n
.RB [ \-e ]
.RB [ \-h ]
.RB [ \-i ]
.RB [ \-m\ \&mode ]
.RB [ \-n ]
.RB [ \-p ]
.RB [ \-q ]
.RB [ \-u ]
.RB [ \-v ]
.br
.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
.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
calc read many_errors.cal
.fi
.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.
.sp 1
By default, calc startup scripts ($CALCRC) are silently
ignored if not found.
This flag will report missing
startup scripts unless
.B \-d
is also given.
.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
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
This flag disables the reporting of missing calc
startup scripts ($CALCRC).
.TP
.BR -D " calc_debug[:lib_debug:[user_debug]]"
Force the initial value of config("calc_debug"),
config("lib_debug") and config("user_debug").
.sp 1
The : separated strings are interpreted as signed 32 bit values.
After an optional leading sign a leading zero indicates octal
conversion, and a leading ``0x'' or ``0X'' hexadecimal
conversion. Otherwise, decimal conversion is assumed.
.sp 1
By default,
.I calc_debug
is 0,
.I lib_debug
is 3 and
.I lib_debug
is 0.
.sp 1
For more information use the following
.B calc
command:
.sp 1
.in +5n
.nf
help config
.fi
.in -5n
.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.
.I 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
@@ -51,140 +231,166 @@ to that of the \fRchmod(1)\fP octal mode:
6 do not execute any program
7 allow everything (default mode)
.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
If one wished to run
.B calc
from a privileged user, one might want to use
.BR \-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
.BR \-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 +405,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 +428,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 +466,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 +487,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 +509,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 +538,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,19 +550,32 @@ 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
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.
.sp
.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
The Calc primary mirror, calc mailing list and calc bug report
processing is performed by Landon Curt Noll.
.sp
Landon Curt Noll maintains the master reference source, performs
release control functions as well as other calc maintenance functions.
.sp
Thanks for suggestions and encouragement from Peter Miller,
Neil Justusson, and Landon Noll.
@@ -378,46 +608,74 @@ 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
.nf
calc-tester at postofc dot corp dot sgi dot com
[[ Replace 'at' with @, 'dot' is with . and remove the spaces ]]
.fi
.in -0.5i
.sp
Landon Noll maintains the official calc ftp archive at:
.sp
Bug reports are sent to:
.in +0.5i
ftp://ftp.uu.net/pub/calc
.nf
calc-bugs at postofc dot corp dot sgi dot com
[[ Replace 'at' with @, 'dot' is with . and remove the spaces ]]
.fi
.in -0.5i
.sp
Alpha test versions, complete with bugs, untested code and
experimental features may be fetched (if you are brave) under:
See the
.I BUGS
source file or use the
.I calc
command:
.sp
.in +0.5i
http://reality.sgi.com/chongo/calc/
.nf
help bugs
.fi
.in -0.5i
.sp
One may join the calc testing group by sending a request to:
for more information about bug reporting.
.sp
Landon Noll maintains the the
.B calc
web site is located at:
.sp
.in +0.5i
calc-tester-request@postofc.corp.sgi.com
http://reality.sgi.com/chongo/tech/comp/calc/
.in -0.5i
.sp
One may join the
.B calc
testing group by sending a request to:
.sp
.in +0.5i
.nf
calc-tester-request at postofc dot corp dot sgi dot com
[[ Replace 'at' with @, 'dot' is with . and remove the spaces ]]
.fi
.in -0.5i
.sp
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

@@ -1,123 +0,0 @@
/*
* errno - Determine how to declare errno, sys_errlist and sys_nerr
*
* On most machines: errno sys_errlist and sys_nerr are declared
* by either <stdio.h> and/or <errno.h>. But some systems declare
* them somewhere else or do not declare them at all!
*
* If the system were doing a proper job in headers, this should declare them:
*
* #include <stdio.h>
* #include <errno.h>
*
* But one some systems one must explicitly declare them as:
*
* extern int errno;
* extern const char *const sys_errlist[];
* extern int sys_nerr;
*
* and on some old systems they must be explicitly and incorrectly declared as:
*
* extern int errno;
* extern char *sys_errlist[];
* extern int sys_nerr;
*
* The purpose of this utility is try and find the right way to declare
* them and to output the middle of a header file called calc_errno.h.
*/
/*
* Copyright (c) 1999 by Landon Curt Noll. All Rights Reserved.
*
* Permission to use, copy, modify, and distribute this software and
* its documentation for any purpose and without fee is hereby granted,
* provided that the above copyright, this permission notice and text
* this comment, and the disclaimer below appear in all of the following:
*
* supporting documentation
* source copies
* source works derived from this source
* binaries derived from this source or from derived source
*
* LANDON CURT NOLL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
* EVENT SHALL LANDON CURT NOLL BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*
* chongo was here /\../\
*/
#include <stdio.h>
#if defined(TRY_ERRNO_NO_DECL)
# include <errno.h>
#endif /* TRY_ERRNO_NO_DECL */
int
main(void)
{
#if defined(TRY_ERRNO_NO_DECL)
printf("/*\n");
printf(" * The following comments were produced by calc_errno\n");
printf(" * in an effort to see if these values were correctly\n");
printf(" * declared when calc_errno.c was compiled.\n");
printf(" */\n\n");
printf("/* Initially errno is %d */\n", errno);
printf("/* There are %d entries in sys_errlist[] */\n", sys_nerr);
printf("/* The 2nd sys_errlist entry is \"%s\" */\n\n", sys_errlist[1]);
printf("/*\n");
printf(" * Based on the above, calc_errno now knows\n");
printf(" * how to declare errno and friends.\n");
printf(" */\n\n");
printf("#include <stdio.h>\n");
printf("#include <errno.h>\n");
#elif defined(TRY_ERRNO_OLD_DECL)
extern int errno; /* last system error */
extern char *sys_errlist[]; /* system error messages */
extern int sys_nerr; /* number of system errors*/
printf("/*\n");
printf(" * The following comments were produced by calc_errno\n");
printf(" * in an effort to see if these values were correctly\n");
printf(" * declared when calc_errno.c was compiled.\n");
printf(" */\n\n");
printf("/* Initially errno is %d */\n", errno);
printf("/* There are %d entries in sys_errlist[] */\n", sys_nerr);
printf("/* The 2nd sys_errlist entry is \"%s\" */\n\n", sys_errlist[1]);
printf("/*\n");
printf(" * Based on the above, calc_errno now knows\n");
printf(" * how to declare errno and friends.\n");
printf(" */\n\n");
printf("extern int errno;\t\t/* last system error */\n");
printf("extern char *sys_errlist[];\t"
"/* system error messages */\n");
printf("extern int sys_nerr;\t\t/* number of system errors*/\n");
#else /* assume defined(TRY_ERRNO_STD_DECL) */
extern int errno; /* last system error */
extern const char *const sys_errlist[]; /* system error messages */
extern int sys_nerr; /* number of system errors*/
printf("/*\n");
printf(" * The following comments were produced by calc_errno\n");
printf(" * in an effort to see if these values were correctly\n");
printf(" * declared when calc_errno.c was compiled.\n");
printf(" */\n\n");
printf("/* Initially errno is %d */\n", errno);
printf("/* There are %d entries in sys_errlist[] */\n", sys_nerr);
printf("/* The 2nd sys_errlist entry is \"%s\" */\n\n", sys_errlist[1]);
printf("/*\n");
printf(" * Based on the above, calc_errno now knows\n");
printf(" * how to declare errno and friends.\n");
printf(" */\n\n");
printf("extern int errno;\t\t\t/* last system error */\n");
printf("extern const char *const sys_errlist[];\t"
"/* system error messages */\n");
printf("extern int sys_nerr;\t\t\t/* number of system errors*/\n");
#endif
/* exit(0); */
return 0;
}

View File

@@ -336,3 +336,5 @@ E_STRCPY Bad argument type for strcpy
E_STRNCPY Bad argument type for strncpy
E_BACKSLASH Bad argument type for unary backslash
E_SETMINUS Bad argument type for setminus
E_INDICES1 Bad first argument type for indices
E_INDICES2 Bad second argument for indices

View File

@@ -11,6 +11,7 @@ BEGIN {
havebuf2=0;
buf2=0;
error = 0;
end_seen = 0;
}
NF == 0 {
@@ -29,6 +30,10 @@ NF == 0 {
next;
}
/: Ending regression tests$/ {
end_seen = 1;
}
$1 ~ /^[0-9]+:/ {
if (error > 0) {
if (havebuf2) {
@@ -71,7 +76,7 @@ END {
if (error > 0 && havebuf0) {
print buf0;
}
if (error > 0) {
if (error > 0 || !end_seen) {
exit(1);
} else {
exit(0);

295
codegen.c
View File

@@ -31,9 +31,9 @@ static void getshowstatement(void);
static void getfunction(void);
static void ungetfunction(void);
static void getbody(LABEL *contlabel, LABEL *breaklabel,
LABEL *nextcaselabel, LABEL *defaultlabel, BOOL toplevel);
static void getdeclarations(int symtype);
static void getsimpledeclaration (int symtype);
LABEL *nextcaselabel, LABEL *defaultlabel);
static int getdeclarations(int symtype);
static int getsimpledeclaration (int symtype);
static int getonevariable (int symtype);
static void getstatement(LABEL *contlabel, LABEL *breaklabel,
LABEL *nextcaselabel, LABEL *defaultlabel);
@@ -81,8 +81,14 @@ static long getinitlist(void);
void
getcommands(BOOL toplevel)
{
char name[PATHSIZE+1]; /* program name */
char name[MAXCMD+1+1]; /* program name */
/* firewall */
name[0] = '\0';
name[MAXCMD+1] = '\0';
abort_now = FALSE;
/* getcommands */
if (!toplevel)
enterfilescope();
for (;;) {
@@ -120,6 +126,7 @@ getcommands(BOOL toplevel)
switch (opensearchfile(name,calcpath,CALCEXT,rdonce)) {
case 0:
getcommands(FALSE);
closeinput();
break;
case 1:
/* previously read and -once was given */
@@ -158,6 +165,13 @@ getcommands(BOOL toplevel)
if (evaluate(FALSE))
updateoldvalue(curfunc);
freefunc(curfunc);
if (abort_now) {
if (!stdin_tty)
run_state = RUN_EXIT;
else if (run_state < RUN_PRE_TOP_LEVEL)
run_state = RUN_PRE_TOP_LEVEL;
longjmp(jmpbuf, 1);
}
}
}
}
@@ -184,13 +198,16 @@ evaluate(BOOL nestflag)
funcname = (nestflag ? "**" : "*");
beginfunc(funcname, nestflag);
if (gettoken() == T_LEFTBRACE) {
getbody(NULL_LABEL, NULL_LABEL, NULL_LABEL, NULL_LABEL);
} else {
if (nestflag)
(void) tokenmode(TM_DEFAULT);
rescantoken();
while (loop) {
switch (gettoken()) {
case T_SEMICOLON:
break;
case T_NEWLINE:
case T_EOF:
loop = 0;
@@ -202,6 +219,7 @@ evaluate(BOOL nestflag)
NULL_LABEL, NULL_LABEL);
}
}
}
addop(OP_UNDEF);
addop(OP_RETURN);
checklabels();
@@ -238,9 +256,15 @@ ungetfunction(void)
case T_MULT:
rmalluserfunc();
continue;
default:
case T_NEWLINE:
case T_SEMICOLON:
case T_EOF:
rescantoken();
return;
default:
scanerror(T_SEMICOLON,
"Non-name arg for undefine");
return;
}
}
}
@@ -256,6 +280,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) {
@@ -271,9 +297,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)
@@ -287,12 +315,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) {
@@ -302,13 +340,11 @@ getfunction(void)
}
switch (gettoken()) {
case T_ASSIGN:
rescantoken();
getsimplebody();
break;
case T_LEFTBRACE:
rescantoken();
getbody(NULL_LABEL, NULL_LABEL, NULL_LABEL,
NULL_LABEL, TRUE);
NULL_LABEL);
break;
default:
scanerror(T_NULL,
@@ -327,18 +363,9 @@ getfunction(void)
static void
getsimplebody(void)
{
if (gettoken() != T_ASSIGN) {
scanerror(T_SEMICOLON,
"Missing equals for simple function body");
return;
}
(void) tokenmode(TM_NEWLINES);
(void) getexprlist();
addop(OP_RETURN);
if (gettoken() != T_SEMICOLON)
rescantoken();
if (gettoken() != T_NEWLINE)
scanerror(T_NULL, "Illegal function definition");
}
@@ -349,14 +376,10 @@ getsimplebody(void)
*/
/*ARGSUSED*/
static void
getbody(LABEL *contlabel, LABEL *breaklabel, LABEL *nextcaselabel, LABEL *defaultlabel, BOOL toplevel)
getbody(LABEL *contlabel, LABEL *breaklabel, LABEL *nextcaselabel, LABEL *defaultlabel)
{
int oldmode;
if (gettoken() != T_LEFTBRACE) {
scanerror(T_SEMICOLON, "Missing left brace for function body");
return;
}
oldmode = tokenmode(TM_DEFAULT);
while (TRUE) {
switch (gettoken()) {
@@ -364,6 +387,10 @@ getbody(LABEL *contlabel, LABEL *breaklabel, LABEL *nextcaselabel, LABEL *defaul
(void) tokenmode(oldmode);
return;
case T_EOF:
scanerror(T_NULL, "End-of-file in function body");
return;
default:
rescantoken();
getstatement(contlabel, breaklabel, nextcaselabel, defaultlabel);
@@ -377,9 +404,11 @@ getbody(LABEL *contlabel, LABEL *breaklabel, LABEL *nextcaselabel, LABEL *defaul
* declarations = { LOCAL | GLOBAL | STATIC } onedeclaration
* [ ',' onedeclaration ] ... ';'.
*/
static void
static int
getdeclarations(int symtype)
{
int res = 0;
while (TRUE) {
switch (gettoken()) {
case T_COMMA:
@@ -388,29 +417,33 @@ getdeclarations(int symtype)
case T_NEWLINE:
case T_SEMICOLON:
case T_RIGHTBRACE:
case T_EOF:
rescantoken();
return;
return res;
case T_SYMBOL:
addopone(OP_DEBUG, linenumber());
rescantoken();
getsimpledeclaration(symtype);
if (getsimpledeclaration(symtype))
res = 1;
break;
case T_MAT:
addopone(OP_DEBUG, linenumber());
getmatdeclaration(symtype);
res = 1;
break;
case T_OBJ:
addopone(OP_DEBUG, linenumber());
getobjdeclaration(symtype);
addop(OP_POP);
res = 1;
break;
default:
scanerror(T_SEMICOLON, "Bad syntax in declaration statement");
return;
return res;
}
}
}
@@ -422,22 +455,24 @@ getdeclarations(int symtype)
* Subsequences end with "," or at end of line; spaces indicate
* repeated assignment, e.g. "c d = 2" has the effect of "c = 2, d = 2".
*/
static void
static int
getsimpledeclaration(int symtype)
{
int res = 0;
for (;;) {
switch (gettoken()) {
case T_SYMBOL:
rescantoken();
if (getonevariable(symtype))
res = getonevariable(symtype);
if (res)
addop(OP_POP);
continue;
case T_COMMA:
continue;
default:
rescantoken();
return;
return res;
}
}
}
@@ -486,11 +521,9 @@ getonevariable(int symtype)
* | BREAK ';'
* | RETURN assignment ';'
* | GOTO label ';'
* | MAT name '[' value [ ':' value ] [',' value [ ':' value ] ] ']' ';'
* | OBJ type '{' arg [ ',' arg ] ... '}' ] ';'
* | OBJ type name [ ',' name ] ';'
* | PRINT assignment [, assignment ] ... ';'
* | QUIT [ string ] ';'
* | ABORT [ string ] ';'
* | SHOW item ';'
* | body
* | assignment ';'
@@ -519,18 +552,20 @@ getstatement(LABEL *contlabel, LABEL *breaklabel, LABEL *nextcaselabel, LABEL *d
return;
case T_GLOBAL:
getdeclarations(SYM_GLOBAL);
(void) getdeclarations(SYM_GLOBAL);
break;
case T_STATIC:
clearlabel(&label);
addoplabel(OP_INITSTATIC, &label);
getdeclarations(SYM_STATIC);
if (getdeclarations(SYM_STATIC))
setlabel(&label);
else
curfunc->f_opcodecount -= 2;
break;
case T_LOCAL:
getdeclarations(SYM_LOCAL);
(void) getdeclarations(SYM_LOCAL);
break;
case T_RIGHTBRACE:
@@ -579,8 +614,7 @@ getstatement(LABEL *contlabel, LABEL *breaklabel, LABEL *nextcaselabel, LABEL *d
break;
case T_LEFTBRACE:
rescantoken();
getbody(contlabel, breaklabel, nextcaselabel, defaultlabel, FALSE);
getbody(contlabel, breaklabel, nextcaselabel, defaultlabel);
return;
case T_IF:
@@ -593,25 +627,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) {
@@ -662,7 +696,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);
@@ -671,14 +705,14 @@ getstatement(LABEL *contlabel, LABEL *breaklabel, LABEL *nextcaselabel, LABEL *d
}
}
if (gettoken() != T_RIGHTPAREN) { /* have 'c' part */
if (label1.l_offset <= 0)
if (label1.l_offset < 0)
addoplabel(OP_JUMP, &label3);
setlabel(&label2);
contlabel = &label2;
rescantoken();
(void) getexprlist();
addop(OP_POP);
if (label1.l_offset > 0)
if (label1.l_offset >= 0)
addoplabel(OP_JUMP, &label1);
if (gettoken() != T_RIGHTPAREN) {
(void) tokenmode(oldmode);
@@ -698,15 +732,21 @@ getstatement(LABEL *contlabel, LABEL *breaklabel, LABEL *nextcaselabel, LABEL *d
case T_WHILE:
oldmode = tokenmode(TM_DEFAULT);
contlabel = &label1;
breaklabel = &label2;
clearlabel(contlabel);
clearlabel(breaklabel);
setlabel(contlabel);
getcondition();
addoplabel(OP_JUMPEQ, breaklabel);
getstatement(contlabel, breaklabel, NULL_LABEL, NULL_LABEL);
if (gettoken() != T_SEMICOLON) {
breaklabel = &label2;
clearlabel(breaklabel);
addoplabel(OP_JUMPZ, breaklabel);
rescantoken();
getstatement(contlabel, breaklabel,
NULL_LABEL, NULL_LABEL);
addoplabel(OP_JUMP, contlabel);
setlabel(breaklabel);
} else {
addoplabel(OP_JUMPNZ, contlabel);
}
(void) tokenmode(oldmode);
return;
@@ -726,7 +766,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;
@@ -810,6 +850,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:
@@ -848,6 +890,17 @@ getstatement(LABEL *contlabel, LABEL *breaklabel, LABEL *nextcaselabel, LABEL *d
}
break;
case T_ABORT:
switch (gettoken()) {
case T_STRING:
addopone(OP_ABORT, tokenstring());
break;
default:
addopone(OP_ABORT, -1);
rescantoken();
}
break;
case T_SYMBOL:
if (nextchar() == ':') { /****HACK HACK****/
definelabel(tokensymbol());
@@ -961,7 +1014,11 @@ getobjdeclaration(int symtype)
/*FALLTHRU*/
case T_RIGHTBRACE:
(void) tokenmode(oldmode);
(void) defineobject(name, indices, count);
if (defineobject(name, indices, count)) {
scanerror(T_NULL,
"Object type \"%s\" is already defined", name);
return;
}
getobjvars(name, symtype);
return;
case T_NEWLINE:
@@ -983,8 +1040,7 @@ getoneobj(long index, int symtype)
if (symtype == SYM_UNDEFINED) {
rescantoken();
(void) getidexpr(TRUE, TRUE);
}
else {
} else {
symname = tokensymbol();
definesymbol(symname, symtype);
usesymbol(symname, FALSE);
@@ -1001,18 +1057,14 @@ getoneobj(long index, int symtype)
}
/*
* Routine to collect a set of variables for the specified object type
* and initialize them as being that type of object.
* Here
* objlist = name initlist [ ',' name initlist ] ... ';'.
* If symtype is SYM_UNDEFINED, then this is an OBJ statement where the
* values can be any variable expression, and no symbols are to be defined.
* Otherwise this is part of a declaration, and the variables must be raw
* symbol names which are defined with the specified symbol type.
* Routine to assign a specified object-type value to each of a set of
* variables in a "global", "local" or "static" declaration, or, if
* symtype is SYM_UNDEFINED, to create one object value of the specified
* type.
*
* given:
* name object name
* symtype type of symbol to collect for
* symtype declaration type
*/
static void
getobjvars(char *name, int symtype)
@@ -1026,6 +1078,8 @@ getobjvars(char *name, int symtype)
}
for (;;) {
getoneobj(index, symtype);
if (symtype == SYM_UNDEFINED)
return;
if (gettoken() != T_COMMA) {
rescantoken();
return;
@@ -1068,8 +1122,7 @@ getonematrix(int symtype)
if (symtype == SYM_UNDEFINED) {
rescantoken();
(void) getidexpr(FALSE, TRUE);
}
else {
} else {
name = tokensymbol();
definesymbol(name, symtype);
usesymbol(name, FALSE);
@@ -1082,6 +1135,21 @@ getonematrix(int symtype)
}
rescantoken();
if (gettoken() == T_LEFTPAREN) {
if (isrvalue(getexprlist())) {
scanerror(T_SEMICOLON, "Lvalue expected");
return;
}
if (gettoken() != T_RIGHTPAREN) {
scanerror(T_SEMICOLON, "Missing right parenthesis");
return;
}
getonematrix(symtype);
addop(OP_ASSIGN);
return;
}
rescantoken();
if (gettoken() != T_LEFTBRACKET) {
rescantoken();
scanerror(T_SEMICOLON, "Left-bracket expected");
@@ -1097,6 +1165,7 @@ getonematrix(int symtype)
* will patch the correct value back into the opcode.
*/
if (gettoken() == T_RIGHTBRACKET) {
if (gettoken() == T_ASSIGN) {
clearopt();
patchpc = curfunc->f_opcodecount + 1;
addopone(OP_NUMBER, (long) -1);
@@ -1106,16 +1175,24 @@ getonematrix(int symtype)
addop(OP_ZERO);
addop(OP_INITFILL);
count = 0;
if (gettoken() == T_ASSIGN)
count = getinitlist();
else
rescantoken();
index = addqconstant(itoq(count));
if (index < 0)
math_error("Cannot allocate constant");
curfunc->f_opcodes[patchpc] = index;
return;
}
rescantoken();
addopone(OP_MATCREATE, 0);
if (gettoken() == T_LEFTBRACKET) {
creatematrix();
} else {
rescantoken();
addop(OP_ZERO);
}
addop(OP_INITFILL);
return;
}
/*
* This isn't implicit, so we expect expressions for the bounds.
@@ -1133,41 +1210,45 @@ creatematrix(void)
{
long dim;
dim = 1;
dim = 0;
while (TRUE) {
for (;;) {
if (gettoken() == T_RIGHTBRACKET) {
addopone(OP_MATCREATE, dim);
if (gettoken() == T_LEFTBRACKET) {
creatematrix();
} else {
rescantoken();
addop(OP_ZERO);
}
addop(OP_INITFILL);
return;
}
rescantoken();
if (++dim > MAXDIM) {
scanerror(T_SEMICOLON, "Only %ld dimensions allowed", MAXDIM);
return;
}
(void) getopassignment();
switch (gettoken()) {
case T_RIGHTBRACKET:
case T_COMMA:
rescantoken();
case T_COMMA:
addop(OP_ONE);
addop(OP_SUB);
addop(OP_ZERO);
break;
case T_COLON:
(void) getopassignment();
break;
default:
rescantoken();
}
switch(gettoken()) {
case T_RIGHTBRACKET:
addopone(OP_MATCREATE, dim);
if (gettoken() == T_LEFTBRACKET)
creatematrix();
else {
rescantoken();
addop(OP_ZERO);
}
addop(OP_INITFILL);
return;
case T_COMMA:
if (++dim <= MAXDIM)
break;
scanerror(T_SEMICOLON, "Only %ld dimensions allowed", MAXDIM);
return;
continue;
}
/*FALLTHRU*/
default:
rescantoken();
scanerror(T_SEMICOLON, "Illegal matrix definition");
return;
}
@@ -1318,7 +1399,7 @@ getopassignment(void)
return type;
}
if (isrvalue(type)) {
scanerror(T_NULL, "Illegal assignment in getopassignment");
scanerror(T_NULL, "Illegal assignment");
(void) getopassignment();
return (EXPR_RVALUE | EXPR_ASSIGN);
}
@@ -1332,8 +1413,7 @@ getopassignment(void)
while (gettoken() == T_ASSIGN)
getinitlist();
rescantoken();
}
else {
} else {
rescantoken();
(void) getassignment();
}
@@ -1372,6 +1452,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()) {
@@ -1397,7 +1492,7 @@ getassignment (void)
return type;
}
if (isrvalue(type)) {
scanerror(T_SEMICOLON, "Illegal assignment in getassignment");
scanerror(T_SEMICOLON, "Illegal assignment");
(void) getassignment();
return (EXPR_RVALUE | EXPR_ASSIGN);
}
@@ -1436,7 +1531,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");
@@ -1856,11 +1951,6 @@ getterm(void)
case T_MAT:
getonematrix(SYM_UNDEFINED);
while (gettoken() == T_COMMA) {
addop(OP_POP);
getonematrix(SYM_UNDEFINED);
}
rescantoken();
type = EXPR_ASSIGN;
break;
@@ -2129,8 +2219,14 @@ getmatargs(void)
* finds that the element will be referenced for writing, then
* it will call writeindexop to change the flag in the opcode.
*/
dim = 1;
dim = 0;
if (gettoken() == T_RIGHTBRACKET) {
addoptwo(OP_INDEXADDR, (long) dim, (long) FALSE);
return;
}
rescantoken();
for (;;) {
++dim;
(void) getopassignment();
switch (gettoken()) {
case T_RIGHTBRACKET:
@@ -2138,7 +2234,6 @@ getmatargs(void)
(long) FALSE);
return;
case T_COMMA:
dim++;
break;
default:
rescantoken();

View File

@@ -138,38 +138,6 @@ csqrt(COMPLEX *c, NUMBER *epsilon, long R)
up1 = up2 = 0;
sign = (R & 64) != 0;
#if 0
if (qiszero(epsilon)) {
aes = qsquare(c->real);
bes = qsquare(c->imag);
v = qqadd(aes, bes);
qfree(aes);
qfree(bes);
u = qsqrt(v, epsilon, 0);
qfree(v);
if (qiszero(u)) {
qfree(u);
return clink(&_czero_);
}
aes = qqadd(u, c->real);
qfree(u);
bes = qscale(aes, -1);
qfree(aes);
u = qsqrt(bes, epsilon, R);
qfree(bes);
if (qiszero(u)) {
qfree(u);
return clink(&_czero_);
}
aes = qscale(c->imag, -1);
v = qqdiv(aes, u);
qfree(aes);
r = comalloc();
r->real = u;
r->imag = v;
return r;
}
#endif
imsign = c->imag->num.sign;
es = qsquare(epsilon);
aes = qqdiv(c->real, es);
@@ -231,8 +199,7 @@ csqrt(COMPLEX *c, NUMBER *epsilon, long R)
return r;
}
s3 = zquo(tmp3, d, &tmp1, s2 < 0);
}
else {
} else {
s2 = zquo(tmp1, d, &tmp3, s1 ? (s1 < 0) : 16);
zfree(tmp1);
s3 = zsqrt(tmp3,&tmp1,(s1||s2) ? (s1<0 || s2<0) : 16);
@@ -256,8 +223,7 @@ csqrt(COMPLEX *c, NUMBER *epsilon, long R)
up2 = -1;
zfree(tmp1);
zfree(aa);
}
else {
} else {
s1 = zsqrt(tmp3, &cc, 0);
zfree(tmp3);
zadd(cc, a, &tmp1);
@@ -288,8 +254,7 @@ csqrt(COMPLEX *c, NUMBER *epsilon, long R)
return r;
}
s3 = zquo(tmp3, d, &mul1, 0);
}
else {
} else {
s2 = zquo(tmp1, d, &tmp3, 0);
zfree(tmp1);
s3 = zsqrt(tmp3, &mul1, 0);
@@ -335,9 +300,9 @@ csqrt(COMPLEX *c, NUMBER *epsilon, long R)
zfree(mul2);
mul2 = tmp2;
}
if (ziszero(mul1))
if (ziszero(mul1)) {
u = qlink(&_qzero_);
else {
} else {
mul1.sign = sign ^ epsilon->num.sign;
u = qalloc();
zreduce(mul1, epsilon->den, &tmp2, &u->den);
@@ -345,9 +310,9 @@ csqrt(COMPLEX *c, NUMBER *epsilon, long R)
zfree(tmp2);
}
zfree(mul1);
if (ziszero(mul2))
if (ziszero(mul2)) {
v = qlink(&_qzero_);
else {
} else {
mul2.sign = imsign ^ sign ^ epsilon->num.sign;
v = qalloc();
zreduce(mul2, epsilon->den, &tmp2, &v->den);
@@ -1149,5 +1114,3 @@ cprintfr(COMPLEX *c)
zprintval(i->den, 0L, 0L);
}
}
/* END CODE */

375
config.c
View File

@@ -55,6 +55,9 @@ NAMETYPE configs[] = {
{"lib_debug", CONFIG_LIB_DEBUG},
{"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}
};
@@ -93,9 +96,11 @@ 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 */
0, /* internal calc debug level */
0 /* user defined debug level */
3, /* calc library debug level */
0, /* user defined debug level */
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 */
@@ -128,9 +133,11 @@ 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 */
0, /* internal calc debug level */
0 /* user defined debug level */
3, /* calc library debug level */
0, /* user defined debug level */
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 */
@@ -139,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},
@@ -155,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},
@@ -199,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}
};
@@ -217,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);
/*
@@ -246,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:
* 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;
}
@@ -266,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;
@@ -414,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*/
@@ -523,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*/
@@ -537,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*/
@@ -677,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*/
@@ -692,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*/
@@ -769,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*/
@@ -783,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);
@@ -797,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);
@@ -806,20 +783,6 @@ setconfig(int type, VALUE *vp)
conf->blkfmt = temp;
break;
case CONFIG_LIB_DEBUG:
if (vp->v_type != V_NUM) {
math_error("Non numeric for lib_debug");
/*NOTREACHED*/
}
q = vp->v_num;
temp = qtoi(q);
if (qisfrac(q) || !zistiny(q->num)) {
math_error("Illegal lib_debug parameter value");
/*NOTREACHED*/
}
conf->lib_debug = temp;
break;
case CONFIG_CALC_DEBUG:
if (vp->v_type != V_NUM) {
math_error("Non numeric for calc_debug");
@@ -834,6 +797,20 @@ setconfig(int type, VALUE *vp)
conf->calc_debug = temp;
break;
case CONFIG_LIB_DEBUG:
if (vp->v_type != V_NUM) {
math_error("Non numeric for lib_debug");
/*NOTREACHED*/
}
q = vp->v_num;
temp = qtoi(q);
if (qisfrac(q) || !zistiny(q->num)) {
math_error("Illegal lib_debug parameter value");
/*NOTREACHED*/
}
conf->lib_debug = temp;
break;
case CONFIG_USER_DEBUG:
if (vp->v_type != V_NUM) {
math_error("Non numeric for user_debug");
@@ -848,6 +825,35 @@ setconfig(int type, VALUE *vp)
conf->user_debug = temp;
break;
case CONFIG_VERBOSE_QUIT:
if (vp->v_type == V_NUM) {
q = vp->v_num;
conf->verbose_quit = !qiszero(q);
} else if (vp->v_type == V_STR) {
temp = lookup_long(truth, vp->v_str->s_str);
if (temp < 0) {
math_error("Illegal truth value "
"for verbose_quit");
/*NOTREACHED*/
}
conf->verbose_quit = (int)temp;
}
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*/
@@ -890,7 +896,7 @@ config_copy(CONFIG *src)
/*
* copy over the values
*/
*dest = *src;
memcpy((void *)dest, (void *)src, sizeof(CONFIG));
/*
* clone the pointer values
@@ -968,6 +974,7 @@ void
config_value(CONFIG *cfg, int type, VALUE *vp)
{
long i=0;
char *p;
/*
* firewall
@@ -982,6 +989,7 @@ config_value(CONFIG *cfg, int type, VALUE *vp)
* convert element to value
*/
vp->v_type = V_NUM;
vp->v_subtype = V_NOSUBTYPE;
switch (type) {
case CONFIG_ALL:
vp->v_type = V_CONFIG;
@@ -998,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:
@@ -1026,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;
@@ -1070,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;
@@ -1096,29 +1129,65 @@ 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;
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;
break;
case CONFIG_LIB_DEBUG:
i = cfg->lib_debug;
break;
case CONFIG_CALC_DEBUG:
i = cfg->calc_debug;
break;
case CONFIG_USER_DEBUG:
i = cfg->user_debug;
break;
case CONFIG_VERBOSE_QUIT:
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");
/*NOTREACHED*/
@@ -1192,7 +1261,9 @@ config_cmp(CONFIG *cfg1, CONFIG *cfg2)
cfg1->blkverbose != cfg2->blkverbose ||
cfg1->blkbase != cfg2->blkbase ||
cfg1->blkfmt != cfg2->blkfmt ||
cfg1->lib_debug != cfg2->lib_debug ||
cfg1->calc_debug != cfg2->calc_debug ||
cfg1->user_debug != cfg2->user_debug;
cfg1->lib_debug != cfg2->lib_debug ||
cfg1->user_debug != cfg2->user_debug ||
cfg1->verbose_quit != cfg2->verbose_quit ||
cfg1->ctrl_d != cfg2->ctrl_d;
}

View File

@@ -29,11 +29,9 @@
* Happy bit twiddling,
*
* Landon Curt Noll
* http://reality.sgi.com/chongo/
*
* chongo@toad.com
* ...!{pyramid,sun,uunet}!hoptoad!chongo
*
* chongo was here /\../\
* chongo <was here> /\../\
*/
@@ -82,10 +80,12 @@
#define CONFIG_LIB_DEBUG 30
#define CONFIG_CALC_DEBUG 31
#define CONFIG_USER_DEBUG 32
#define CONFIG_VERBOSE_QUIT 33
#define CONFIG_CTRL_D 34
/*
* 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
@@ -105,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 */
@@ -118,8 +118,8 @@ struct config {
LEN sq2; /* size of number to use square algorithm 2 */
LEN pow2; /* size of modulus to use REDC for powers */
LEN redc2; /* size of modulus to use REDC algorithm 2 */
int tilde_ok; /* ok to print a tilde on aproximations */
int tab_ok; /* ok to print tab before numeric values */
BOOL tilde_ok; /* ok to print a tilde on aproximations */
BOOL tab_ok; /* ok to print tab before numeric values */
long quomod; /* quomod() default rounding mode */
long quo; /* quotent // default rounding mode */
long mod; /* mod % default rounding mode */
@@ -129,28 +129,61 @@ struct config {
long cfsim; /* cfsim() default rounding mode */
long outround; /* output default rounding mode */
long round; /* round()/bround() default rounding mode */
int leadzero; /* ok to print leading 0 before decimal pt */
int fullzero; /* ok to print trailing 0's */
BOOL leadzero; /* ok to print leading 0 before decimal pt */
BOOL fullzero; /* ok to print trailing 0's */
long maxscancount; /* max scan errors before abort */
char *prompt1; /* normal prompt */
char *prompt2; /* prompt when inside multi-line input */
int blkmaxprint; /* octets of a block to print, 0 => all */
int blkverbose; /* TRUE => print all lines if a block */
BOOL blkverbose; /* TRUE => print all lines if a block */
int blkbase; /* block output base */
int blkfmt; /* block output style */
int lib_debug; /* library debug: <0 none, 0 default, >0 more */
int calc_debug; /* internal debug: <0 none, 0 default,>0 more */
int user_debug; /* user defined debug value: 0 default */
long calc_debug; /* internal debug, see CALC_DEBUG_XXX below */
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;
/*
* lib_debug bit masks
*/
#define LIBDBG_STDIN_FUNC (0x00000001) /* interactive func define debug */
#define LIBDBG_FILE_FUNC (0x00000002) /* file read func define debug */
#define LIBDBG_FUNC_INFO (0x00000004) /* print extra info for show func */
#define LIBDBG_MASK (0x00000007)
/*
* calc_debug bit masks
*/
#define CALCDBG_SYSTEM (0x00000001) /* print system cmd prior to exec */
#define CALCDBG_FUNC_QUIT (0x00000002) /* active functions when quit */
#define CALCDBG_HASH_STATE (0x00000004) /* hash state details */
#define CALCDBG_BLOCK (0x00000008) /* block debug */
#define CALCDBG_TTY (0x00000010) /* report TTY state changes */
#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
*/
extern CONFIG *conf; /* current configuration */
extern CONFIG oldstd; /* backward compatible standard configuration */
extern CONFIG newstd; /* new non-backward compatible configuration */
extern char *calc_debug; /* !=NULL => value of config("calc_debug") */
extern char *lib_debug; /* !=NULL => value of config("lib_debug") */
extern char *user_debug; /* !=NULL => value of config("user_debug") */
/*

14
const.c
View File

@@ -27,10 +27,11 @@ initconstants(void)
math_error("Unable to allocate constant table");
/*NOTREACHED*/
}
for (i = 0; i < 8; i++)
for (i = 0; i < INITCONSTCOUNT; i++)
consttable[i] = initnumbs[i];
constcount = 8;
constavail = CONSTALLOCSIZE - 8;
consttable[INITCONSTCOUNT] = NULL; /* firewall */
constcount = INITCONSTCOUNT;
constavail = CONSTALLOCSIZE - INITCONSTCOUNT;
}
@@ -187,10 +188,9 @@ freeconstant(unsigned long index)
void
trimconstants(void)
{
NUMBER **qp;
qp = &consttable[constcount];
while (constcount > 0 && (*--qp)->links == 0) {
while (constcount > 0 &&
(consttable[constcount-1] == NULL ||
consttable[constcount-1]->links == 0)) {
constcount--;
constavail++;
}

View File

@@ -25,11 +25,9 @@
* Happy bit twiddling,
*
* Landon Curt Noll
* http://reality.sgi.com/chongo/
*
* chongo@toad.com
* ...!{pyramid,sun,uunet}!hoptoad!chongo
*
* chongo was here /\../\
* chongo <was here> /\../\
*/
/* these include files are needed regardless of CUSTOM */

View File

@@ -29,14 +29,11 @@
* Happy bit twiddling,
*
* Landon Curt Noll
* http://reality.sgi.com/chongo/
*
* chongo@toad.com
* ...!{pyramid,sun,uunet}!hoptoad!chongo
*
* chongo was here /\../\
* chongo <was here> /\../\
*/
/*
* Be careful what you put in this file, upper .c files include
* this file even when CUSTOM is not defined (ALLOW_CUSTOM is empty).

View File

@@ -1,5 +1,5 @@
#
# Copyright (c) 1997 Landon Curt Noll
# Copyright (c) 1999 Landon Curt Noll
#
# Permission to use, copy, modify, and distribute this software and
# its documentation for any purpose and without fee is hereby granted,
@@ -19,7 +19,7 @@
# OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
#
# chongo was here /\../\ chongo@toad.com
# chongo was here /\../\ http://reality.sgi.com/chongo/
The following custom calc library files are provided because they serve
as examples of how use the custom interface. The custom interface
@@ -44,8 +44,19 @@ calc library standards and guidelines.
=-=
argv.cal
argv(var, ...)
print information about various args
halflen.cal
halflen(num)
Calculate the length of a numeric value in HALF's.
pzasusb8.cal
Run custom("pzasusb8") on a standard set of data, print Endian
related information and print value size information.

View File

@@ -38,17 +38,17 @@ Step 1: Do some background work
you look at some examples of custom functions. Check out
the following source files:
../custom.c
custom.h
custtbl.c
c_*.[ch]
../help/custom
custom.c
custom/custom.h
custom/custtbl.c
custom/c_*.[ch]
help/custom (or run: calc help custom)
You would be well advised to look at a more recent calc source
such as one available in from the calc alpha test archive.
such as one available in from the calc version archive.
See the following for more details:
../help/archive
help/archive (or run: calc help archive)
Step 2: Name your custom function
@@ -604,3 +604,16 @@ Step 11: Install
Although calc does not run setuid, you may need to be root to install
the directories into which calc installs may be write protected.
Step 12: Contribute
Your custom function may be of interest to some people and/or
serve as an example of what one can do with custom functions.
Read the file:
help/contrib (or run: calc help contrib)
and consider submitting your custom function for possible
inclusion in later versions of calc.

View File

@@ -27,11 +27,9 @@
# Happy bit twiddling,
#
# Landon Curt Noll
# http://reality.sgi.com/chongo/
#
# chongo@toad.com
# ...!{pyramid,sun,uunet}!hoptoad!chongo
#
# chongo was here /\../\
# chongo <was here> /\../\
##############################################################################
#-=-=-=-=-=-=-=-=- You may want to change some values below -=-=-=-=-=-=-=-=-#
@@ -41,13 +39,13 @@
#
# Put your custom calc library files here.
#
CUSTOM_CALC_FILES= argv.cal halflen.cal
CUSTOM_CALC_FILES= argv.cal halflen.cal pzasusb8.cal
# The custom help files to install
#
# Put your custom help files here.
#
CUSTOM_HELP= argv devnull help sysinfo
CUSTOM_HELP= argv devnull help sysinfo pzasusb8
# Any .h files that are needed by programs that use libcustcalc.a
#
@@ -63,7 +61,7 @@ CUSTOM_H_SRC=
#
# Put your custom .c files here.
#
CUSTOM_SRC= c_argv.c c_devnull.c c_help.c c_sysinfo.c
CUSTOM_SRC= c_argv.c c_devnull.c c_help.c c_sysinfo.c c_pzasusb8.c
# Any .o files that are needed by program that use libcustcalc.a.
# Don't put ${REQUIRED_OBJ} files in this list.
@@ -72,7 +70,7 @@ CUSTOM_SRC= c_argv.c c_devnull.c c_help.c c_sysinfo.c
#
# Put your custom .o files here.
#
CUSTOM_OBJ= c_argv.o c_devnull.o c_help.o c_sysinfo.o
CUSTOM_OBJ= c_argv.o c_devnull.o c_help.o c_sysinfo.o c_pzasusb8.o
##############################################################################
#-=-=-=-=-=-=- Defaults in case you want to build from this dir -=-=-=-=-=-=-#
@@ -287,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}
@@ -312,6 +314,15 @@ libcustcalc.a: ${CUSTCALC_OBJ} ${MAKE_FILE} ../Makefile
ar qc libcustcalc.a ${CUSTCALC_OBJ}
${RANLIB} libcustcalc.a
##
#
# Special .o files
#
##
c_sysinfo.o: c_sysinfo.c ${MAKE_FILE}
${CC} ${CFLAGS} c_sysinfo.c -c
##
#
# used by the upper level Makefile
@@ -339,14 +350,17 @@ libcustcalc.a: ${CUSTCALC_OBJ} ${MAKE_FILE} ../Makefile
distlist: ${DISTLIST}
${Q}for i in ${DISTLIST}; do \
echo calc/custom/$$i; \
echo custom/$$i; \
done
# The bsdi distribution has generated files as well as distributed files.
#
bsdilist: ${DISTLIST}
${Q}for i in ${DISTLIST}; do \
echo calc/custom/$$i; \
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
##
@@ -381,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"; \
@@ -390,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"; \
@@ -403,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
@@ -421,9 +433,13 @@ depend:
else \
rm -f Makefile.tmp; \
mv Makefile Makefile.tmp; \
sccs edit Makefile; \
if [ -d RCS ]; then \
co -l Makefile; \
fi ;\
mv Makefile.tmp Makefile; \
echo new 'custom Makefile formed -- you need to check it in'; \
if [ -d RCS ]; then \
echo 'new custom Makefile formed -- you need to check it in'; \
fi; \
fi
##
@@ -590,6 +606,31 @@ c_help.o: ../string.h
c_help.o: ../value.h
c_help.o: ../zmath.h
c_help.o: c_help.c
c_pzasusb8.o: ../alloc.h
c_pzasusb8.o: ../block.h
c_pzasusb8.o: ../byteswap.h
c_pzasusb8.o: ../calcerr.h
c_pzasusb8.o: ../cmath.h
c_pzasusb8.o: ../config.h
c_pzasusb8.o: ../custom.h
c_pzasusb8.o: ../endian_calc.h
c_pzasusb8.o: ../hash.h
c_pzasusb8.o: ../have_const.h
c_pzasusb8.o: ../have_malloc.h
c_pzasusb8.o: ../have_memmv.h
c_pzasusb8.o: ../have_newstr.h
c_pzasusb8.o: ../have_stdlib.h
c_pzasusb8.o: ../have_string.h
c_pzasusb8.o: ../longbits.h
c_pzasusb8.o: ../md5.h
c_pzasusb8.o: ../nametype.h
c_pzasusb8.o: ../qmath.h
c_pzasusb8.o: ../shs.h
c_pzasusb8.o: ../shs1.h
c_pzasusb8.o: ../string.h
c_pzasusb8.o: ../value.h
c_pzasusb8.o: ../zmath.h
c_pzasusb8.o: c_pzasusb8.c
c_sysinfo.o: ../alloc.h
c_sysinfo.o: ../block.h
c_sysinfo.o: ../byteswap.h

View File

@@ -10,7 +10,7 @@
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*
* chongo was here /\../\ chongo@toad.com
* chongo was here /\../\ http://reality.sgi.com/chongo/
*/
/*
* argv - print information about various args

View File

@@ -16,11 +16,9 @@
* Happy bit twiddling,
*
* Landon Curt Noll
* http://reality.sgi.com/chongo/
*
* chongo@toad.com
* ...!{pyramid,sun,uunet}!hoptoad!chongo
*
* chongo was here /\../\
* chongo <was here> /\../\
*/
#if defined(CUSTOM)

View File

@@ -16,11 +16,9 @@
* Happy bit twiddling,
*
* Landon Curt Noll
* http://reality.sgi.com/chongo/
*
* chongo@toad.com
* ...!{pyramid,sun,uunet}!hoptoad!chongo
*
* chongo was here /\../\
* chongo <was here> /\../\
*/
#if defined(CUSTOM)

View File

@@ -16,11 +16,9 @@
* Happy bit twiddling,
*
* Landon Curt Noll
* http://reality.sgi.com/chongo/
*
* chongo@toad.com
* ...!{pyramid,sun,uunet}!hoptoad!chongo
*
* chongo was here /\../\
* chongo <was here> /\../\
*/
#if defined(CUSTOM)

70
custom/c_pzasusb8.c Normal file
View File

@@ -0,0 +1,70 @@
/*
* Permission to use, copy, modify, and distribute this software and
* its documentation for any purpose and without fee is hereby granted.
*
* Ernest Bowen, following Landon Curt Noll
*/
#if defined(CUSTOM)
#include <stdio.h>
#include "../have_const.h"
#include "../value.h"
#include "../custom.h"
#include "../zmath.h"
/*
* c_pzasusb8 - print numereator of real as if its array of HALFs were
* a string of USB8s
*
* given:
* count = 1;
* vals[0] real number;
*
* returns:
* null
*/
/*ARGSUSED*/
VALUE
c_pzasusb8(char *name, int count, VALUE **vals)
{
VALUE result; /* what we will return */
ZVALUE z; /* numerator of the value */
long half_cnt; /* number of HALFs in the numerator */
USB8 *h; /* octet pointer */
long half_len; /* length of a half in octets */
long i;
long j;
/*
* arg check
*/
result.v_type = V_NULL;
if (vals[0]->v_type != V_NUM) {
math_error("Non-real argument for pzasusb8");
/*NOTREACHED*/
}
/*
* look at the numerator
*/
z = vals[0]->v_num->num;
half_len = sizeof(HALF);
half_cnt = z.len;
/*
* print the octets
*/
h = (USB8 *) z.v;
for (i=0; i < half_cnt; ++i) {
printf("%ld:\t", i);
for (j=0; j < half_len; ++j) {
printf("%02x", (int)(*h++));
}
putchar('\n');
}
return result;
}
#endif /* CUSTOM */

View File

@@ -16,11 +16,9 @@
* Happy bit twiddling,
*
* Landon Curt Noll
* http://reality.sgi.com/chongo/
*
* chongo@toad.com
* ...!{pyramid,sun,uunet}!hoptoad!chongo
*
* chongo was here /\../\
* chongo <was here> /\../\
*/
#if defined(CUSTOM)
@@ -35,6 +33,7 @@
#include "../config.h"
#include "../calc.h"
#include "../longbits.h"
#define CHECK_L_FORMAT
#include "../longlong.h"
#include "../block.h"
#include "../calcerr.h"
@@ -99,6 +98,7 @@ static struct infoname sys_info[] = {
{"LONGLONG_BITS", "length of a long long, or 0", NULL, (FULL)LONGLONG_BITS},
{"LONG_BITS", "bit length of a long", NULL, (FULL)LONG_BITS},
{"MAP_POPCNT", "number of odd primes in pr_map", NULL, (FULL)MAP_POPCNT},
{"MAX_CALCRC", "maximum allowed length of $CALCRC", NULL, (FULL)MAX_CALCRC},
{"MAXCMD", "max length of command invocation", NULL, (FULL)MAXCMD},
{"MAXDIM", "max number of dimensions in matrices", NULL, (FULL)MAXDIM},
{"MAXERROR", "max length of error message string", NULL, (FULL)MAXERROR},
@@ -109,7 +109,6 @@ static struct infoname sys_info[] = {
{"MAXLABELS", "max number of user labels in function", NULL, (FULL)MAXLABELS},
{"MAXLEN", "longest storage size allowed", NULL, (FULL)MAXLEN},
{"MAXLONG", "largest long val", NULL, (FULL)MAXLONG},
{"MAXOBJECTS", "max number of object types", NULL, (FULL)MAXOBJECTS},
{"MAXPRINT_DEFAULT", "default number of elements printed", NULL, (FULL)MAXPRINT_DEFAULT},
{"MAXREDC", "number of entries in REDC cache", NULL, (FULL)MAXREDC},
{"MAXSCANCOUNT", "default max scan errors before an abort", NULL, (FULL)MAXSCANCOUNT},
@@ -128,8 +127,6 @@ static struct infoname sys_info[] = {
{"NXT_MAP_PRIME", "smallest odd prime not in pr_map", NULL, (FULL)NXT_MAP_PRIME},
{"NXT_PFACT_VAL", "next prime for higher pfact values", NULL, (FULL)NXT_PFACT_VAL},
{"OFF_T_BITS", "file offset size in bits", NULL, (FULL)OFF_T_BITS},
{"PATHSIZE", "max length of path name", NULL, (FULL)PATHSIZE},
{"PATHSIZE", "max length of path name", NULL, (FULL)PATHSIZE},
{"PIX_32B", "max pix() value", NULL, (FULL)PIX_32B},
{"POW_ALG2", "default size for using REDC for powers", NULL, (FULL)POW_ALG2},
{"REDC_ALG2", "default size using alternative REDC alg", NULL, (FULL)REDC_ALG2},
@@ -238,9 +235,10 @@ c_sysinfo(char *name, int count, VALUE **vals)
} else if (vals[0]->v_type == V_STR) {
/* convert vals[0] to upper case string */
buf = (char *)malloc(strlen((char *)vals[0]->v_str)+1);
for (q = (char *)vals[0]->v_str, r = buf; *q; ++q, ++r) {
if (isascii(*q) && islower(*q)) {
buf = (char *)malloc(strlen((char *)vals[0]->v_str->s_str)+1);
for (q = (char *)vals[0]->v_str->s_str, r = buf; *q; ++q, ++r)
{
if (isascii((int)*q) && islower((int)*q)) {
*r = *q - 'a' + 'A';
} else {
*r = *q;
@@ -262,7 +260,7 @@ c_sysinfo(char *name, int count, VALUE **vals)
/* return value as string */
result.v_type = V_STR;
result.v_subtype = V_NOSUBTYPE;
result.v_str = (STRING *)p->str;
result.v_str = makestring(p->str);
}
/* return found infotype as value */
@@ -309,17 +307,33 @@ static void
dump_name_value(void)
{
struct infoname *p; /* current infoname */
char *fmt; /* printf value format */
/* dump the entire table */
for (p = sys_info; p->name != NULL; ++p) {
if (p->str == NULL) {
#if LONG_BITS == FULL_BITS || FULL_BITS == 32 || !defined(HAVE_LONGLONG)
printf("%s%-23s\t%-8lu\t(0x%lx)\n",
fmt = "%s%-23s\t%-8lu\t(0x%lx)\n";
printf(fmt,
(conf->tab_ok ? "\t" : ""), p->name,
(unsigned long)p->nmbr,
(unsigned long)p->nmbr);
#else
printf("%s%-23s\t%-8llu\t(0x%llx)\n",
/*
* Determine of %ld can print a 64 bit long long.
*
* Some systems that can make use of %ld to print a
* a 64 bit value do not support the %lld type.
* So we will only try %lld if %ld does not work.
*/
if (l_format < 0) {
/* %ld prints lower 32 bits only, use %lld */
fmt = "%s%-23s\t%-8llu\t(0x%llx)\n";
} else {
/* %ld prints all 64 bits, use %ld */
fmt = "%s%-23s\t%-8lu\t(0x%lx)\n";
}
printf(fmt,
(conf->tab_ok ? "\t" : ""), p->name,
(unsigned long long)p->nmbr,
(unsigned long long)p->nmbr);
@@ -340,17 +354,33 @@ static void
dump_mening_value(void)
{
struct infoname *p; /* current infoname */
char *fmt; /* printf value format */
/* dump the entire table */
for (p = sys_info; p->name != NULL; ++p) {
if (p->str == NULL) {
#if LONG_BITS == FULL_BITS || FULL_BITS == 32 || !defined(HAVE_LONGLONG)
printf("%s%-36.36s\t%-8lu\t(0x%lx)\n",
fmt = "%s%-36.36s\t%-8lu\t(0x%lx)\n";
printf(fmt,
(conf->tab_ok ? "\t" : ""), p->meaning,
(unsigned long)p->nmbr,
(unsigned long)p->nmbr);
#else
printf("%s%-36.36s\t%-8llu\t(0x%llx)\n",
/*
* Determine of %ld can print a 64 bit long long.
*
* Some systems that can make use of %ld to print a
* a 64 bit value do not support the %lld type.
* So we will only try %lld if %ld does not work.
*/
if (l_format < 0) {
/* %ld prints lower 32 bits only, use %lld */
fmt = "%s%-36.36s\t%-8llu\t(0x%llx)\n";
} else {
/* %ld prints all 64 bits, use %ld */
fmt = "%s%-36.36s\t%-8lu\t(0x%lx)\n";
}
printf(fmt,
(conf->tab_ok ? "\t" : ""), p->meaning,
(unsigned long long)p->nmbr,
(unsigned long long)p->nmbr);

View File

@@ -25,11 +25,9 @@
* Happy bit twiddling,
*
* Landon Curt Noll
* http://reality.sgi.com/chongo/
*
* chongo@toad.com
* ...!{pyramid,sun,uunet}!hoptoad!chongo
*
* chongo was here /\../\
* chongo <was here> /\../\
*/
@@ -59,6 +57,7 @@ extern VALUE c_argv(char*, int, VALUE**);
extern VALUE c_devnull(char*, int, VALUE**);
extern VALUE c_help(char*, int, VALUE**);
extern VALUE c_sysinfo(char*, int, VALUE**);
extern VALUE c_pzasusb8(char*, int, VALUE**);
#endif /* CUSTOM */
@@ -108,6 +107,9 @@ CONST struct custom cust[] = {
{ "sysinfo", "return a calc #define value",
0, 1, c_sysinfo },
{ "pzasusb8", "print ZCALUE as USB8",
0, 1, c_pzasusb8 },
#endif /* CUSTOM */

View File

@@ -10,7 +10,7 @@
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*
* chongo was here /\../\ chongo@toad.com
* chongo was here /\../\ http://reality.sgi.com/chongo/
*/
/*
* halflen - determine the length of numeric value in HALFs

50
custom/pzasusb8 Normal file
View File

@@ -0,0 +1,50 @@
NAME
pzasusb8 - print a number in hex octets
SYNOPSIS
custom("pzasusb8", arg)
TYPES
arg real
return null
DESCRIPTION
This custom function prints out the numerator of a real value
in octets. Each HALF value is printed in a separate line.
NOTE: The output will vary depending on the size of a HALF
and the byte order of the system. See:
custom("sysinfo", "BASEB")
custom("sysinfo", "CALC_BYTE_ORDER")
foe details.
This custom function is intented for testing of the general
custom interface.
EXAMPLE
> custom("pzasusb8", 0x01020304050607080910111213141516);
0: 13141516
1: 09101112
2: 05060708
3: 01020304
> custom("pzasusb8", 10^25)
0: 4a000000
1: 16140148
2: 00084595
> printf("%x\n", 10^25);
0x84595161401484a000000
LIMITS
calc must be built with ALLOW_CUSTOM= -DCUSTOM
calc must be executed with a -C arg.
LIBRARY
none
SEE ALSO
custom

31
custom/pzasusb8.cal Normal file
View File

@@ -0,0 +1,31 @@
/*
* Permission to use, copy, modify, and distribute this software and
* its documentation for any purpose and without fee is hereby granted.
*
* Ernest Bowen, following Landon Curt Noll
*/
print "p(n) prints array in which numerator of n is stored as a";
print "sequence of 2-hex-digits representing unsigned characters.";
print "h(n) printx n in hex notation. This should be the same as";
print "p(n) except for (1) its leading 0x, (2) possible trailing zeros";
print "in p(n), and (3) the order of the hex-digit pairs.";
print "The following example show results for n = isqrt(2e100).";
print "";
define p(n) {custom("pzasusb8", n); print;}
define h(n) = printf("%x\n", n);
n = isqrt(2e100);
print "";
p(n);
h(n);
print "";
print "BASEB: ", custom("sysinfo", "BASEB");
print "CALC_BYTE_ORDER: ", custom("sysinfo", "CALC_BYTE_ORDER");
print "BIG_ENDIAN: ", custom("sysinfo", "BIG_ENDIAN");
print "LITTLE_ENDIAN: ", custom("sysinfo", "LITTLE_ENDIAN");
print "LONG_BITS: ", custom("sysinfo", "LONG_BITS");
print "LONGLONG_BITS: ", custom("sysinfo", "LONGLONG_BITS");
print "Calc sizes:";
show sizes;

27
file.c
View File

@@ -115,15 +115,14 @@ file_init(void)
*/
if (fstat(i, &sbuf) >= 0) {
fp = (FILE *) fdopen(i,"r+"); /*guess mode*/
if (fp)
if (fp) {
strcpy(files[idnum].mode, "r+");
else {
} else {
fp = (FILE *) fdopen(i, "r");
if (fp) {
strcpy(files[idnum].mode, "r");
files[idnum].writing = FALSE;
}
else {
} else {
fp = (FILE *) fdopen(i, "w");
if (fp) {
strcpy(files[idnum].mode, "w?");
@@ -890,8 +889,9 @@ idprintf(FILEID id, char *fmt, int count, VALUE **vals)
NULL)
math_chr(*vp->v_nblock->
blk->data);
} else
} else {
printvalue(vp, PRINT_NORMAL);
}
break;
default:
printvalue(vp, PRINT_NORMAL);
@@ -1770,8 +1770,7 @@ showfiles(void)
if (fstat(fileno(fp), &sbuf) < 0) {
printf("Bad fstat for file %d\n", (int) fiop->id);
sizes[i] = -1;
}
else {
} else {
inodes[i] = sbuf.st_ino;
sizes[i] = (long) sbuf.st_size;
}
@@ -2229,15 +2228,16 @@ freadnum(FILE *fp, VALUE *valptr)
ch = fgetc(fp);
}
}
if (ch == 'i' || ch == 'I')
if (ch == 'i' || ch == 'I') {
imag = TRUE;
else {
} else {
ungetc(ch, fp);
}
if (ziszero(num)) {
zfree(num);
val.v_type = V_NUM;
val.v_subtype = V_NOSUBTYPE;
val.v_num = qlink(&_qzero_);
*valptr = val;
return;
@@ -2271,6 +2271,7 @@ freadnum(FILE *fp, VALUE *valptr)
num = newnum;
zden = newden;
}
zfree(div);
}
q = qalloc();
q->num = num;
@@ -2281,11 +2282,11 @@ freadnum(FILE *fp, VALUE *valptr)
c->imag = q;
val.v_type = V_COM;
val.v_com = c;
}
else {
} else {
val.v_type = V_NUM;
val.v_num = q;
}
val.v_subtype = V_NOSUBTYPE;
*valptr = val;
}
@@ -2470,9 +2471,9 @@ fsearch(FILEID id, char *str, ZVALUE start, ZVALUE end, ZVALUE *res)
}
(void) f_seek_set(fiop->fp, &cur);
}
if (*tmp.v)
if (*tmp.v) {
(*tmp.v)--;
else {
} else {
if (tmp.len == 1)
break;
k = 0;

1155
func.c

File diff suppressed because it is too large Load Diff

126
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)
@@ -391,8 +403,8 @@ hash_zvalue(int type, ZVALUE zval, HASH *state)
*/
if (zval.len > full_lim) {
for (j=0; j < zval.len-full_lim-1; j += 2) {
half[j] = zval.v[full_lim+i+1];
half[j+1] = zval.v[full_lim+i];
half[j] = zval.v[full_lim+j+1];
half[j+1] = zval.v[full_lim+j];
}
if (j < zval.len-full_lim) {
half[j] = (HALF)0;
@@ -562,7 +574,7 @@ hash_complex(int type, void *c, HASH *state)
/*
* hash_str - hash a string
* hash_str - hash a null-terminated string
*
* given:
* type - hash type (see hash.h)
@@ -606,6 +618,47 @@ hash_str(int type, char *str, HASH *state)
}
/*
* hash_STR - hash a STRING
*
* given:
* type - hash type (see hash.h)
* str - the STRING
* state - the state to hash or NULL
*
* returns:
* the new state
*/
HASH *
hash_STR(int type, STRING *str, HASH *state)
{
/*
* initialize if state is NULL
*/
if (state == NULL) {
state = hash_init(type, NULL);
}
/*
* setup for the string hash
*/
if (!state->bytes) {
(state->chkpt)(state);
state->bytes = TRUE;
}
/*
* hash the string
*/
(state->update)(state, (USB8*) str->s_str, (USB32) str->s_len);
/*
* all done
*/
return state;
}
/*
* hash_usb8 - hash an array of USB8s
*
@@ -693,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;
@@ -720,7 +772,7 @@ hash_value(int type, void *v, HASH *state)
/* strings have no setup */
/* hash this type */
state = hash_str(type, value->v_str->s_str, state);
state = hash_STR(type, value->v_str, state);
break;
case V_MAT:
@@ -785,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++) {
@@ -843,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,
@@ -862,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);
@@ -877,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);
@@ -900,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:
@@ -930,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

@@ -46,16 +46,21 @@ int
main(void)
{
#if defined(HAVE_NO_CONST)
printf("#undef HAVE_CONST /* no */\n");
printf("#undef CONST\n");
printf("#define CONST /* no */\n");
#else /* HAVE_NO_CONST */
const char * const str = "const";
printf("#define HAVE_CONST /* yes */\n");
printf("#undef CONST\n");
printf("#define CONST %s /* yes */\n", str);
#endif /* HAVE_NO_CONST */
/* exit(0); */
return 0;
}

60
have_getpgid.c Normal file
View File

@@ -0,0 +1,60 @@
/*
* have_getpgid - Determine if we getpgid()
*
* usage:
* have_getpgid
*
* Not all systems have the getpgid() function, so this may not
* compile on your system.
*
* This prog outputs several defines:
*
* HAVE_GETPGID
* defined ==> use getpgid()
* undefined ==> do not or cannot call getpgid()
*/
/*
* Copyright (c) 1999 by Landon Curt Noll. All Rights Reserved.
*
* Permission to use, copy, modify, and distribute this software and
* its documentation for any purpose and without fee is hereby granted,
* provided that the above copyright, this permission notice and text
* this comment, and the disclaimer below appear in all of the following:
*
* supporting documentation
* source copies
* source works derived from this source
* binaries derived from this source or from derived source
*
* LANDON CURT NOLL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
* EVENT SHALL LANDON CURT NOLL BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*
* chongo was here /\../\
*/
#include <sys/types.h>
#include <unistd.h>
int
main(void)
{
#if defined(HAVE_NO_GETPGID)
printf("#undef HAVE_GETPGID /* no */\n");
#else /* HAVE_NO_GETPGID */
(void) getpgid((pid_t)0);
printf("#define HAVE_GETPGID /* yes */\n");
#endif /* HAVE_NO_GETPGID */
/* exit(0); */
return 0;
}

59
have_getprid.c Normal file
View File

@@ -0,0 +1,59 @@
/*
* have_getprid - Determine if we getprid()
*
* usage:
* have_getprid
*
* Not all systems have the getprid() function, so this may not
* compile on your system.
*
* This prog outputs several defines:
*
* HAVE_GETPRID
* defined ==> use getprid()
* undefined ==> do not or cannot call getprid()
*/
/*
* Copyright (c) 1999 by Landon Curt Noll. All Rights Reserved.
*
* Permission to use, copy, modify, and distribute this software and
* its documentation for any purpose and without fee is hereby granted,
* provided that the above copyright, this permission notice and text
* this comment, and the disclaimer below appear in all of the following:
*
* supporting documentation
* source copies
* source works derived from this source
* binaries derived from this source or from derived source
*
* LANDON CURT NOLL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
* EVENT SHALL LANDON CURT NOLL BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*
* chongo was here /\../\
*/
#include <sys/types.h>
#include <unistd.h>
int
main(void)
{
#if defined(HAVE_NO_GETPRID)
printf("#undef HAVE_GETPRID /* no */\n");
#else /* HAVE_NO_GETPRID */
(void) getprid();
printf("#define HAVE_GETPRID /* yes */\n");
#endif /* HAVE_NO_GETPRID */
/* exit(0); */
return 0;
}

59
have_getsid.c Normal file
View File

@@ -0,0 +1,59 @@
/*
* have_getsid - Determine if we getsid()
*
* usage:
* have_getsid
*
* Not all systems have the getsid() function, so this may not
* compile on your system.
*
* This prog outputs several defines:
*
* HAVE_GETSID
* defined ==> use getsid()
* undefined ==> do not call or cannot call getsid()
*/
/*
* Copyright (c) 1999 by Landon Curt Noll. All Rights Reserved.
*
* Permission to use, copy, modify, and distribute this software and
* its documentation for any purpose and without fee is hereby granted,
* provided that the above copyright, this permission notice and text
* this comment, and the disclaimer below appear in all of the following:
*
* supporting documentation
* source copies
* source works derived from this source
* binaries derived from this source or from derived source
*
* LANDON CURT NOLL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
* EVENT SHALL LANDON CURT NOLL BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*
* chongo was here /\../\
*/
#include <sys/types.h>
int
main(void)
{
#if defined(HAVE_NO_GETSID)
printf("#undef HAVE_GETSID /* no */\n");
#else /* HAVE_NO_GETSID */
(void) getsid((pid_t)0);
printf("#define HAVE_GETSID /* yes */\n");
#endif /* HAVE_NO_GETSID */
/* exit(0); */
return 0;
}

74
have_gettime.c Normal file
View File

@@ -0,0 +1,74 @@
/*
* have_gettime - Determine if we clock_gettime()
*
* usage:
* have_gettime
*
* Not all systems have the clock_gettime() function, so this may not
* compile on your system.
*
* This prog outputs several defines:
*
* HAVE_GETTIME
* defined ==> use clock_gettime() for either CLOCK_SGI_CYCLE
* and/or CLOCK_REALTIME
* undefined ==> clock_gettime() is not available for both
* CLOCK_SGI_CYCLE and CLOCK_REALTIME
*/
/*
* Copyright (c) 1999 by Landon Curt Noll. All Rights Reserved.
*
* Permission to use, copy, modify, and distribute this software and
* its documentation for any purpose and without fee is hereby granted,
* provided that the above copyright, this permission notice and text
* this comment, and the disclaimer below appear in all of the following:
*
* supporting documentation
* source copies
* source works derived from this source
* binaries derived from this source or from derived source
*
* LANDON CURT NOLL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
* EVENT SHALL LANDON CURT NOLL BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*
* chongo was here /\../\
*/
#include <time.h>
int
main(void)
{
#if defined(HAVE_NO_GETTIME)
printf("#undef HAVE_GETTIME /* no */\n");
#else /* HAVE_NO_GETTIME */
# if defined(CLOCK_SGI_CYCLE)
struct timespec sgi_cycle; /* SGI hardware clock */
(void) clock_gettime(CLOCK_SGI_CYCLE, &sgi_cycle);
printf("#define HAVE_GETTIME /* yes - w/CLOCK_SGI_CYCLE */\n");
# elif defined(CLOCK_REALTIME)
struct timespec realtime; /* POSIX realtime clock */
(void) clock_gettime(CLOCK_REALTIME, &realtime);
printf("#define HAVE_GETTIME /* yes - CLOCK_REALTIME only */\n");
# else
printf("#undef HAVE_GETTIME /* no - no SGI_CYCLE and no REALTIME */\n");
# endif /* CLOCK_REALTIME */
#endif /* HAVE_NO_GETTIME */
/* exit(0); */
return 0;
}

View File

@@ -2,7 +2,7 @@
* have_memmv - Determine if we memmove()
*
* usage:
* have_newstr
* have_memmv
*
* Not all systems with memcpy() have memmove() functions, so this may not
* compile on your system.
@@ -48,12 +48,17 @@ int
main(void)
{
#if defined(HAVE_NO_MEMMOVE)
printf("#undef HAVE_MEMMOVE /* no */\n");
#else /* HAVE_NO_MEMMOVE */
(void) memmove(dest, src, MOVELEN);
printf("#define HAVE_MEMMOVE /* yes */\n");
#endif /* HAVE_NO_MEMMOVE */
/* exit(0); */
return 0;
}

View File

@@ -50,14 +50,19 @@ int
main(void)
{
#if defined(HAVE_NO_NEWSTR)
printf("#undef HAVE_NEWSTR /* no */\n");
#else /* HAVE_NO_NEWSTR */
(void) memcpy(dest, src, MOVELEN);
(void) memset(dest, 0, MOVELEN);
(void) strchr(src, 'e');
printf("#define HAVE_NEWSTR /* yes */\n");
#endif /* HAVE_NO_NEWSTR */
/* exit(0); */
return 0;
}

62
have_rusage.c Normal file
View File

@@ -0,0 +1,62 @@
/*
* have_rusage - Determine if we getrusage()
*
* usage:
* have_rusage
*
* Not all systems have the getrusage() function, so this may not
* compile on your system.
*
* This prog outputs several defines:
*
* HAVE_GETRUSAGE
* defined ==> use getrusage()
* undefined ==> do not call or cannot call getrusage()
*/
/*
* Copyright (c) 1999 by Landon Curt Noll. All Rights Reserved.
*
* Permission to use, copy, modify, and distribute this software and
* its documentation for any purpose and without fee is hereby granted,
* provided that the above copyright, this permission notice and text
* this comment, and the disclaimer below appear in all of the following:
*
* supporting documentation
* source copies
* source works derived from this source
* binaries derived from this source or from derived source
*
* LANDON CURT NOLL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
* EVENT SHALL LANDON CURT NOLL BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*
* chongo was here /\../\
*/
#include <sys/time.h>
#include <sys/resource.h>
int
main(void)
{
#if defined(HAVE_NO_GETRUSAGE)
printf("#undef HAVE_GETRUSAGE /* no */\n");
#else /* HAVE_NO_GETRUSAGE */
struct rusage rusage; /* resource utilization */
(void) getrusage(RUSAGE_SELF, &rusage);
printf("#define HAVE_GETRUSAGE /* yes */\n");
#endif /* HAVE_NO_GETRUSAGE */
/* exit(0); */
return 0;
}

62
have_strdup.c Normal file
View File

@@ -0,0 +1,62 @@
/*
* have_strdup - Determine if we strdup()
*
* usage:
* have_strdup
*
* Not all systems have the strdup() function, so this may not
* compile on your system.
*
* This prog outputs several defines:
*
* HAVE_STRDUP
* defined ==> use strdup()
* undefined ==> do not call or cannot call strdup()
*/
/*
* Copyright (c) 1999 by Landon Curt Noll. All Rights Reserved.
*
* Permission to use, copy, modify, and distribute this software and
* its documentation for any purpose and without fee is hereby granted,
* provided that the above copyright, this permission notice and text
* this comment, and the disclaimer below appear in all of the following:
*
* supporting documentation
* source copies
* source works derived from this source
* binaries derived from this source or from derived source
*
* LANDON CURT NOLL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
* EVENT SHALL LANDON CURT NOLL BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*
* chongo was here /\../\
*/
#include <string.h>
int
main(void)
{
#if defined(HAVE_NO_STRDUP)
printf("#undef HAVE_STRDUP /* no */\n");
#else /* HAVE_NO_STRDUP */
char *p;
p = strdup("#define HAVE_STRDUP /* yes */");
if (p != NULL) {
printf("%s\n", p);
}
#endif /* HAVE_NO_STRDUP */
/* exit(0); */
return 0;
}

View File

@@ -51,15 +51,20 @@ int
main(void)
{
#if defined(HAVE_NO_UID_T)
printf("#undef HAVE_UID_T /* no */\n");
#else /* HAVE_NO_UID_T */
uid_t curds;
extern uid_t geteuid();
curds = geteuid();
printf("#define HAVE_UID_T /* yes */\n");
#endif /* HAVE_NO_UID_T */
/* exit(0); */
return 0;
}

65
have_ustat.c Normal file
View File

@@ -0,0 +1,65 @@
/*
* have_ustat - Determine if we ustat()
*
* usage:
* have_ustat
*
* Not all systems have the ustat() function, so this may not
* compile on your system.
*
* This prog outputs several defines:
*
* HAVE_USTAT
* defined ==> use ustat()
* undefined ==> do not call or cannot call ustat()
*/
/*
* Copyright (c) 1999 by Landon Curt Noll. All Rights Reserved.
*
* Permission to use, copy, modify, and distribute this software and
* its documentation for any purpose and without fee is hereby granted,
* provided that the above copyright, this permission notice and text
* this comment, and the disclaimer below appear in all of the following:
*
* supporting documentation
* source copies
* source works derived from this source
* binaries derived from this source or from derived source
*
* LANDON CURT NOLL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
* EVENT SHALL LANDON CURT NOLL BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*
* chongo was here /\../\
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <ustat.h>
int
main(void)
{
#if defined(HAVE_NO_USTAT)
printf("#undef HAVE_USTAT /* no */\n");
#else /* HAVE_NO_USTAT */
struct stat stat_dot; /* stat of "." */
struct ustat ustat_dot; /* usage stat of "." */
(void) stat(".", &stat_dot);
(void) ustat(stat_dot.st_dev, &ustat_dot);
printf("#define HAVE_USTAT /* yes */\n");
#endif /* HAVE_NO_USTAT */
/* exit(0); */
return 0;
}

View File

@@ -57,11 +57,13 @@ try_this(char *fmt, ...)
va_list ap;
va_start(ap);
#if !defined(DONT_HAVE_VSPRINTF)
vsprintf(buf, fmt, ap);
#else
sprintf(buf, fmt, ap);
#endif
va_end(ap);
}

3
help.c
View File

@@ -121,9 +121,8 @@ givehelp(char *type)
"else %s no such help, try: help help;fi",
HELPDIR, type, pager, HELPDIR, type,
CUSTOMHELPDIR, type, pager, CUSTOMHELPDIR, type, ECHO);
if (conf->calc_debug > 0) {
if (conf->calc_debug & CALCDBG_SYSTEM) {
printf("%s\n", helpcmd);
sleep(3);
}
/* execute the help command */

View File

@@ -35,13 +35,12 @@ Q=@
# standard tools
#
NATIVE_CC= cc
NATIVE_CFLAGS=
LCC= cc
ICFLAGS=
ILDFLAGS=
SED= sed
SORT= sort
FMT= fmt
CMP= cmp
CAT= cat
# Standard and Builtin help files
#
@@ -68,13 +67,13 @@ 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
BLT_HELP_FILES_13= bugs changes
STD_HELP_FILES_14= contrib credit todo
STD_HELP_FILES_14= contrib credit wishlist todo
# These files are used in the following order to construct full
#
@@ -106,28 +105,29 @@ BLT_HELP_FILES= ${BLT_HELP_FILES_3} ${BLT_HELP_FILES_5} \
#
DETAIL_HELP= abs access acos acosh acot acoth acsc acsch address agd append \
appr arg arrow asec asech asin asinh assign atan atan2 atanh avg base \
bit blk blkcpy blkfree blocks bround btrunc ceil cfappr cfsim char \
cmdbuf cmp comb conj cos cosh cot coth count cp csc csch ctime delete \
den dereference det digit digits dp epsilon errcount errmax errno \
error eval exp fact factor fclose fcnt feof ferror fflush fgetc \
fgetfield fgetline fgets fgetstr fib files floor fopen forall fprintf \
fputc fputs fputstr frac free freeglobals freeredc freestatics frem \
freopen fscan fscanf fseek fsize ftell gcd gcdrem gd getenv hash head \
highbit hmean hnrmod hypot ilog ilog10 ilog2 im insert int inverse \
iroot isassoc isatty isblk isconfig isdefined iserror iseven isfile \
ishash isident isint islist ismat ismult isnull isnum isobj isobjtype \
isodd isprime isptr isqrt isrand israndom isreal isrel issimple issq \
isstr istype jacobi join lcm lcmfact lfactor ln lowbit ltol makelist \
matdim matfill matmax matmin matsum mattrace mattrans max md5 memsize \
meq min minv mmin mne mod modify name near newerror nextcand \
nextprime norm null num oldvalue ord param perm pfact pi pix places \
pmod polar poly pop popcnt power prevcand prevprime printf prompt \
protect ptest push putenv quo quomod rand randbit random randombit \
randperm rcin rcmul rcout rcpow rcsq re remove reverse rewind rm root \
round rsearch runtime saveval scale scan scanf search sec sech \
segment select sgn sha sha1 sin sinh size sizeof sort sqrt srand \
srandom ssq str strcat strerror strlen strpos strprintf strscan \
strscanf substr sum swap system tail tan tanh test time trunc xor
bit blk blkcpy blkfree blocks bround btrunc calclevel ceil cfappr \
cfsim char cmdbuf cmp comb conj cos cosh cot coth count cp csc csch \
ctime delete den dereference det digit digits dp epsilon errcount \
errmax errno error eval exp fact factor fclose fcnt feof ferror \
fflush fgetc fgetfield fgetline fgets fgetstr fib files floor fopen \
forall fprintf fputc fputs fputstr frac free freeglobals freeredc \
freestatics frem freopen fscan fscanf fseek fsize ftell gcd gcdrem \
gd getenv hash head highbit hmean hnrmod hypot ilog ilog10 ilog2 \
im indices inputlevel insert int inverse iroot isassoc isatty isblk \
isconfig isdefined iserror iseven isfile ishash isident isint islist \
ismat ismult isnull isnum isobj isobjtype isodd isprime isptr isqrt \
isrand israndom isreal isrel issimple issq isstr istype jacobi join \
lcm lcmfact lfactor ln lowbit ltol makelist matdim matfill matmax \
matmin matsum mattrace mattrans max md5 memsize meq min minv mmin \
mne mod modify name near newerror nextcand nextprime norm null \
num oldvalue ord param perm pfact pi pix places pmod polar poly \
pop popcnt power prevcand prevprime printf prompt protect ptest \
push putenv quo quomod rand randbit random randombit randperm rcin \
rcmul rcout rcpow rcsq re remove reverse rewind rm root round rsearch \
runtime saveval scale scan scanf search sec sech seed segment select \
sgn sha sha1 sin sinh size sizeof sort sqrt srand srandom ssq str \
strcat strerror strlen strpos strprintf strscan strscanf substr \
sum swap system tail tan tanh test time trunc xor
# This list is of files that are clones of DETAIL_HELP files. They are
# built from DETAIL_HELP files.
@@ -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 $@
@@ -233,7 +225,7 @@ bugs: ../BUGS
errorcodes: ../calcerr.h errorcodes.hdr errorcodes.sed
rm -f $@
${CAT} errorcodes.hdr > $@
cat errorcodes.hdr > $@
${SED} -n -f errorcodes.sed < ../calcerr.h >> $@
chmod 0444 $@
-@if [ -z "${Q}" ]; then \
@@ -258,7 +250,7 @@ calc: usage
custom_cal: ../custom/CUSTOM_CAL
rm -f $@
cp usage $@
cp ../custom/CUSTOM_CAL $@
chmod 0444 $@
-@if [ -z "${Q}" ]; then \
echo ''; \
@@ -270,7 +262,7 @@ custom_cal: ../custom/CUSTOM_CAL
new_custom: ../custom/HOW_TO_ADD
rm -f $@
cp usage $@
cp ../custom/HOW_TO_ADD $@
chmod 0444 $@
-@if [ -z "${Q}" ]; then \
echo ''; \
@@ -282,7 +274,7 @@ new_custom: ../custom/HOW_TO_ADD
copy: blkcpy
rm -f $@
cp usage $@
cp blkcpy $@
chmod 0444 $@
-@if [ -z "${Q}" ]; then \
echo ''; \
@@ -358,17 +350,13 @@ ${SINGULAR_FILES}: ${PLURAL_FILES}
#
builtin: builtin.top builtin.end ../func.c funclist.sed
${Q}echo "forming builtin help file"
-${Q}rm -f builtin
${Q}cat builtin.top > builtin
-${Q}rm -f funclist.c
${Q}${SED} -n -f funclist.sed ../func.c > funclist.c
-${Q}rm -f ../funclist.c ../funclist.o ../funclist funclist
${Q}cp funclist.c ..
-${Q}(cd ..; \
${NATIVE_CC} ${NATIVE_CFLAGS} -DFUNCLIST funclist.c -o funclist; \
mv funclist help; \
rm -f funclist.c funclist.o funclist)
-${Q}rm -f funclist.o funclist
${Q}${LCC} ${ICFLAGS} -DFUNCLIST -I/usr/include -I.. funclist.c -c
${Q}${LCC} ${ILDFLAGS} funclist.o -o funclist
-${Q}rm -f builtin
${Q}cat builtin.top > builtin
${Q}./funclist | \
${SED} -e 's/^/ /' -e 's/[ ][ ]*$$//' >> builtin
${Q}cat builtin.end >> builtin
@@ -393,15 +381,18 @@ builtin: builtin.top builtin.end ../func.c funclist.sed
distlist: ${DISTLIST}
${Q}for i in ${DISTLIST}; do \
echo calc/help/$$i; \
echo help/$$i; \
done | ${SORT}
# The bsdi distribution has generated files as well as distributed files.
#
bsdilist: ${DISTLIST} ${BLT_HELP_FILES}
${Q}for i in ${DISTLIST} ${BLT_HELP_FILES}; do \
echo calc/help/$$i; \
done | ${SORT}
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
@@ -416,8 +407,8 @@ bsdi: all
detaillist:
${Q}-(echo "xxxxx"; \
for i in ${DETAIL_HELP}; do \
if [ ! -f SCCS/s.$$i ]; then \
echo "WARNING: $$i not under SCCS control" 1>&2; \
if [ ! -f RCS/$$i,v ]; then \
echo "WARNING: $$i not under RCS control" 1>&2; \
else \
echo $$i; \
fi; \

View File

@@ -1,31 +1,16 @@
Where to get the the latest versions of calc
Landon Noll maintains the official calc ftp archive at:
Landon Noll maintains the official calc home page at:
ftp://ftp.uu.net/pub/calc
Alpha test versions, complete with bugs, untested code and
experimental features may be fetched (if you are brave) under:
http://reality.sgi.com/chongo/calc/
One may join the calc testing group by sending a request to:
calc-tester-request@postofc.corp.sgi.com
Your message body (not the subject) should consist of:
subscribe calc-tester address
end
name your_full_name
where "address" is your EMail address and "your_full_name"
is your full name.
http://reality.sgi.com/chongo/tech/comp/calc/
See:
http://prime.corp.sgi.com/csp/ioccc/noll/noll.html#calc
http://reality.sgi.com/chongo/tech/comp/calc/calc-download.html
for details.
for information on how to obtain up a recent version of calc.
Landon Curt Noll <chongo@toad.com> /\oo/\
Landon Curt Noll
http://reality.sgi.com/chongo/
chongo <was here> /\../\

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

35
help/calclevel Normal file
View File

@@ -0,0 +1,35 @@
NAME
calclevel - current calculation level
SYNOPSIS
calclevel()
TYPES
return nonnegative integer
DESCRIPTION
This function returns the calculation level at which it is called.
When a command is being read from a terminal or from a file,
calc is at calculation level zero. The level is increased
by 1 each time calculation starts of a user-defined function
or of eval(S) for some expression S which evaluates to a string. It
decreases to zero if an error occurs or a quit or abort statement
is executed. Otherwise, it decreases by 1 when the calculation
is completed. Except when an error occurs or abort is executed,
the input level is not affected by changes in the calculation level.
Zero calculation level is also called top calculation level; greater
values of calclevel() indicate calculation is occurring at greater
depths.
EXAMPLE
n/a
LIMITS
none
LIBRARY
none
SEE ALSO
eval, read, quit, abort, inputlevel

View File

@@ -14,12 +14,10 @@ Command sequence
described in the next section.
NOTE: Calc commands are in lower case. UPPER case is used below
for emphasis only, and should be considered in lower case.
DEFINE function(params) { body }
DEFINE function(params) = expression
define a function
-----------------
define function(params) { body }
define function(params) = expression
This first form defines a full function which can consist
of declarations followed by many statements which implement
the function.
@@ -30,13 +28,22 @@ Command sequence
and question mark operators can be useful. Examples of
simple functions are:
define sumcubes(a, b) = a^3 + b^3;
define pimod(a) = a % pi();
define sumcubes(a, b) = a^3 + b^3
define pimod(a) = a % pi()
define printnum(a, n, p)
{
if (p == 0) {
print a: "^": n, "=", a^n;
} else {
print a: "^": n, "mod", p, "=", pmod(a,n,p);
}
}
HELP
This displays a general help message.
READ filename
read calc commands
------------------
read filename
read -once filename
This reads definitions from the specified filename.
The name can be quoted if desired. The calculator
uses the CALCPATH environment variable to search
@@ -52,14 +59,11 @@ Command sequence
evaluate or functions to define, just like at the top
level command level.
If the -m mode disallows opening of files for reading,
this command will be disabled.
When -once is given, the read command acts like the regular
read expect that it will ignore filename if is has been
previously read.
READ -once filename
This command acts like the regular READ expect that it
will ignore filename if is has been previously read.
This command is particularly useful in a library that
The read -once form is particularly useful in a library that
needs to read a 2nd library. By using the READ -once
command, one will not reread that 2nd library, nor will
once risk entering into a infinite READ loop (where
@@ -69,7 +73,10 @@ Command sequence
If the -m mode disallows opening of files for reading,
this command will be disabled.
WRITE filename
write calc commands
-------------------
write filename
This writes the values of all global variables to the
specified filename, in such a way that the file can be
later read in order to recreate the variable values.
@@ -81,19 +88,221 @@ Command sequence
If the -m mode disallows opening of files for writing,
this command will be disabled.
QUIT
This leaves the calculator, when given as a top-level
command.
CD
Change the current directory to the home directory, if $HOME
quit or exit
------------
quit
quit string
exit
exit string
The action of these commands depends on where they are used.
At the interactive level, they will cause calc it edit.
This is the normal way to leave the calculator. In any
other use, they will stop the current calculation as if
an error had occurred.
If a string is given, then the string is printed as the reason
for quitting, otherwise a general quit message is printed.
The routine name and line number which executed the quit is
also printed in either case.
Exit is an alias for quit.
Quit is useful when a routine detects invalid arguments,
in order to stop a calculation cleanly. For example,
for a square root routine, an error can be given if the
supplied parameter was a negative number, as in:
define mysqrt(n)
{
if (! isnum(n))
quit "non-numeric argument";
if (n < 0)
quit "Negative argument";
return sqrt(n);
}
See 'more information about abort and quit' below for
more information.
abort
-----
abort
abort string
This command behaves like QUIT except that it will attempt
to return to the interactive level if permitted, otherwise
calc exit.
See 'more information about abort and quit' below for
more information.
change current directory
------------------------
cd
cd dir
Change the current directory to 'dir'. If 'dir' is ommitted,
change the current directory to the home directory, if $HOME
is set in the environment.
CD dir
Change the current directory to dir.
show information
----------------
show item
This command displays some information where 'item' is
one of the following:
blocks unfreed named blocks
builtin built in functions
config config parameters and values
constants cache of numeric constants
custom custom functions if calc -C was used
errors new error-values created
files open files, file position and sizes
function user-defined functions
globaltypes global variables
objfunctions possible object functions
objtypes defined objects
opcodes func internal opcodes for function `func'
sizes size in octets of calc value types
realglobals numeric global variables
statics unscoped static variables
numbers calc number cache
redcdata REDC data defined
strings calc string cache
literals calc literal cache
Only the first 4 characters of item are examined, so:
show globals
show global
show glob
do the same thing.
calc help
---------
help
help name
This displays a help related to 'name' or general
help of none is given.
=-=
more information about abort and quit
=====================================
Consider the following calc file called myfile.cal:
print "start of myfile.cal";
define q() {quit "quit from q()"; print "end of q()"}
define a() {abort "abort from a()"}
x = 3;
{print "start #1"; if (x > 1) q()} print "after #1";
{print "start #2"; if (x > 1) a()} print "after #2";
{print "start #3"; if (x > 1) quit "quit from 3rd statement"}
print "end of myfile.cal";
The command:
calc read myfile
will produce:
q() defined
a() defined
start statment #1
quit from q()
after statment #1
start statment #2
abort from a()
The QUIT within the q() function prevented the ``end of q()''
statement from being evaluated. This QUIT command caused
control to be returned to just after the place where q()
was called.
Notice that unlike QUIT, the ABORT inside function a() halts
the processing of statements from the input source (myfile.cal).
Because calc was not interactive, ABORT causes calc to exit.
The command:
calc -i read myfile
will produce:
q() defined
a() defined
start statment #1
quit from q()
after statment #1
start statment #2
abort from a()
> <==== calc interactive prompt
because the '-i' calc causes ABORT to drop into an
interactive prompt. However typing a QUIT or ABORT
at the interactive prompt level will always calc to exit,
even when calc is invoked with '-i'.
Also observe that both of these commands:
cat myfile.cal | calc
cat myfile.cal | calc -i
will produce:
q() defined
a() defined
start statment #1
quit from q()
after statment #1
start statment #2
abort from a()
The ABORT inside function a() halts the processing of statements
from the input source (standard input). Because standard input
is not a terminal, using '-i' does not force it to drop into
an interactive prompt.
If one were to type in the contents of myfile.cal interactively,
calc will produce:
> print "start of myfile.cal";
start of myfile.cal
> define q() {quit "quit from q()"; print "end of q()"}
q() defined
> define a() {abort "abort from a()"}
a() defined
> x = 3;
> {print "start #1"; if (x > 1) q()} print "after #1";
start statment #1
quit from q()
after statment #1
> {print "start #2"; if (x > 1) a()} print "after #2";
start statment #2
abort from a()
> {print "start #3"; if (x > 1) quit "quit from 3rd statement"}
start #3
quit from 3rd statement
The ABORT from within the a() function returned control to
the interactive level.
The QUIT (after the if (x > 1) ...) will cause calc to exit
because it was given at the interactive prompt level.
=-=
Also see the help topic:
statement flow control and declaration statements
usage for -m modes
usage how to invoke the calc command and calc -options

View File

@@ -40,10 +40,11 @@ Configuration parameters
"blkverbose" TRUE=>print all lines, FALSE=>skip duplicates
"blkbase" block output base
"blkfmt" block output format
"lib_debug" calc library script debug level
"calc_debug" internal calc debug level
"user_debug" user defined debug level
"calc_debug" controls internal calc debug information
"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:
@@ -78,7 +79,45 @@ Configuration parameters
The "newstd" is not backward compatible with the historic
configuration. Even so, some people prefer this configuration
and place the config("all", "newstd") command in their CALCRC
startup files.
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
@@ -99,13 +138,25 @@ 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
formatted printing (printf, strprintf, fprintf) when precision is not
specified. The initial value is 20. This parameter does not change
the stored value of a number. Where rounding is necessary, the type
of rounding to be used is controlled by "outround".
specified. The initial value for oldstd is 20, for newstd 10.
The parameter may be changed to the value d by either
config("display", d) or by display (d). This parameter does not change
the stored value of a number. Where rounding is necessary to
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
@@ -118,28 +169,65 @@ Configuration parameters
absolute value of the remainder usually does not exceed epsilon/2.
Functions which require an epsilon value accept an
optional argument which overrides this default epsilon value for
that single call. (The value v can be assigned to the "epsilon"
parameter by epsilon(v) as well as by config("epsilon", v), and the
current value obtained by epsilon() as well as by config("epsilon").)
that single call. The value v can be assigned to the "epsilon"
parameter by either config("epsilon", v) or epsilon(v); each of
these functions return the current epsilon value; config("epsilon")
or epsilon() returns but does not change the epsilon value.
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
@@ -157,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
@@ -165,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
@@ -173,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
@@ -228,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
@@ -240,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:
@@ -253,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
@@ -272,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"
@@ -290,101 +439,201 @@ 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.
With regards to "lib_debug", "calc_debug" and "user_debug":
higher absolute values result in more detailed debugging and
more verbose debug messages. The default value is 0 in which
a very amount of debugging will be performed with nil messages.
The -1 value is reserved for no debugging or messages. Any
value <-1 will perform debugging silently (presumably collecting
data to be displayed at a later time). Values >0 result in a
greater degree of debugging and more verbose messages.
The default "blkfmt" is "hd_style".
The "lib_debug" is reserved by convention for calc library scripts.
This config parameter takes the place of the lib_debug global variable.
By convention, "lib_debug" has the following meanings:
=-=
<-1 no debug messages are printed though some internal
debug actions and information may be collected
config("calc_debug", bitflag)
-1 no debug messages are printed, no debug actions will be taken
The "calc_debug" is intended for controlling internal calc routines
that test its operation, or collect or display information that
might be useful for debug purposes. Much of the output from these
will make sense only to calc wizards. Zero value (the default for
both oldstd and newstd) of config("lib_calc") corresponds to switching
off all these routines. For nonzero value, particular bits
currently have the following meanings:
0 only usage message regarding each important object are
printed at the time of the read (default)
n Meaning of bit n of config("calc_debug")
>0 messages regarding each important object are
printed at the time of the read in addition
to other debug messages
0 outputs shell commands prior to execution
The "calc_debug" is reserved by convention for internal calc routines.
The output of "calc_debug" will change from release to release.
Generally this value is used by calc wizards and by the regress.cal
routine (make check). By convention, "calc_debug" has the following
meanings:
1 outputs currently active functions when a quit instruction
is executed
<-1 reserved for future use
2 some details of shs, shs1 and md5 hash states are included
in the output when these are printed
-1 no debug messages are printed, no debug actions will be taken
3 when a function constructs a block value, tests are
made that the result has the properties required for use of
that block, e.g. that the pointer to the start of the
block is not NULL, and that its "length" is not negative.
A failure will result in a runtime error.
0 very little, if any debugging is performed (and then mostly
in alpha test code). The only output is as a result of
internal fatal errors (typically either math_error() or
exit() will be called). (default)
4 Report on changes to the state of stdin as well as changes
to internal variables that control the setting and restoring
of stdin.
>0 a greater degree of debugging is performed and more
verbose messages are printed (regress.cal uses 1).
5 Report on changes to the run state of calc.
Bits >= 6 are reserved for future use and should not be used at this time.
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.
Zero value of config("lib_debug") means that no such information
is displayed. For other values, the non-zero bits which currently
have meanings are as follows:
n Meaning of bit n of config("lib_debug")
0 When a function is defined, redefined or undefined at
interactive level, a message saying what has been done
is displayed.
1 When a function is defined, redefined or undefined during
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")
is changed, a message will be output when a function is defined
either interactively or during the reading of a file.
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 will change this value other than
during startup or during a config("all", xyz) call.
No calc code or shipped library should change this value. Users
should feel free to use it in any way. In particular they may
use particular bits for special purposes as with "calc_debug", or
they may use it to indicate a debug level with larger values
indicating more stringent and more informative tests with presumably
slower operation or more memory usage, and a particular value (like
-1 or 0) corresponding to "no tests".
The following is suggested as a convention for use of "user_debug".
These are only suggestions: feel free to use it as you like:
By default, "user_debug" is 0. The initial value may be overridden
by the -D command line option.
<-1 no debug messages are printed though some internal
debug actions and information may be collected
=-=
-1 no debug messages are printed, no debug actions will be taken
config("verbose_quit", bool)
0 very little, if any debugging is performed. The only output
are from fatal errors. (default)
The "verbose_quit" controls the print of the message:
>0 a greater degree of debugging is performed and more
verbose messages are printed
Quit or abort executed
The following are synonyms for true:
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.
"on" "yes" "y" "true" "t" "1" any non-zero number
=-=
The following are synonyms for false:
config("ctrl_d", "ctrl_d_string")
"off" "no" "n" "false" "f" "0" the number zero (0)
For calc that is using the calc binding (not GNU-readline) facility:
Examples of setting some parameters are:
The "ctrl_d" controls the interactive meaning of ^D (Control D):
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
"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.
"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

@@ -5,30 +5,27 @@ We welcome and encourage you to send us:
* custom functions that you have modified or written
* any other source code modifications
Prior to doing so, you should consider trying your changes on the most
recent alpha test code. To obtain the most recent code, look under
Prior to doing so, you should consider applying your changes to the most
recent version of calc.
http://reality.sgi.com/chongo/calc/
Landon Noll maintains the official calc home page at:
You should also consider joining the calc testing group by sending a
request to:
http://reality.sgi.com/chongo/tech/comp/calc/
calc-tester-request@postofc.corp.sgi.com
See:
Your message body (not the subject) should consist of:
http://reality.sgi.com/chongo/tech/comp/calc/calc-download.html
subscribe calc-tester address
end
name your_full_name
for information on how to obtain up a recent version of calc.
where "address" is your EMail address and "your_full_name"
is your full name.
=-=
In order to consider integrating your code, we need:
* help files (documentation)
* CHANGES text (brief description of what it does)
* regress.cal test (to test non-custom code)
* the calc version you are working with (use the latest calc, see above)
* new help files or help file patches, if applicable (documentation)
* proposed text for the CHANGES file (brief description of what it does)
* regress.cal test patch, if applicable
* your source code and/or source code changes (:-))
The best way to send us new code, if your changes are small, is
@@ -39,10 +36,44 @@ gziped (or compressed) tar file).
You should send submissions to:
calc-tester@postofc.corp.sgi.com
calc-tester at postofc dot corp dot sgi dot com
[[ Replace 'at' with @, 'dot' is with . and remove the spaces ]]
Thanks for considering submitting code to calc. Calc is a collective
work by a number of people. It would not be what it is today without
your efforts and submissions!
Landon Curt Noll <chongo@toad.com> /\oo/\
Calc bug reports, however, should be sent to:
calc-bugs at postofc dot corp dot sgi dot com
[[ Replace 'at' with @, 'dot' is with . and remove the spaces ]]
See the BUGS file or try the help command:
help bugs
for details on bug reporting.
=-=
One may join the calc testing group by sending a request to:
calc-tester-request at postofc dot corp dot sgi dot com
[[ Replace 'at' with @, 'dot' is with . and remove the spaces ]]
Your message body (not the subject) should consist of:
subscribe calc-tester address
end
name your_full_name
where "address" is your EMail address and "your_full_name"
is your full name.
Landon Curt Noll
http://reality.sgi.com/chongo/
chongo <was here> /\../\

View File

@@ -2,7 +2,11 @@ Credits
The majority of calc was written by David I. Bell.
Calc archives and calc-tester mailing list maintained by Landon Curt Noll.
The Calc primary mirror, calc mailing list and calc bug report
processing is performed by Landon Curt Noll.
Landon Curt Noll maintains the master reference source, performs
release control functions as well as other calc maintenance functions.
Thanks for suggestions and encouragement from Peter Miller,
Neil Justusson, and Landon Noll.
@@ -22,41 +26,10 @@ Credits
Most of this source and binary has one of the following copyrights:
Copyright (c) 19xx David I. Bell
Copyright (c) 19xx David I. Bell and Landon Curt Noll
Copyright (c) 19xx Landon Curt Noll
Copyright (c) 19xx Ernest Bowen and Landon Curt Noll
Copyright (c) year David I. Bell
Copyright (c) year David I. Bell and Landon Curt Noll
Copyright (c) year Landon Curt Noll
Copyright (c) year Ernest Bowen and Landon Curt Noll
Permission is granted to use, distribute, or modify this source,
provided that this copyright notice remains intact.
Send calc comments, suggestions, bug fixes, enhancements and
interesting calc scripts that you would like you see included in
future distributions to:
dbell@auug.org.au
chongo@toad.com
Landon Noll maintains the official calc ftp archive at:
ftp://ftp.uu.net/pub/calc
Alpha test versions, complete with bugs, untested code and
experimental features may be fetched (if you are brave) under:
http://reality.sgi.com/chongo/calc/
One may join the calc testing group by sending a request to:
calc-tester-request@postofc.corp.sgi.com
Your message body (not the subject) should consist of:
subscribe calc-tester address
end
name your_full_name
where "address" is your EMail address and "your_full_name"
is your full name.
Enjoy!

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:
@@ -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.
@@ -58,6 +56,10 @@ Environment variables
a terminal, then calc will still run, but fancy command line
editing is disabled.
NOTE: If calc was compiled with GNU-readline support, the
CALCBINDINGS facility is ignored and the standard
readline mechanisms (see readline(3)) are used.
HOME
This value is taken to be the home directory of the

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

@@ -22,7 +22,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

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

@@ -3,7 +3,5 @@ s/NUMBER[ ]*\*/int /
s/NUMBER/int/
s/STRINGHEAD/int/
s/\(".*",.*,.*\),.*,.*,.*,.*,/\1, 0, 0, 0, 0,/
/sed me out/d
s/showbuiltins/main/
s/[ ][ ]*$//
p

View File

@@ -1,5 +1,5 @@
NAME
hash - hash value
hash - FNV-1 hash value
SYNOPSIS
hash(x_1 [, x_2, x_3, ...])
@@ -12,10 +12,32 @@ TYPES
DESCRIPTION
Returns a hash value for one or more values of arbitrary types.
The basis of this hash algorithm was taken from an idea sent
as reviewer comments to the IEEE POSIX P1003.2 committee by:
Phong Vo (http://www.research.att.com/info/kpv/)
Glenn Fowler (http://www.research.att.com/~gsf/)
In a subsequent ballot round:
Landon Curt Noll (http://reality.sgi.com/chongo/)
improved on their algorithm. Some people tried this hash
and found that it worked rather well. In an EMail message
to Landon, they named it ``Fowler/Noll/Vo'' or the FNV hash.
FNV hashes are architected to be fast while maintaining a low
collision rate. The FNV speed allows one to quickly hash lots
of data while maintaining a reasonable collision rate. See:
http://reality.sgi.com/chongo/tech/comp/fnv/
for more details as well as other forms of the FNV hash.
EXAMPLE
> a = isqrt(2e1000); s = "xyz";
> hash(a,s)
870000771
2378490456
LIMITS
The number of arguments is not to exceed 100.
@@ -24,3 +46,4 @@ LIBRARY
none
SEE ALSO
sha, sha1, md5

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
@@ -42,7 +41,8 @@ following topics:
changes recent changes to calc
contrib how to contribute scripts, code or custom functions
credit who wrote calc and who helped
todo needed enhancements and wish list
todo list of priority action items for calc
wishlist wish list of future enhancements of calc
full all of the above (in the above order)

58
help/indices Normal file
View File

@@ -0,0 +1,58 @@
NAME
indices - indices for specified matrix or association element
SYNOPSIS
indices(V, index)
TYPES
V matrix or association
index integer
return list with up to 4 elements
DESCRIPTION
For 0 <= index < size(V), indices(V, index) returns list(i_0, i_1, ...)
for which V[i_0, i_1, ...] is the same lvalue as V[[index]].
For other values of index, a null value is returned.
This function can be useful for determining those elements for which
the indices satisfy some condition. This is particularly so for
associations since these have no simple relation between the
double-bracket index and the single-bracket indices, which may be
non-integer numbers or strings or other types of value. The
information provided by indices() is often required after the use
of search() or rsearch() which, when successful, return the
double-bracket index of the item found.
EXAMPLE
> mat M[2,3,1:5]
> indices(M, 11)
list (3 elements, 2 nonzero):
[[0]] = 0
[[1]] = 2
[[2]] = 2
> A = assoc();
> A["cat", "dog"] = "fight";
> A[2,3,5,7] = "primes";
> A["square", 3] = 9
> indices(A, search(A, "primes"))
list (4 elements, 4 nonzero):
[[0]] = 2
[[1]] = 3
[[2]] = 5
[[3]] = 7
LIMITS
abs(index) < 2^31
LIBRARY
LIST* associndices(ASSOC *ap, long index)
LIST* matindices(MATRIX *mp, long index)
SEE ALSO
assoc, mat

36
help/inputlevel Normal file
View File

@@ -0,0 +1,36 @@
NAME
inputlevel - current input level
SYNOPSIS
inputlevel()
TYPES
return nonnegative integer
DESCRIPTION
This function returns the input level at which it is called.
When calc starts, it is at level zero. The level is increased
by 1 each time execution starts of a read file command or a call to
eval(S) for some expression S which evaluates to a string. It
decreases by 1 when a file being read reaches EOF or a string
being eval-ed reaches '\0', or earlier if a quit statement is
encountered at top calculation-level in the flle or string. It
decreases to zero if an abort statement is encountered at any
function-level in the file or string. If a quit or abort
statement is encountered at top calculation-level at top input-level,
calc is exited.
Zero input level is also called top input level; greater values
of inputlevel() indicate reading at greater depths.
EXAMPLE
n/a
LIMITS
none
LIBRARY
none
SEE ALSO
read, eval, quit, abort, calclevel

View File

@@ -25,7 +25,7 @@ LIBRARY
none
SEE ALSO
rand, srand, randbit,
seed, rand, srand, randbit,
isassoc, isatty, isblk, isconfig, isdefined, iserror, iseven, isfile,
ishash, isident, isint, islist, ismat, ismult, isnull, isnum, isobj,
isobjtype, isodd, isprime, israndom, isreal, isrel,

View File

@@ -27,7 +27,7 @@ LIBRARY
none
SEE ALSO
random, srandom, randombit,
seed, random, srandom, randombit,
isassoc, isatty, isblk, isconfig, isdefined, iserror, iseven, isfile,
ishash, isident, isint, islist, ismat, ismult, isnull, isnum, isobj,
isobjtype, isodd, isprime, isrand, isreal, isrel,

457
help/mat
View File

@@ -1,102 +1,397 @@
Using matrices
NAME
mat - keyword to create a matrix value
Matrices can have from 1 to 4 dimensions, and are indexed by a
normal-sized integer. The lower and upper bounds of a matrix can
be specified at runtime. The elements of a matrix are defaulted
to zeroes, but can be assigned to be of any type. Thus matrices
can hold complex numbers, strings, objects, etc. Matrices are
stored in memory as an array so that random access to the elements
is easy.
SYNOPSIS
mat [index-range-list] [ = {value_0. ...} ]
mat [] [= {value_0, ...}]
mat variable_1 ... [index-range-list] [ = {value_0, ...} ]
mat variable_1 ... [] [ = {value_0, ...} ]
Matrices are normally indexed using square brackets. If the matrix
is multi-dimensional, then an element can be indexed either by
using multiple pairs of square brackets (as in C), or else by
separating the indexes by commas. Thus the following two statements
reference the same matrix element:
mat [index-range-list_1[index-ranges-list_2] ... [ = { { ...} ...} ]
x = name[3][5];
x = name[3,5];
decl id_1 id_2 ... [index-range-list] ...
The double-square bracket operator can be used on any matrix to
make references to the elements easy and efficient. This operator
bypasses the normal indexing mechanism, and treats the array as if
it was one-dimensional and with a lower bound of zero. In this
indexing mode, elements correspond to the normal indexing mode where
the rightmost index increases most frequently. For example, when
using double-square bracket indexing on a two-dimensional matrix,
increasing indexes will reference the matrix elements left to right,
row by row. Thus in the following example, 'x' and 'y' are copied
from the same matrix element:
TYPES
index-range-list range_1 [, range_2, ...] up to 4 ranges
range_1, ... integer, or integer_1 : integer_2
value, value_1, ... any
variable_1 ... lvalue
decl declarator = global, static or local
id_1, ... identifier
mat m[1:2, 1:3];
x = m[2,1];
y = m[[3]];
DESCRIPTION
The expression mat [index-range-list] returns a matrix value.
This may be assigned to one or more lvalues A, B, ... by either
There are functions which return information about a matrix.
The 'size' functions returns the total number of elements.
The 'matdim', 'matmin', and 'matmax' functions return the number
of dimensions of a matrix, and the lower and upper index bounds
for a dimension of a matrix. For square matrices, the 'det'
function calculates the determinant of the matrix.
mat A B ... [index-range-list]
Some functions return matrices as their results. These functions
do not affect the original matrix argument, but instead return
new matrices. For example, the 'mattrans' function returns the
transpose of a matrix, and 'inverse' returns the inverse of a
matrix. So to invert a matrix called 'x', you could use:
or
x = inverse(x);
A = B = ... = mat[index-range-list]
The 'matfill' function fills all elements of a matrix with the
specified value, and optionally fills the diagonal elements of a
square matrix with a different value. For example:
If a variable is specified by an expression that is not a symbol with
possibly object element specifiers, the expression should be enclosed
in parentheses. For example, parentheses are required in
mat (A[2]) [3] and mat (*p) [3] but mat P.x [3] is acceptable.
matfill(x,1);
When an index-range is specified as integer_1 : integer_2, where
integer_1 and integer_2 are expressions which evaluate to integers,
the index-range consists of all integers from the minimum of the
two integers to the maximum of the two integers. For example,
mat[2:5, 0:4] and mat[5:2, 4:0] return the same matrix value.
will fill any matrix with ones, and:
If an index-range is an expression which evaluates to an integer,
the range is as if specified by 0 : integer - 1. For example,
mat[4] and mat[0:3] return the same 4-element matrix; mat[-2] and
mat[-3:0] return the same 4-element matrix.
matfill(x, 0, 1);
If the variable A has a matrix value, then for integer indices
i_1, i_2, ..., equal in number to the number of ranges specified at
its creation, and such that each index is in the corresponding range,
the matrix element associated with those index list is given as an
lvalue by the expressions A[i_1, i_2, ...].
will create an identity matrix out of any square matrix. Note that
unlike most matrix functions, this function does not return a matrix
value, but manipulates the matrix argument itself.
The elements of the matrix are stored internally as a linear array
in which locations are arranged in order of increasing indices.
For example, in order of location, the six element of A = mat [2,3]
are
Matrices can be multiplied by numbers, which multiplies each element
by the number. Matrices can also be negated, conjugated, shifted,
rounded, truncated, fractioned, and modulo'ed. Each of these
operations is applied to each element.
A[0,0], A[0,1], A[0,2], A[1,0], A[1,,1], A[1,2].
Matrices can be added or multiplied together if the operation is
legal. Note that even if the dimensions of matrices are compatible,
operations can still fail because of mismatched lower bounds. The
lower bounds of two matrices must either match, or else one of them
must have a lower bound of zero. Thus the following code:
These elements may also be specified using the double-bracket operator
with a single integer index as in A[[0]], A[[1]], ..., A[[5]].
If p is assigned the value &A[0.0], the address of A[[i]] for 0 <= i < 6
is p + i as long as A exists and a new value is not assigned to A.
mat x[3:3];
mat y[4:4];
z = x + y;
When a matrix is created, each element is initially assigned the
value zero. Other values may be assigned then or later using the
"= {...}" assignment operation. Thus
fails because the calculator does not have a way of knowing what
the bounds should be on the resulting matrix. If the bounds match,
then the resulting matrix has the same bounds. If exactly one of
the lower bounds is zero, then the resulting matrix will have the
nonzero lower bounds. Thus means that the bounds of a matrix are
preserved when operated on by matrices with lower bounds of zero.
For example:
A = {value_0, value_1, ...}
mat x[3:7];
mat y[5];
z = x + y;
assigns the values value_0, value_1, ... to the elements A[[0]],
A[[1]], ... Any blank "value" is passed over. For example,
will succeed and assign the variable 'z' a matrix whose
bounds are 3-7.
A = {1, , 2}
Vectors are matrices of only a single dimension. The 'dp' and 'cp'
functions calculate the dot product and cross product of a vector
(cross product is only defined for vectors of size 3).
will assign the value 1 to A[[0]], 2 to A[[2]] and leave all other
elements unchanged. Values may also be assigned to elements by
simple assignments, as in A[0,0] = 1, A[0,2] = 2;
Matrices can be searched for particular values by using the 'search'
and 'rsearch' functions. They return the element number of the
found value (zero based), or null if the value does not exist in the
matrix. Using the element number in double-bracket indexing will
then refer to the found element.
If the index-range is left blank but an initializer list is specified
as in
mat A[] = {1, 2 }
B = mat[] = {1, , 3, }
the matrix created is one-dimensional. If the list contains a
positive number n of values or blanks, the result is as if the
range were specified by [n], i.e. the range of indices is from
0 to n - 1. In the above examples, A is of size 2 with A[0] = 1
and A[1] = 2; B is of size 4 with B[0] = 1, B[1] = B[3] = 0,
B[2] = 3. The specification mat[] = { } creates the same as mat[1].
If the index-range is left blank and no initializer list is specified,
as in mat C[] or C = mat[], the matrix assigned to C has zero
dimension; this has one element C[]. To assign a value using "= { ...}"
at the same time as creating C, parentheses are required as in
(mat[]) = {value} or (mat C[]) = {value}. Later a value may be
assigned to C[] by C[] = value or C = {value}.
The value assigned at any time to any element of a matrix can be of
any type - number, string, list, matrix, object of previously specified
type, etc. For some matrix operations there are of course conditions
that elements may have to satisfy: for example, addition of matrices
requires that addition of corresponding elements be possible.
If an element of a matrix is a structure for which indices or an
object element specifier is required, an element of that structure is
referred to by appropriate uses of [ ] or ., and so on if an element
of that element is required. For example, one may have an expressions
like
A[1,2][3].alpha[2];
if A[1,2][3].alpha is a list with at least three elements, A[1,2][3] is
an object of a type like obj {alpha, beta}, A[1,2] is a matrix of
type mat[4] and A is a mat[2,3] matrix. When an element of a matrix
is a matrix and the total number of indices does not exceed 4, the
indices can be combined into one list, e.g. the A[1,2][3] in the
above example can be shortened to A[1,2,3]. (Unlike C, A[1,2] cannot
be expressed as A[1][2].)
The function ismat(V) returns 1 if V is a matrix, 0 otherwise.
isident(V) returns 1 if V is a square matrix with diagonal elements 1,
off-diagonal elements zero, or a zero- or one-dimensional matrix with
every element 1; otherwise zero is returned. Thus isident(V) = 1
indicates that for V * A and A * V where A is any matrix of
for which either product is defined and the elements of A are real
or complex numbers, that product will equal A.
If V is matrix-valued, test(V) returns 0 if every element of V tests
as zero; otherwise 1 is returned.
The dimension of a matrix A, i.e. the number of index-ranges in the
initial creation of the matrix, is returned by the function matdim(A).
For 1 <= i <= matdim(A), the minimum and maximum values for the i-th
index range are returned by matmin(A, i) and matmax(A,i), respectively.
The total number of elements in the matrix is returned by size(A).
The sum of the elements in the matrix is returned by matsum(A).
The default method of printing matrices is to give a line of information
about the matrix, and to list on separate lines up to 15 elements,
the indices and either the value (for numbers, strings, objects) or
some descriptive information for lists or matrices, etc.
Numbers are displayed in the current number-printing mode.
The maximum number of elements to be printed can be assigned
any nonnegative integer value m by config("maxprint", m).
Users may define another method of printing matrices by defining a
function mat_print(M); for example, for a not too big 2-dimensional
matrix A it is a common practice to use a loop like:
for (i = matmin(A,1); i <= matmax(A,1); i++) {
for (j = matmin(A,2); j <= matmax(A,2); j++)
printf("%8d", A[i,j];
print;
}
The default printing may be restored by
undefine mat_print;
The keyword "mat" followed by two or more index-range-lists returns a
matrix with indices specified by the first list, whose elements are
matrices as determined by the later index-range-lists. For
example mat[2][3] is a 2-element matrix, each of whose elements has
as its value a 3-element matrix. Values may be assigned to the
elements of the innermost matrices by nested = {...} operations as in
mat [2][3] = {{1,2,3},{4,5,6}}
An example of the use of mat with a declarator is
global mat A B [2,3], C [4]
This creates, if they do not already exist, three global variables with
names A, B, C, and assigns to A and B the value mat[2,3] and to C mat[4].
Some operations are defined for matrices.
A == B
Returns 1 if A and B are of the same "shape" and "corresponding"
elements are equal; otherwise 0 is returned. Being of the same
shape means they have the same dimension d, and for each i <= d,
matmax(A,i) - matmin(A,i) == matmax(B,i) - matmin(B,i),
One consequence of being the same shape is that the matrices will
have the same size. Elements "correspond" if they have the same
double-bracket indices; thus A == B implies that A[[i]] == B[[i]]
for 0 <= i < size(A) == size(B).
A + B
A - B
These are defined A and B have the same shape, the element
with double-bracket index j being evaluated by A[[j]] + B[[j]] and
A[[j]] - B[[j]], respectively. The index-ranges for the results
are those for the matrix A.
A[i,j]
If A is two-dimensional, it is customary to speak of the indices
i, j in A[i,j] as referring to rows and columns; the number of
rows is matmax(A,1) - matmin(A,1) + 1; the number of columns if
matmax(A,2) - matmin(A,2) + 1. A matrix is said to be square
if it is two-dimensional and the number of rows is equal to the
number of columns.
A * B
Multiplication is defined provided certain conditions by the
dimensions and shapes of A and B are satisfied. If both have
dimension 2 and the column-index-list for A is the same as
the row-index-list for B, C = A * B is defined in the usual
way so that for i in the row-index-list of A and j in the
column-index-list for B,
C[i,j] = Sum A[i,k] * B[k,j]
the sum being over k in the column-index-list of A. The same
formula is used so long as the number of columns in A is the same
as the number of rows in B and k is taken to refer to the offset
from matmin(A,2) and matmin(B,1), respectively, for A and B.
If the multiplications and additions required cannot be performed,
an execution error may occur or the result for C may contain
one or more error-values as elements.
If A or B has dimension zero, the result for A * B is simply
that of multiplying the elements of the other matrix on the
left by A[] or on the right by B[].
If both A and B have dimension 1, A * B is defined if A and B
have the same size; the result has the same index-list as A
and each element is the product of corresponding elements of
A and B. If A and B have the same index-list, this multiplication
is consistent with multiplication of 2D matrices if A and B are
taken to represent 2D matrices for which the off-diagonal elements
are zero and the diagonal elements are those of A and B.
the real and complex numbers.
If A is of dimension 1 and B is of dimension 2, A * B is defined
if the number of rows in B is the same as the size of A. The
result has the same index-lists as B; each row of B is multiplied
on the left by the corresponding element of A.
If A is of dimension 2 and B is of dimension 1, A * B is defined
if number of columns in A is the same as the size of A. The
result has the same index-lists as A; each column of A is
multiplied on the right by the corresponding element of B.
The algebra of additions and multiplications involving both one-
and two-dimensional matrices is particularly simple when all the
elements are real or complex numbers and all the index-lists are
the same, as occurs, for example, if for some positive integer n,
all the matrices start as mat [n] or mat [n,n].
det(A)
If A is a square, det(A) is evaluated by an algorithm that returns
the determinant of A if the elements of A are real or complex
numbers, and if such an A is non-singular, inverse(A) returns
the inverse of A indexed in the same way as A. For matrix A of
dimension 0 or 1, det(A) is defined as the product of the elements
of A in the order in which they occur in A, inverse(A) returns
a matrix indexed in the same way as A with each element inverted.
The following functions are defined to return matrices with the same
index-ranges as A and the specified operations performed on all
elements of A. Here num is an arbitrary complex number (nonzero
when it is a divisor), int an integer, rnd a rounding-type
specifier integer, real a real number.
num * A
A * num
A / num
- A
conj(A)
A << int, A >> int
scale(A, int)
round(A, int, rnd)
bround(A, int, rnd)
appr(A, real, rnd)
int(A)
frac(A)
A // real
A % real
A ^ int
If A and B are one-dimensional of the same size dp(A, B) returns
their dot-product, i.e. the sum of the products of corresponding
elements.
If A and B are one-dimension and of size 3, cp(A, B) returns their
cross-product.
randperm(A) returns a matrix indexed the same as A in which the elements
of A have been randomly permuted.
sort(A) returns a matrix indexed the same as A in which the elements
of A have been sorted.
If A is an lvalue whose current value is a matrix, matfill(A, v)
assigns the value v to every element of A, and if also, A is
square, matfill(A, v1, v2) assigns v1 to the off-diagonal elements,
v2 to the diagonal elements. To create and assign to A the unit
n * n matrix, one may use matfill(mat A[n,n], 0, 1).
For a square matrix A, mattrace(A) returns the trace of A, i.e. the
sum of the diagonal elements. For zero- or one-dimensional A,
mattrace(A) returns the sum of the elements of A.
For a two-dimensional matrix A, mattrans(A) returns the transpose
of A, i.e. if A is mat[m,n], it returns a mat[n,m] matrix with
[i,j] element equal to A[j,i]. For zero- or one-dimensional A,
mattrace(A) returns a matrix with the same value as A.
The functions search(A, value, start, end]) and
rsearch(A, value, start, end]) return the first or last index i
for which A[[i]] == value and start <= i < end, or if there is
no such index, the null value. For further information on default
values and the use of an "accept" function, see the help files for
search and rsearch.
reverse(A) returns a matrix with the same index-lists as A but the
elements in reversed order.
The copy and blkcpy functions may be used to copy data to a matrix from
a matrix or list, or from a matrix to a list. In copying from a
matrix to a matrix the matrices need not have the same dimension;
in effect they are treated as linear arrays.
EXAMPLE
> obj point {x,y}
> mat A[5] = {1, 2+3i, "ab", mat[2] = {4,5}. obj point = {6,7}}
> A
mat [5] (5 elements, 5 nonzero):
[0] = 1
[1] = 2+3i
[2] = "ab"
[3] = mat [2] (2 elements, 2 nonzero)
[4] = obj point {6, 7}
> print A[0], A[1], A[2], A[3][0], A[4].x
1 2+3i ab 4 6
> define point_add(a,b) = obj point = {a.x + b.x, a.y + b.y}
point_add(a,b) defined
> mat [B] = {8, , "cd", mat[2] = {9,10}, obj point = {11,12}}
> A + B
mat [5] (5 elements, 5 nonzero):
[0] = 9
[1] = 2+3i
[2] = "abcd"
[3] = mat [2] (2 elements, 2 nonzero)
[4] = obj point {17, 19}
> mat C[2,2] = {1,2,3,4}
> C^10
mat [2,2] (4 elements, 4 nonzero):
[0,0] = 4783807
[0,1] = 6972050
[1,0] = 10458075
[1,1] = 15241882
> C^-10
mat [2,2] (4 elements, 4 nonzero):
[0,0] = 14884.650390625
[0,1] = -6808.642578125
[1,0] = -10212.9638671875
[1,1] = 4671.6865234375
> mat A[4] = {1,2,3,4}, A * reverse(A);
mat [4] (4 elements, 4 nonzero):
[0] = 4
[1] = 6
[2] = 6
[3] = 4
LIMITS
The theoretical upper bound for the absolute values of indices is
2^31 - 1, but the size of matrices that can be handled in practice will
be limited by the availability of memory and what is an acceptable
runtime. For example, although it may take only a fraction of a
second to invert a 10 * 10 matrix, it will probably take about 1000
times as long to invert a 100 * 100 matrix.
LIBRARY
n/a
SEE ALSO
ismat, matdim, matmax, matmin, mattrans, mattrace, matsum, det, inverse,
isident, test, config, search, rsearch, reverse, copy, blkcpy, dp, cp,
randperm, sort

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

@@ -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,14 @@
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
To learn how to invoke the calc command and about calc -flags, try:
help usage
A full and extensive overview of calc may be obtained by:
help full
@@ -156,5 +164,3 @@
These can contain both functions to be defined, and expressions
to be calculated. Global variables which are numbers can be
saved to a file by using the 'write filename' command.
XXX - update this file and add in new major features

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

@@ -230,4 +230,4 @@ LIBRARY
long irand(long max)
SEE ALSO
srand, randbit, isrand, random, srandom, israndom
seed, srand, randbit, isrand, random, srandom, israndom

View File

@@ -40,4 +40,4 @@ LIBRARY
void zrand(long cnt, ZVALUE *res)
SEE ALSO
srand, randbit, isrand, random, srandom, israndom
seed, srand, randbit, isrand, random, srandom, israndom

View File

@@ -154,4 +154,4 @@ LIBRARY
long irandom(long max)
SEE ALSO
srand, randbit, isrand, rand, srandom, israndom
seed, srand, randbit, isrand, rand, srandom, israndom

View File

@@ -39,4 +39,4 @@ LIBRARY
void zrandom(long cnt, ZVALUE *res)
SEE ALSO
srand, randbit, isrand, rand, srandom, israndom
seed, srand, randbit, isrand, rand, srandom, israndom

52
help/seed Normal file
View File

@@ -0,0 +1,52 @@
NAME
seed - return a value that may be used to seed a pseudo-random generator
SYNOPSIS
seed()
TYPES
return integer
DESCRIPTION
Generate a pseudo-random seed based on a collection of system and process
information. The seed() builtin function returns a value:
0 <= seed < 2^64
IMPORTANT WARNING:
It should be pointed out that the information collected by seed
is almost certainly non-chaotic. This function is likely not
suitable for applications (such as cryptographic applications)
where the unpredictability of seeds is critical. For such critical
applications, lavarand should be used. See the URL:
http://lavarand.sgi.com/index.html
for information about seeding a pseudo-random number generator
(such as rand() or random()) with the cryptographic hash of the
digitization of chaotic system.
Given the above warning, this builtin function produces a seed that is
suitable for most applications that desire a different pseudo-random
sequence each time they are run.
The return value of this builtin function should NOT be considered
a random or pseudo-random value. The return value should be used
as an argument to a seed function such as srand() or srandom().
EXAMPLE
> print srand(seed())
RAND state
> print srandom(seed())
RAND state
LIMITS
none
LIBRARY
NUMBER *pseudo_seed(void)
SEE ALSO
seed, srand, randbit, isrand, rand, random, srandom, israndom

View File

@@ -148,4 +148,4 @@ LIBRARY
RAND *zsetrand(RAND *state)
SEE ALSO
srandom, randbit, isrand, random, srandom, israndom
seed, srandom, randbit, isrand, random, srandom, israndom

View File

@@ -222,8 +222,7 @@ DESCRIPTION
The pre-defined Blum moduli and quadratic residues were selected
by lavarand, a hardware random number generator. See the URL:
http://lavarand.sgi.com
XXX - This URL is not available on 17Feb97 ... but will be soon.
http://lavarand.sgi.com/index.html
for an explanation of how the lavarand random number generator works.
For more information, see the comments at the top of the calc
@@ -337,4 +336,4 @@ LIBRARY
RAND *zsetrandom(RAND *state)
SEE ALSO
srand, randbit, isrand, random, srandom, israndom
seed, srand, randbit, isrand, random, srandom, israndom

View File

@@ -10,28 +10,38 @@ Statements
expressions are optional and may be omitted (as in RETURN).
NOTE: Calc commands are in lower case. UPPER case is used below
for emphasis only, and should be considered in lower case.
IF (expr) statement
IF (expr) statement ELSE statement
FOR (optionalexpr ; optionalexpr ; optionalexpr) statement
WHILE (expr) statement
DO statement WHILE (expr)
CONTINUE
BREAK
GOTO label
C-like statements
-----------------
{ statement }
{ statement; ... statement }
if (expr) statement
if (expr) statement ELSE statement
for (optionalexpr ; optionalexpr ; optionalexpr) statement
while (expr) statement
do statement while (expr)
continue
break
goto label
These all work like in normal C.
RETURN optionalexpr
See 'help expression' for details on expressions.
See 'help builtin' for details on calc builtin functions.
return
------
return optionalexpr
return ( optionalexpr )
This returns a value from a function. Functions always
have a return value, even if this statement is not used.
If no return statement is executed, or if no expression
is specified in the return statement, then the return
value from the function is the null type.
SWITCH (expr) { caseclauses }
switch
------
switch (expr) { caseclauses }
Switch statements work similarly to C, except for the
following. A switch can be done on any type of value,
and the case statements can be of any type of values.
@@ -42,17 +52,12 @@ Statements
is the exception, and only matches once all other cases
have been tested.
{ statements }
This is a normal list of statements, each one ended by
a semicolon. Unlike the C language, no declarations are
permitted within an inner-level compound statement.
Declarations are only permitted at the beginning of a
function definition, or at the beginning of an expression
sequence.
MAT variable [dimension] [dimension] ...
MAT variable [dimension, dimension, ...]
MAT variable [] = { value, ... }
matrix
------
mat variable [dimension] [dimension] ...
mat variable [dimension, dimension, ...]
mat variable [] = { value, ... }
This creates a matrix variable with the specified dimensions.
Matrices can have from 1 to 4 dimensions. When specifying
multiple dimensions, you can use either the standard C syntax,
@@ -119,8 +124,11 @@ Statements
local mat temp[5];
static mat strtable[] = {"hi", "there", "folks");
OBJ type { elementnames } optionalvariables
OBJ type variable
object
------
obj type { elementnames } optionalvariables
obj type variable
These create a new object type, or create one or more
variables of the specified type. For this calculator,
an object is just a structure which is implicitly acted
@@ -183,33 +191,12 @@ Statements
static obj point temp2 = {4, 3};
global obj point p1, p2, p3;
EXIT string
QUIT string
This command is used in two cases. At the top command
line level, quit will exit from the calculator. This
is the normal way to leave the calculator. In any other
use, quit will abort the current calculation as if an
error had occurred. If a string is given, then the string
is printed as the reason for quitting, otherwise a general
quit message is printed. The routine name and line number
which executed the quit is also printed in either case.
Quit is useful when a routine detects invalid arguments,
in order to stop a calculation cleanly. For example,
for a square root routine, an error can be given if the
supplied parameter was a negative number, as in:
define mysqrt(n)
{
if (n < 0)
quit "Negative argument";
...
}
Exit is an alias for quit.
PRINT exprs
print expressions
-----------------
print expr
print expr, ... expr
print expr: ... expr
For interactive expression evaluation, the values of all
typed-in expressions are automatically displayed to the
user. However, within a function or loop, the printing of
@@ -247,25 +234,9 @@ Statements
prints the name of the file that was opened.
SHOW item
This command displays some information.
builtin built in functions
global global variables
function user-defined functions
objfunc possible object functions
config config parameters and values
objtype defined objects
Only the first 4 characters of item are examined, so:
show globals
show global
show glob
do the same thing.
Also see the help topic:
command top level commands
expression calc expression syntax
builtin calc builtin functions
usage how to invoke the calc command and calc -options

Some files were not shown because too many files have changed in this diff Show More