Compare commits

...

9 Commits

Author SHA1 Message Date
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
76 changed files with 1405 additions and 660 deletions

154
BUGS
View File

@@ -68,9 +68,157 @@ importantly, fixes (in the form of a context diff patch) to:
Known bugs: Known bugs:
None reported. We are sure some bugs exist. When you find them, * When compiled on some Big Endian machines with BASEB forced to
please let us know! See the above for details on how to report and be 16 (by setting LONGLONG_BITS= 0 in the Makefile), calc fails
were to EMail your bug reports and hopefully patches to fix them. a number of regression tests:
4230: n = ftell(f)
4231: isnull(fputs(f,L,"\n",C,"\n",N,"\n"))
4232: fseek(f, n)
**** Non-true result (0): 4233: fgetstr(f) == LCN
4234: isnull(fclose(f))
4235: a = exp(27, 1e-1000)
4236: b = sqrt(7 + 5i, 1e-2000)
4252: fscanf(f, "%*[^|]%*c%n%*[^[]%*c%n", m, n) == 2
4253: fseek(f, m)
4254: fscanf(f, "%3c", x) == 1
**** Non-true result (0): 4255: x == " Cu"
4256: fseek(f, n)
4257: fscanf(f, "%s", y) == 1
**** Non-true result (0): 4258: y == "Noll"
4259: isnull(fclose(f))
4260: x = rm("junk4200")
4261: Ending test_fileops
4600: Beginning test_fileop
4601: ttest(0,0): passed
4602: stest(): failed
**** search(f, "and") != 10 failed
4603: ttest(1,1): failed
**** Failure 2 for i = 0
4604: stest(): failed
**** search(f, "and") != 10 failed
4605: ttest(2,2): failed
**** Failure 2 for i = 0
4606: stest(): failed
**** search(f, "and") != 10 failed
4607: ttest(3,3): failed
**** Failure 2 for i = 0
4608: stest(): failed
**** search(f, "and") != 10 failed
4609: ttest(4,4): failed
**** Failure 2 for i = 0
4610: stest(): failed
**** search(f, "and") != 10 failed
4611: ttest(5,5): failed
**** Failure 2 for i = 0
4612: stest(): failed
**** search(f, "and") != 10 failed
4613: ttest(6,6): failed
**** Failure 2 for i = 0
4614: stest(): failed
**** search(f, "and") != 10 failed
4615: ttest(7,7): failed
**** Failure 2 for i = 0
4616: stest(): failed
**** search(f, "and") != 10 failed
4617: ttest(8,8): failed
**** Failure 2 for i = 0
4618: stest(): failed
**** search(f, "and") != 10 failed
4619: ttest(9,9): failed
**** Failure 1 for file size
4620: stest(): failed
**** fopen("junk4600", "w") failed
4621: Ending test_fileop
4700: Beginning test_charset
**** errcount:172 > ecnt:150
4701: "\a" == char(7)
4702: "\v" == char(11)
4703: "\e" == char(27)
5000: Beginning test_filesearch
5001: x = rm("-f", "junk5000")
5002: f = fopen("junk5000", "w")
**** Unable to open "junk5000" for writing
5100: Beginning test_newdecl
5101: test5100(1)
**** errcount:173 > ecnt:172
5102: a5100 == 0
5103: b5100 == 2
5104: test5100(1)
5927: test unused
5928: test unused
5929: test unused
**** errcount:180 > ecnt:177
5930: isassoc(loc) == 0
5931: isassoc(a) == 1
5932: isassoc(ofd) == 0
6079: test unused
6080: iserror(loc) == 0
6081: iserror(a) == 0
**** Non-true result (0): 6082: iserror(ofd) == 0
**** Non-true result (0): 6083: iserror(cfd) == 0
6084: iserror(blk) == 0
6085: iserror(nblk) == 0
6086: iserror(cfg) == 0
6139: test unused
6140: isfile(loc) == 0
6141: isfile(a) == 0
**** Non-true result (0): 6142: isfile(ofd) == 1
**** Non-true result (0): 6143: isfile(cfd) == 1
6144: isfile(blk) == 0
6145: isfile(nblk) == 0
6146: isfile(cfg) == 0
6700: Beginning test_blk
6701: A = blk(20);
**** errcount:181 > ecnt:180
6702: size(A) == 20
6703: sizeof(A) == 256
6704: B = A;
6822: C == A
6823: fs = fopen("junk6800", "w+");
6824: blkcpy(fs, A);
**** errcount:183 > ecnt:181
**** Non-true result (0): 6825: size(f) == 5
6826: blkcpy(B = blk(), fs);
**** errcount:184 > ecnt:183
**** Non-true result (0): 6827: B == A
6828: blkcpy(fs, A, ,100);
**** errcount:185 > ecnt:184
**** Non-true result (0): 6829: size(f) == 105
6830: blkcpy(C = blk(), fs, 2, ,100)
**** errcount:186 > ecnt:185
**** Non-true result (0): 6831: C == (blk() = {1,2}
6832: A = blk();
6833: blkcpy(A, "blk6800");
6834: size(A) == 9
6900: Beginning test_name
6901: x = rm("-f", "junk6900")
6902: f = fopen("junk6900", "w")
**** errcount:189 > ecnt:186
**** Non-true result (0): 6903: name(f) == "junk6900"
6904: fclose(f)
**** errcount:190 > ecnt:189
6905: name(f) == null()
6906: A = blk("blk6900")
6907: name(A) == "blk6900"
7002: B = blk();
7003: copy("abc yz", A);
7004: copy("defg", B);
**** errcount:191 > ecnt:190
7005: strprintf("%s", A) == "abc yz"
7006: strprintf("%s", A[2]) == "c yz"
7007: strprintf("%s", A[7]) == ""
9995: freeredc()
9996: freestatics()
**** 24 error(s) found \/++\/
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.
=-= =-=

129
CHANGES
View File

@@ -34,10 +34,139 @@ Following is the change from calc version 2.11.0t8 to date:
are used by pseudo_seed() in seed.c to determine what types of are used by pseudo_seed() in seed.c to determine what types of
system services can be used to form a pseudo-random seed. system services can be used to form a pseudo-random seed.
Fixed the way calc -c will continue processing $CALCRC when errors
are encountered. Unless -d is also given, calc -c will report
when calc is unable to open a $CALCRC file.
Fixed the lower level make depend rules. Fixed the lower level make depend rules.
Misc cleanup on the have_*.c support source files. Misc cleanup on the have_*.c support source files.
Misc source file cleanup for things such as } else { style consistency.
Fixed the basis for FNV-1 hashes. Piror to this fix, the hash()
builtin produced FNV hash values that did not match the FNV-1
algorithm as specified in:
http://reality.sgi.com/chongo/tech/comp/fnv/index.html
Removed an unused argument in the function getbody() in codegen.c.
Encountering of EOF in getbody() will cause a scanerror rather then
stop activity. This will now result in a scanerror:
echo 'define f(x) { ' > myfile
calc -i read myfile
A '{' at the start of a command and a later matching '}' surrounding zero
or more statements (and possibly newlines) results in a function body to
be "evaluated". This permits another command to follow on the same
line as the '}' as in:
{display(5)} read something;
and:
{static a = 5} define f(x) = a + x;
String constants can now be concatenated. For exmaple:
s = "curds" ' and ' "whey";
Added FNV hash to the regression test suite.
Added Ernest Bowen's <ernie@turing.une.edu.au> fix for the
FNV regression test of the hash() builtin function.
Added Ernest Bowen's <ernie@turing.une.edu.au> patch to improve
the way config("calc_debug"). Now the lower 4 bits of the
config("calc_debug") parameter have the following meaning:
n Meaning of bit n of config("calc_debug")
0 Outputs shell commands prior to execution.
1 Outputs currently active functions when a quit instruction
is executed.
2 Some details of shs, shs1 and md5 hash states are included
in the output when these are printed.
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.
Changed the meaning of (config("calc_debug") & 1) from only printing
the shell commands (and pausing) while displaying help files into
the printing of any shell command prior to execution.
Documented the meaning of config("lib_debug"):
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.
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.
Changed the calc lib files to reflect the new config("lib_debug")
bit field meaning. Calc lib files that need to print extra information
should now do something such as:
if (config("lib_debug") & 3) {
print "obj xyz defined";
print "funcA([val1 [, val2]]) defined";
print "funcB(size, mass, ...) defined";
}
Fixed the help/custom_cal, help/new_custom, and help/copy files so
that they contain the correct contents instead of the 'usage' file.
Fixed problem with loss of bindings when calc -i args runs into
an error while processing 'args' and drops into interactive mode
without the terminal bindings being set.
Added patch from Ernest Bowen to extablish the abort command as
well as to clarify the roles of quit and exit. See the help/command
file for details.
Updated to some extend, the help/statement and help/command help
files with new information about SHOW, QUIT, EXIT and ABORT.
Added show sizes to pzasusb8.cal.
Updated calc man page and help/usage file to reflect recent
command line changes.
Fixed a bug, reported by Michael Somos <somos@grail.cba.csuohio.edu>,
which prevented calc -m from being used.
The config("verbose_quit") will control the printing of the message:
Quit or abort executed
when a non-interactive ABORT, QUIT or EXIT is encounted. By default,
config("verbose_quit") is TRUE and the message is printed. If one does:
config("verbose_quit", 0)
the message is disabled.
Added 8400 regression test set and test8400.cal to test the new
quit and config("verbose_quit") functionality.
Fixed misc compiler warnings.
Following is the change from calc version 2.11.0t7 to 2.11.0t7.5: Following is the change from calc version 2.11.0t7 to 2.11.0t7.5:

1
README
View File

@@ -42,6 +42,7 @@ For overview of calc overview:
> help define > help define
> help statement > help statement
> help variable > help variable
> help usage
For list of builtin functions: For list of builtin functions:

View File

@@ -164,8 +164,8 @@ endfunc(void)
size += dumpop(&fp->f_opcodes[size]); size += dumpop(&fp->f_opcodes[size]);
} }
} }
if ((inputisterminal() && conf->lib_debug & 1) || if ((inputisterminal() && conf->lib_debug & LIBDBG_STDIN_FUNC) ||
(!inputisterminal() && conf->lib_debug & 2)) { (!inputisterminal() && conf->lib_debug & LIBDBG_FILE_FUNC)) {
printf("%s(", fp->f_name); printf("%s(", fp->f_name);
for (index = 0; index < fp->f_paramcount; index++) { for (index = 0; index < fp->f_paramcount; index++) {
if (index) if (index)
@@ -238,8 +238,8 @@ rmuserfunc(char *name)
return; return;
freenumbers(functions[index]); freenumbers(functions[index]);
free(functions[index]); free(functions[index]);
if ((inputisterminal() && conf->lib_debug & 1) || if ((inputisterminal() && conf->lib_debug & LIBDBG_STDIN_FUNC) ||
(!inputisterminal() && conf->lib_debug & 2)) (!inputisterminal() && conf->lib_debug & LIBDBG_FILE_FUNC))
printf("%s() undefined\n", name); printf("%s() undefined\n", name);
functions[index] = NULL; functions[index] = NULL;
} }

View File

@@ -57,7 +57,7 @@ associndex(ASSOC *ap, BOOL create, long dim, VALUE *indices)
* so that we can first select the correct hash chain, and * so that we can first select the correct hash chain, and
* also so we can quickly compare each element for a match. * also so we can quickly compare each element for a match.
*/ */
hash = (QCKHASH)0; hash = FNV1_32_BASIS;
for (i = 0; i < dim; i++) for (i = 0; i < dim; i++)
hash = hashvalue(&indices[i], hash); hash = hashvalue(&indices[i], hash);

20
block.c
View File

@@ -104,7 +104,7 @@ blkalloc(int len, int chunk)
/* /*
* return BLOCK * return BLOCK
*/ */
if (conf->calc_debug > 0) { if (conf->calc_debug & CALCDBG_BLOCK) {
blkchk(nblk); blkchk(nblk);
} }
return nblk; return nblk;
@@ -145,13 +145,11 @@ blk_free(BLOCK *blk)
* debug time, we plan to call this function often. Once we are satisfied, * debug time, we plan to call this function often. Once we are satisfied,
* we will normally call this code only in a few places. * 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() * 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: * given:
* blk - the BLOCK to check * blk - the BLOCK to check
* *
@@ -166,7 +164,7 @@ blkchk(BLOCK *blk)
/* /*
* firewall - general sanity check * firewall - general sanity check
*/ */
if (conf->calc_debug == -1) { if ((conf->calc_debug & CALCDBG_BLOCK) == 0) {
/* do nothing when debugging is disabled */ /* do nothing when debugging is disabled */
return; return;
} }
@@ -231,7 +229,7 @@ blkrealloc(BLOCK *blk, int newlen, int newchunk)
/* /*
* firewall * firewall
*/ */
if (conf->calc_debug != -1) { if (conf->calc_debug & CALCDBG_BLOCK) {
blkchk(blk); blkchk(blk);
} }
@@ -290,7 +288,7 @@ blkrealloc(BLOCK *blk, int newlen, int newchunk)
memset(blk->data, 0, blk->maxsize); memset(blk->data, 0, blk->maxsize);
} }
blk->datalen = 0; blk->datalen = 0;
if (conf->calc_debug > 0) { if (conf->calc_debug & CALCDBG_BLOCK) {
blkchk(blk); blkchk(blk);
} }
return blk; return blk;
@@ -321,7 +319,7 @@ blkrealloc(BLOCK *blk, int newlen, int newchunk)
/* /*
* return realloced type * return realloced type
*/ */
if (conf->calc_debug > 0) { if (conf->calc_debug & CALCDBG_BLOCK) {
blkchk(blk); blkchk(blk);
} }
return blk; return blk;
@@ -349,7 +347,7 @@ blktrunc(BLOCK *blk)
/* /*
* firewall * firewall
*/ */
if (conf->calc_debug != -1) { if (conf->calc_debug & CALCDBG_BLOCK) {
blkchk(blk); blkchk(blk);
} }
@@ -370,7 +368,7 @@ blktrunc(BLOCK *blk)
/*NOTREACHED*/ /*NOTREACHED*/
} }
blk->data[0] = (USB8)0; blk->data[0] = (USB8)0;
if (conf->calc_debug > 0) { if (conf->calc_debug & CALCDBG_BLOCK) {
blkchk(blk); blkchk(blk);
} }
return; return;

14
calc.c
View File

@@ -87,7 +87,7 @@ main(int argc, char **argv)
i_flag = TRUE; i_flag = TRUE;
break; break;
case 'm': case 'm':
if (optarg[1] == '\0' || *optarg<'0' || *optarg>'7') { if (optarg[1] != '\0' || *optarg<'0' || *optarg>'7') {
/* /*
* we are too early in processing to * we are too early in processing to
* call libcalc_call_me_last() * call libcalc_call_me_last()
@@ -249,9 +249,13 @@ main(int argc, char **argv)
fprintf(stderr, "Error in rcfiles\n"); fprintf(stderr, "Error in rcfiles\n");
if ((c_flag && !stoponerror) || stoponerror < 0) { if ((c_flag && !stoponerror) || stoponerror < 0) {
getcommands(FALSE); getcommands(FALSE);
if (inputlevel() == 0) {
closeinput(); closeinput();
if (inputisterminal()) runrcfiles();
run_state = RUN_PRE_CMD_ARGS; run_state = RUN_PRE_CMD_ARGS;
} else {
closeinput();
}
} else { } else {
if ((havecommands && !i_flag) || !stdin_tty) if ((havecommands && !i_flag) || !stdin_tty)
run_state = RUN_EXIT_WITH_ERROR; run_state = RUN_EXIT_WITH_ERROR;
@@ -274,11 +278,9 @@ main(int argc, char **argv)
fprintf(stderr, "Error in commands\n"); fprintf(stderr, "Error in commands\n");
if ((c_flag && !stoponerror) || stoponerror < 0) { if ((c_flag && !stoponerror) || stoponerror < 0) {
getcommands(FALSE); getcommands(FALSE);
closeinput(); if (inputlevel() == 0)
if (inputlevel() == 0) {
getcommands(FALSE);
run_state = RUN_PRE_TOP_LEVEL; run_state = RUN_PRE_TOP_LEVEL;
} closeinput();
} else { } else {
closeinput(); closeinput();
if (!stdin_tty || !i_flag || p_flag) if (!stdin_tty || !i_flag || p_flag)

1
calc.h
View File

@@ -164,6 +164,7 @@ extern int d_flag; /* TRUE => disable heading, lib_debug == 0 */
extern int c_flag; /* TRUE => continue after error if permitted */ extern int c_flag; /* TRUE => continue after error if permitted */
extern int i_flag; /* TRUE => try to go interactive after error */ extern int i_flag; /* TRUE => try to go interactive after error */
extern int stoponerror; /* >0 => stop, <0 => continue, ==0 => use -c */ 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 char *pager; /* $PAGER or default */
extern int stdin_tty; /* TRUE if stdin is a tty */ extern int stdin_tty; /* TRUE if stdin is a tty */

View File

@@ -62,6 +62,13 @@ cause
.B calc .B calc
to try to process each line being read to try to process each line being read
despite the errors that it encounters. 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 .TP
.B \-C .B \-C
@@ -112,6 +119,8 @@ It's nearly ten past six.
.fi .fi
.in -5n .in -5n
.sp 1 .sp 1
This flag disables the reporting of missing calc
startup scripts ($CALCRC).
.TP .TP
.B \-e .B \-e

View File

@@ -31,7 +31,7 @@ static void getshowstatement(void);
static void getfunction(void); static void getfunction(void);
static void ungetfunction(void); static void ungetfunction(void);
static void getbody(LABEL *contlabel, LABEL *breaklabel, static void getbody(LABEL *contlabel, LABEL *breaklabel,
LABEL *nextcaselabel, LABEL *defaultlabel, BOOL toplevel); LABEL *nextcaselabel, LABEL *defaultlabel);
static void getdeclarations(int symtype); static void getdeclarations(int symtype);
static void getsimpledeclaration (int symtype); static void getsimpledeclaration (int symtype);
static int getonevariable (int symtype); static int getonevariable (int symtype);
@@ -86,6 +86,7 @@ getcommands(BOOL toplevel)
/* firewall */ /* firewall */
name[0] = '\0'; name[0] = '\0';
name[MAXCMD+1] = '\0'; name[MAXCMD+1] = '\0';
abort_now = FALSE;
/* getcommands */ /* getcommands */
if (!toplevel) if (!toplevel)
@@ -164,6 +165,13 @@ getcommands(BOOL toplevel)
if (evaluate(FALSE)) if (evaluate(FALSE))
updateoldvalue(curfunc); updateoldvalue(curfunc);
freefunc(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);
}
} }
} }
} }
@@ -190,13 +198,16 @@ evaluate(BOOL nestflag)
funcname = (nestflag ? "**" : "*"); funcname = (nestflag ? "**" : "*");
beginfunc(funcname, nestflag); beginfunc(funcname, nestflag);
if (gettoken() == T_LEFTBRACE) {
getbody(NULL_LABEL, NULL_LABEL, NULL_LABEL, NULL_LABEL);
} else {
if (nestflag) if (nestflag)
(void) tokenmode(TM_DEFAULT); (void) tokenmode(TM_DEFAULT);
rescantoken();
while (loop) { while (loop) {
switch (gettoken()) { switch (gettoken()) {
case T_SEMICOLON: case T_SEMICOLON:
break; break;
case T_NEWLINE: case T_NEWLINE:
case T_EOF: case T_EOF:
loop = 0; loop = 0;
@@ -208,6 +219,7 @@ evaluate(BOOL nestflag)
NULL_LABEL, NULL_LABEL); NULL_LABEL, NULL_LABEL);
} }
} }
}
addop(OP_UNDEF); addop(OP_UNDEF);
addop(OP_RETURN); addop(OP_RETURN);
checklabels(); checklabels();
@@ -322,13 +334,11 @@ getfunction(void)
} }
switch (gettoken()) { switch (gettoken()) {
case T_ASSIGN: case T_ASSIGN:
rescantoken();
getsimplebody(); getsimplebody();
break; break;
case T_LEFTBRACE: case T_LEFTBRACE:
rescantoken();
getbody(NULL_LABEL, NULL_LABEL, NULL_LABEL, getbody(NULL_LABEL, NULL_LABEL, NULL_LABEL,
NULL_LABEL, TRUE); NULL_LABEL);
break; break;
default: default:
scanerror(T_NULL, scanerror(T_NULL,
@@ -347,11 +357,6 @@ getfunction(void)
static void static void
getsimplebody(void) getsimplebody(void)
{ {
if (gettoken() != T_ASSIGN) {
scanerror(T_SEMICOLON,
"Missing equals for simple function body");
return;
}
(void) tokenmode(TM_NEWLINES); (void) tokenmode(TM_NEWLINES);
(void) getexprlist(); (void) getexprlist();
addop(OP_RETURN); addop(OP_RETURN);
@@ -365,14 +370,10 @@ getsimplebody(void)
*/ */
/*ARGSUSED*/ /*ARGSUSED*/
static void static void
getbody(LABEL *contlabel, LABEL *breaklabel, LABEL *nextcaselabel, LABEL *defaultlabel, BOOL toplevel) getbody(LABEL *contlabel, LABEL *breaklabel, LABEL *nextcaselabel, LABEL *defaultlabel)
{ {
int oldmode; int oldmode;
if (gettoken() != T_LEFTBRACE) {
scanerror(T_SEMICOLON, "Missing left brace for function body");
return;
}
oldmode = tokenmode(TM_DEFAULT); oldmode = tokenmode(TM_DEFAULT);
while (TRUE) { while (TRUE) {
switch (gettoken()) { switch (gettoken()) {
@@ -380,6 +381,10 @@ getbody(LABEL *contlabel, LABEL *breaklabel, LABEL *nextcaselabel, LABEL *defaul
(void) tokenmode(oldmode); (void) tokenmode(oldmode);
return; return;
case T_EOF:
scanerror(T_SEMICOLON, "End-of-file in function body");
return;
default: default:
rescantoken(); rescantoken();
getstatement(contlabel, breaklabel, nextcaselabel, defaultlabel); getstatement(contlabel, breaklabel, nextcaselabel, defaultlabel);
@@ -595,8 +600,7 @@ getstatement(LABEL *contlabel, LABEL *breaklabel, LABEL *nextcaselabel, LABEL *d
break; break;
case T_LEFTBRACE: case T_LEFTBRACE:
rescantoken(); getbody(contlabel, breaklabel, nextcaselabel, defaultlabel);
getbody(contlabel, breaklabel, nextcaselabel, defaultlabel, FALSE);
return; return;
case T_IF: case T_IF:
@@ -866,8 +870,19 @@ getstatement(LABEL *contlabel, LABEL *breaklabel, LABEL *nextcaselabel, LABEL *d
} }
break; break;
case T_ABORT:
switch (gettoken()) {
case T_STRING:
addopone(OP_ABORT, tokenstring());
break;
default:
addopone(OP_ABORT, -1);
rescantoken();
}
break;
case T_SYMBOL: case T_SYMBOL:
if (nextchar() == ':') { /****HACK HACK ****/ if (nextchar() == ':') { /****HACK HACK****/
definelabel(tokensymbol()); definelabel(tokensymbol());
if (gettoken() == T_RIGHTBRACE) { if (gettoken() == T_RIGHTBRACE) {
rescantoken(); rescantoken();
@@ -1001,8 +1016,7 @@ getoneobj(long index, int symtype)
if (symtype == SYM_UNDEFINED) { if (symtype == SYM_UNDEFINED) {
rescantoken(); rescantoken();
(void) getidexpr(TRUE, TRUE); (void) getidexpr(TRUE, TRUE);
} } else {
else {
symname = tokensymbol(); symname = tokensymbol();
definesymbol(symname, symtype); definesymbol(symname, symtype);
usesymbol(symname, FALSE); usesymbol(symname, FALSE);
@@ -1086,8 +1100,7 @@ getonematrix(int symtype)
if (symtype == SYM_UNDEFINED) { if (symtype == SYM_UNDEFINED) {
rescantoken(); rescantoken();
(void) getidexpr(FALSE, TRUE); (void) getidexpr(FALSE, TRUE);
} } else {
else {
name = tokensymbol(); name = tokensymbol();
definesymbol(name, symtype); definesymbol(name, symtype);
usesymbol(name, FALSE); usesymbol(name, FALSE);
@@ -1172,9 +1185,9 @@ creatematrix(void)
switch (gettoken()) { switch (gettoken()) {
case T_RIGHTBRACKET: case T_RIGHTBRACKET:
addopone(OP_MATCREATE, dim); addopone(OP_MATCREATE, dim);
if (gettoken() == T_LEFTBRACKET) if (gettoken() == T_LEFTBRACKET) {
creatematrix(); creatematrix();
else { } else {
rescantoken(); rescantoken();
addop(OP_ZERO); addop(OP_ZERO);
} }
@@ -1350,8 +1363,7 @@ getopassignment(void)
while (gettoken() == T_ASSIGN) while (gettoken() == T_ASSIGN)
getinitlist(); getinitlist();
rescantoken(); rescantoken();
} } else {
else {
rescantoken(); rescantoken();
(void) getassignment(); (void) getassignment();
} }

View File

@@ -231,8 +231,7 @@ csqrt(COMPLEX *c, NUMBER *epsilon, long R)
return r; return r;
} }
s3 = zquo(tmp3, d, &tmp1, s2 < 0); s3 = zquo(tmp3, d, &tmp1, s2 < 0);
} } else {
else {
s2 = zquo(tmp1, d, &tmp3, s1 ? (s1 < 0) : 16); s2 = zquo(tmp1, d, &tmp3, s1 ? (s1 < 0) : 16);
zfree(tmp1); zfree(tmp1);
s3 = zsqrt(tmp3,&tmp1,(s1||s2) ? (s1<0 || s2<0) : 16); s3 = zsqrt(tmp3,&tmp1,(s1||s2) ? (s1<0 || s2<0) : 16);
@@ -288,8 +287,7 @@ csqrt(COMPLEX *c, NUMBER *epsilon, long R)
return r; return r;
} }
s3 = zquo(tmp3, d, &mul1, 0); s3 = zquo(tmp3, d, &mul1, 0);
} } else {
else {
s2 = zquo(tmp1, d, &tmp3, 0); s2 = zquo(tmp1, d, &tmp3, 0);
zfree(tmp1); zfree(tmp1);
s3 = zsqrt(tmp3, &mul1, 0); s3 = zsqrt(tmp3, &mul1, 0);

View File

@@ -55,6 +55,7 @@ NAMETYPE configs[] = {
{"lib_debug", CONFIG_LIB_DEBUG}, {"lib_debug", CONFIG_LIB_DEBUG},
{"calc_debug", CONFIG_CALC_DEBUG}, {"calc_debug", CONFIG_CALC_DEBUG},
{"user_debug", CONFIG_USER_DEBUG}, {"user_debug", CONFIG_USER_DEBUG},
{"verbose_quit",CONFIG_VERBOSE_QUIT},
{NULL, 0} {NULL, 0}
}; };
@@ -95,7 +96,8 @@ CONFIG oldstd = { /* backward compatible standard configuration */
BLK_FMT_HD_STYLE, /* block output format */ BLK_FMT_HD_STYLE, /* block output format */
3, /* calc library debug level */ 3, /* calc library debug level */
0, /* internal calc debug level */ 0, /* internal calc debug level */
0 /* user defined debug level */ 0, /* user defined debug level */
TRUE /* print Quit or abort executed messages */
}; };
CONFIG newstd = { /* new non-backward compatible configuration */ CONFIG newstd = { /* new non-backward compatible configuration */
MODE_INITIAL, /* current output mode */ MODE_INITIAL, /* current output mode */
@@ -130,7 +132,8 @@ CONFIG newstd = { /* new non-backward compatible configuration */
BLK_FMT_HD_STYLE, /* block output format */ BLK_FMT_HD_STYLE, /* block output format */
3, /* calc library debug level */ 3, /* calc library debug level */
0, /* internal calc debug level */ 0, /* internal calc debug level */
0 /* user defined debug level */ 0, /* user defined debug level */
TRUE /* print Quit or abort executed messages */
}; };
CONFIG *conf = NULL; /* loaded in at startup - current configuration */ CONFIG *conf = NULL; /* loaded in at startup - current configuration */
@@ -848,6 +851,21 @@ setconfig(int type, VALUE *vp)
conf->user_debug = temp; conf->user_debug = temp;
break; 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 = truthtype(vp->v_str->s_str);
if (temp < 0) {
math_error("Illegal truth value"
"for verbose_quit");
/*NOTREACHED*/
}
conf->verbose_quit = (int)temp;
}
break;
default: default:
math_error("Setting illegal config parameter"); math_error("Setting illegal config parameter");
/*NOTREACHED*/ /*NOTREACHED*/
@@ -1119,6 +1137,10 @@ config_value(CONFIG *cfg, int type, VALUE *vp)
i = cfg->user_debug; i = cfg->user_debug;
break; break;
case CONFIG_VERBOSE_QUIT:
i = cfg->verbose_quit;
break;
default: default:
math_error("Getting illegal CONFIG element"); math_error("Getting illegal CONFIG element");
/*NOTREACHED*/ /*NOTREACHED*/
@@ -1194,5 +1216,6 @@ config_cmp(CONFIG *cfg1, CONFIG *cfg2)
cfg1->blkfmt != cfg2->blkfmt || cfg1->blkfmt != cfg2->blkfmt ||
cfg1->lib_debug != cfg2->lib_debug || cfg1->lib_debug != cfg2->lib_debug ||
cfg1->calc_debug != cfg2->calc_debug || cfg1->calc_debug != cfg2->calc_debug ||
cfg1->user_debug != cfg2->user_debug; cfg1->user_debug != cfg2->user_debug ||
cfg1->verbose_quit != cfg2->verbose_quit;
} }

View File

@@ -80,6 +80,7 @@
#define CONFIG_LIB_DEBUG 30 #define CONFIG_LIB_DEBUG 30
#define CONFIG_CALC_DEBUG 31 #define CONFIG_CALC_DEBUG 31
#define CONFIG_USER_DEBUG 32 #define CONFIG_USER_DEBUG 32
#define CONFIG_VERBOSE_QUIT 33
/* /*
@@ -114,8 +115,8 @@ struct config {
LEN sq2; /* size of number to use square algorithm 2 */ LEN sq2; /* size of number to use square algorithm 2 */
LEN pow2; /* size of modulus to use REDC for powers */ LEN pow2; /* size of modulus to use REDC for powers */
LEN redc2; /* size of modulus to use REDC algorithm 2 */ LEN redc2; /* size of modulus to use REDC algorithm 2 */
int tilde_ok; /* ok to print a tilde on aproximations */ BOOL tilde_ok; /* ok to print a tilde on aproximations */
int tab_ok; /* ok to print tab before numeric values */ BOOL tab_ok; /* ok to print tab before numeric values */
long quomod; /* quomod() default rounding mode */ long quomod; /* quomod() default rounding mode */
long quo; /* quotent // default rounding mode */ long quo; /* quotent // default rounding mode */
long mod; /* mod % default rounding mode */ long mod; /* mod % default rounding mode */
@@ -125,22 +126,41 @@ struct config {
long cfsim; /* cfsim() default rounding mode */ long cfsim; /* cfsim() default rounding mode */
long outround; /* output default rounding mode */ long outround; /* output default rounding mode */
long round; /* round()/bround() default rounding mode */ long round; /* round()/bround() default rounding mode */
int leadzero; /* ok to print leading 0 before decimal pt */ BOOL leadzero; /* ok to print leading 0 before decimal pt */
int fullzero; /* ok to print trailing 0's */ BOOL fullzero; /* ok to print trailing 0's */
long maxscancount; /* max scan errors before abort */ long maxscancount; /* max scan errors before abort */
char *prompt1; /* normal prompt */ char *prompt1; /* normal prompt */
char *prompt2; /* prompt when inside multi-line input */ char *prompt2; /* prompt when inside multi-line input */
int blkmaxprint; /* octets of a block to print, 0 => all */ 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 blkbase; /* block output base */
int blkfmt; /* block output style */ int blkfmt; /* block output style */
int lib_debug; /* library debug: <0 none, 0 default, >0 more */ int lib_debug; /* library debug, see LIB_DEBUG_XXX below */
int calc_debug; /* internal debug: <0 none, 0 default,>0 more */ int calc_debug; /* internal debug, see CALC_DEBUG_XXX below */
int user_debug; /* user defined debug value: 0 default */ int user_debug; /* user defined debug value: 0 default */
BOOL verbose_quit; /* TRUE => print Quit or abort executed msg */
}; };
typedef struct config CONFIG; 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_MASK (0x00000003)
/*
* 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_MASK (0x0000000f)
/* /*
* global configuration states and aliases * global configuration states and aliases
*/ */

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 # Permission to use, copy, modify, and distribute this software and
# its documentation for any purpose and without fee is hereby granted, # its documentation for any purpose and without fee is hereby granted,
@@ -44,8 +44,19 @@ calc library standards and guidelines.
=-= =-=
argv.cal
argv(var, ...)
print information about various args
halflen.cal halflen.cal
halflen(num) halflen(num)
Calculate the length of a numeric value in HALF's. 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 you look at some examples of custom functions. Check out
the following source files: the following source files:
../custom.c custom.c
custom.h custom/custom.h
custtbl.c custom/custtbl.c
c_*.[ch] custom/c_*.[ch]
../help/custom help/custom (or run: calc help custom)
You would be well advised to look at a more recent calc source 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: See the following for more details:
../help/archive help/archive (or run: calc help archive)
Step 2: Name your custom function 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 Although calc does not run setuid, you may need to be root to install
the directories into which calc installs may be write protected. 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,3 +27,5 @@ print "BIG_ENDIAN: ", custom("sysinfo", "BIG_ENDIAN");
print "LITTLE_ENDIAN: ", custom("sysinfo", "LITTLE_ENDIAN"); print "LITTLE_ENDIAN: ", custom("sysinfo", "LITTLE_ENDIAN");
print "LONG_BITS: ", custom("sysinfo", "LONG_BITS"); print "LONG_BITS: ", custom("sysinfo", "LONG_BITS");
print "LONGLONG_BITS: ", custom("sysinfo", "LONGLONG_BITS"); print "LONGLONG_BITS: ", custom("sysinfo", "LONGLONG_BITS");
print "Calc sizes:";
show sizes;

17
file.c
View File

@@ -115,15 +115,14 @@ file_init(void)
*/ */
if (fstat(i, &sbuf) >= 0) { if (fstat(i, &sbuf) >= 0) {
fp = (FILE *) fdopen(i,"r+"); /*guess mode*/ fp = (FILE *) fdopen(i,"r+"); /*guess mode*/
if (fp) if (fp) {
strcpy(files[idnum].mode, "r+"); strcpy(files[idnum].mode, "r+");
else { } else {
fp = (FILE *) fdopen(i, "r"); fp = (FILE *) fdopen(i, "r");
if (fp) { if (fp) {
strcpy(files[idnum].mode, "r"); strcpy(files[idnum].mode, "r");
files[idnum].writing = FALSE; files[idnum].writing = FALSE;
} } else {
else {
fp = (FILE *) fdopen(i, "w"); fp = (FILE *) fdopen(i, "w");
if (fp) { if (fp) {
strcpy(files[idnum].mode, "w?"); strcpy(files[idnum].mode, "w?");
@@ -890,8 +889,9 @@ idprintf(FILEID id, char *fmt, int count, VALUE **vals)
NULL) NULL)
math_chr(*vp->v_nblock-> math_chr(*vp->v_nblock->
blk->data); blk->data);
} else } else {
printvalue(vp, PRINT_NORMAL); printvalue(vp, PRINT_NORMAL);
}
break; break;
default: default:
printvalue(vp, PRINT_NORMAL); printvalue(vp, PRINT_NORMAL);
@@ -1770,8 +1770,7 @@ showfiles(void)
if (fstat(fileno(fp), &sbuf) < 0) { if (fstat(fileno(fp), &sbuf) < 0) {
printf("Bad fstat for file %d\n", (int) fiop->id); printf("Bad fstat for file %d\n", (int) fiop->id);
sizes[i] = -1; sizes[i] = -1;
} } else {
else {
inodes[i] = sbuf.st_ino; inodes[i] = sbuf.st_ino;
sizes[i] = (long) sbuf.st_size; sizes[i] = (long) sbuf.st_size;
} }
@@ -2471,9 +2470,9 @@ fsearch(FILEID id, char *str, ZVALUE start, ZVALUE end, ZVALUE *res)
} }
(void) f_seek_set(fiop->fp, &cur); (void) f_seek_set(fiop->fp, &cur);
} }
if (*tmp.v) if (*tmp.v) {
(*tmp.v)--; (*tmp.v)--;
else { } else {
if (tmp.len == 1) if (tmp.len == 1)
break; break;
k = 0; k = 0;

60
func.c
View File

@@ -1524,16 +1524,12 @@ static VALUE
f_hash(int count, VALUE **vals) f_hash(int count, VALUE **vals)
{ {
QCKHASH hash; QCKHASH hash;
long lhash;
VALUE result; VALUE result;
hash = (QCKHASH)0; hash = FNV1_32_BASIS;
while (count-- > 0) while (count-- > 0)
hash = hashvalue(*vals++, hash); hash = hashvalue(*vals++, hash);
lhash = (long) hash; result.v_num = utoq((FULL) hash);
if (lhash < 0)
lhash = -lhash;
result.v_num = itoq(lhash);
result.v_type = V_NUM; result.v_type = V_NUM;
return result; return result;
} }
@@ -1640,8 +1636,7 @@ f_avg(int count, VALUE **vals)
if ((*vals)->v_type == V_LIST) { if ((*vals)->v_type == V_LIST) {
addlistitems((*vals)->v_list, &sum); addlistitems((*vals)->v_list, &sum);
n += countlistitems((*vals++)->v_list); n += countlistitems((*vals++)->v_list);
} } else {
else {
addvalue(&sum, *vals++, &tmp); addvalue(&sum, *vals++, &tmp);
freevalue(&sum); freevalue(&sum);
sum = tmp; sum = tmp;
@@ -1690,8 +1685,7 @@ f_hmean(int count, VALUE **vals)
if ((*vals)->v_type == V_LIST) { if ((*vals)->v_type == V_LIST) {
addlistinv((*vals)->v_list, &sum); addlistinv((*vals)->v_list, &sum);
n += countlistitems((*vals++)->v_list); n += countlistitems((*vals++)->v_list);
} } else {
else {
invertvalue(*vals++, &tmp1); invertvalue(*vals++, &tmp1);
addvalue(&sum, &tmp1, &tmp2); addvalue(&sum, &tmp1, &tmp2);
freevalue(&tmp1); freevalue(&tmp1);
@@ -3842,9 +3836,9 @@ f_search(int count, VALUE **vals)
start = qlink(start); start = qlink(start);
} }
if (end) { if (end) {
if (!qispos(end)) if (!qispos(end)) {
end = qqadd(size, end); end = qqadd(size, end);
else { } else {
if (qrel(end, size) > 0) if (qrel(end, size) > 0)
end = qlink(size); end = qlink(size);
else else
@@ -3866,8 +3860,7 @@ f_search(int count, VALUE **vals)
if (count == 2 || (count == 4 && end != NULL)) { if (count == 2 || (count == 4 && end != NULL)) {
start = qalloc(); start = qalloc();
start->num = pos; start->num = pos;
} } else {
else {
end = qalloc(); end = qalloc();
end->num = pos; end->num = pos;
} }
@@ -4005,9 +3998,9 @@ f_rsearch(int count, VALUE **vals)
start = qlink(start); start = qlink(start);
} }
if (end) { if (end) {
if (!qispos(end)) if (!qispos(end)) {
end = qqadd(size, end); end = qqadd(size, end);
else { } else {
if (qrel(end, size) > 0) if (qrel(end, size) > 0)
end = qlink(size); end = qlink(size);
else else
@@ -4029,8 +4022,7 @@ f_rsearch(int count, VALUE **vals)
if (count == 2 || (count == 4 && end != NULL)) { if (count == 2 || (count == 4 && end != NULL)) {
start = qalloc(); start = qalloc();
start->num = pos; start->num = pos;
} } else {
else {
end = qalloc(); end = qalloc();
end->num = pos; end->num = pos;
} }
@@ -4042,8 +4034,7 @@ f_rsearch(int count, VALUE **vals)
if (count < 4) { if (count < 4) {
end = start; end = start;
start = NULL; start = NULL;
} } else {
else {
qtmp = qsub(end, qlen); qtmp = qsub(end, qlen);
qfree(end); qfree(end);
end = qtmp; end = qtmp;
@@ -4634,9 +4625,9 @@ f_strerror(int count, VALUE **vals)
if (count > 0) { if (count > 0) {
vp = vals[0]; vp = vals[0];
if (vp->v_type < 0) if (vp->v_type < 0) {
i = (long) -vp->v_type; i = (long) -vp->v_type;
else { } else {
if (vp->v_type != V_NUM || qisfrac(vp->v_num)) if (vp->v_type != V_NUM || qisfrac(vp->v_num))
return error_value(E_STRERROR1); return error_value(E_STRERROR1);
i = qtoi(vp->v_num); i = qtoi(vp->v_num);
@@ -4747,12 +4738,12 @@ f_error(int count, VALUE **vals)
if (count > 0) { if (count > 0) {
vp = vals[0]; vp = vals[0];
if (vp->v_type <= 0) if (vp->v_type <= 0) {
r = (long) -vp->v_type; r = (long) -vp->v_type;
else { } else {
if (vp->v_type != V_NUM || qisfrac(vp->v_num)) if (vp->v_type != V_NUM || qisfrac(vp->v_num)) {
r = E_ERROR1; r = E_ERROR1;
else { } else {
r = qtoi(vp->v_num); r = qtoi(vp->v_num);
if (r < 0 || r >= 32768) if (r < 0 || r >= 32768)
r = E_ERROR2; r = E_ERROR2;
@@ -5542,28 +5533,26 @@ f_tail(VALUE *v1, VALUE *v2)
res.v_type = v1->v_type; res.v_type = v1->v_type;
switch (v1->v_type) { switch (v1->v_type) {
case V_LIST: case V_LIST:
if (n == 0) if (n == 0) {
res.v_list = listalloc(); res.v_list = listalloc();
else if (n > 0) { } else if (n > 0) {
res.v_list = listsegment(v1->v_list, res.v_list = listsegment(v1->v_list,
v1->v_list->l_count - n, v1->v_list->l_count - n,
v1->v_list->l_count - 1); v1->v_list->l_count - 1);
} } else {
else {
res.v_list = listsegment(v1->v_list, res.v_list = listsegment(v1->v_list,
v1->v_list->l_count - 1, v1->v_list->l_count - 1,
v1->v_list->l_count + n); v1->v_list->l_count + n);
} }
return res; return res;
case V_STR: case V_STR:
if (n == 0) if (n == 0) {
res.v_str = slink(&_nullstring_); res.v_str = slink(&_nullstring_);
else if (n > 0) { } else if (n > 0) {
res.v_str = stringsegment(v1->v_str, res.v_str = stringsegment(v1->v_str,
v1->v_str->s_len - n, v1->v_str->s_len - n,
v1->v_str->s_len - 1); v1->v_str->s_len - 1);
} } else {
else {
res.v_str = stringsegment(v1->v_str, res.v_str = stringsegment(v1->v_str,
v1->v_str->s_len - 1, v1->v_str->s_len - 1,
v1->v_str->s_len + n); v1->v_str->s_len + n);
@@ -6048,6 +6037,9 @@ f_system(VALUE *vp)
/*NOTREACHED*/ /*NOTREACHED*/
} }
result.v_type = V_NUM; result.v_type = V_NUM;
if (conf->calc_debug & CALCDBG_SYSTEM) {
printf("%s\n", vp->v_str->s_str);
}
result.v_num = itoq((long) system(vp->v_str->s_str)); result.v_num = itoq((long) system(vp->v_str->s_str));
return result; return result;
} }

3
help.c
View File

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

View File

@@ -258,7 +258,7 @@ calc: usage
custom_cal: ../custom/CUSTOM_CAL custom_cal: ../custom/CUSTOM_CAL
rm -f $@ rm -f $@
cp usage $@ cp ../custom/CUSTOM_CAL $@
chmod 0444 $@ chmod 0444 $@
-@if [ -z "${Q}" ]; then \ -@if [ -z "${Q}" ]; then \
echo ''; \ echo ''; \
@@ -270,7 +270,7 @@ custom_cal: ../custom/CUSTOM_CAL
new_custom: ../custom/HOW_TO_ADD new_custom: ../custom/HOW_TO_ADD
rm -f $@ rm -f $@
cp usage $@ cp ../custom/HOW_TO_ADD $@
chmod 0444 $@ chmod 0444 $@
-@if [ -z "${Q}" ]; then \ -@if [ -z "${Q}" ]; then \
echo ''; \ echo ''; \
@@ -282,7 +282,7 @@ new_custom: ../custom/HOW_TO_ADD
copy: blkcpy copy: blkcpy
rm -f $@ rm -f $@
cp usage $@ cp blkcpy $@
chmod 0444 $@ chmod 0444 $@
-@if [ -z "${Q}" ]; then \ -@if [ -z "${Q}" ]; then \
echo ''; \ echo ''; \

View File

@@ -1,26 +1,14 @@
Where to get the the latest versions of calc 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/tech/comp/calc/ http://reality.sgi.com/chongo/tech/comp/calc/
One may join the calc testing group by sending a request to: See:
calc-tester-request@postofc.corp.sgi.com http://reality.sgi.com/chongo/tech/comp/calc/calc-download.html
Your message body (not the subject) should consist of: for information on how to obtain up a recent version of calc.
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 Landon Curt Noll
http://reality.sgi.com/chongo http://reality.sgi.com/chongo

View File

@@ -14,12 +14,10 @@ Command sequence
described in the next section. described in the next section.
NOTE: Calc commands are in lower case. UPPER case is used below define a function
for emphasis only, and should be considered in lower case. -----------------
define function(params) { body }
define function(params) = expression
DEFINE function(params) { body }
DEFINE function(params) = expression
This first form defines a full function which can consist This first form defines a full function which can consist
of declarations followed by many statements which implement of declarations followed by many statements which implement
the function. the function.
@@ -30,13 +28,22 @@ Command sequence
and question mark operators can be useful. Examples of and question mark operators can be useful. Examples of
simple functions are: simple functions are:
define sumcubes(a, b) = a^3 + b^3; define sumcubes(a, b) = a^3 + b^3
define pimod(a) = a % pi(); 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. This reads definitions from the specified filename.
The name can be quoted if desired. The calculator The name can be quoted if desired. The calculator
uses the CALCPATH environment variable to search uses the CALCPATH environment variable to search
@@ -52,14 +59,11 @@ Command sequence
evaluate or functions to define, just like at the top evaluate or functions to define, just like at the top
level command level. level command level.
If the -m mode disallows opening of files for reading, When -once is given, the read command acts like the regular
this command will be disabled. read expect that it will ignore filename if is has been
previously read.
READ -once filename The read -once form is particularly useful in a library that
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
needs to read a 2nd library. By using the READ -once needs to read a 2nd library. By using the READ -once
command, one will not reread that 2nd library, nor will command, one will not reread that 2nd library, nor will
once risk entering into a infinite READ loop (where 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, If the -m mode disallows opening of files for reading,
this command will be disabled. this command will be disabled.
WRITE filename
write calc commands
-------------------
write filename
This writes the values of all global variables to the This writes the values of all global variables to the
specified filename, in such a way that the file can be specified filename, in such a way that the file can be
later read in order to recreate the variable values. 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, If the -m mode disallows opening of files for writing,
this command will be disabled. this command will be disabled.
QUIT
This leaves the calculator, when given as a top-level
command.
CD quit or exit
Change the current directory to the home directory, if $HOME ------------
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. 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: Also see the help topic:
statement flow control and declaration statements statement flow control and declaration statements
usage for -m modes usage how to invoke the calc command and calc -options

View File

@@ -40,9 +40,10 @@ Configuration parameters
"blkverbose" TRUE=>print all lines, FALSE=>skip duplicates "blkverbose" TRUE=>print all lines, FALSE=>skip duplicates
"blkbase" block output base "blkbase" block output base
"blkfmt" block output format "blkfmt" block output format
"lib_debug" calc library script debug level "lib_debug" controls library script debug information
"calc_debug" internal calc debug level "calc_debug" controls internal calc debug information
"user_debug" user defined debug level "user_debug" for user defined debug information
"verbose_quit" TRUE=>print message on empty quit or abort
The "all" config value allows one to save/restore the configuration The "all" config value allows one to save/restore the configuration
@@ -78,7 +79,8 @@ Configuration parameters
The "newstd" is not backward compatible with the historic The "newstd" is not backward compatible with the historic
configuration. Even so, some people prefer this configuration configuration. Even so, some people prefer this configuration
and place the config("all", "newstd") command in their CALCRC 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.
When nonzero, the "trace" parameter activates one or more features When nonzero, the "trace" parameter activates one or more features
that may be useful for debugging. These features correspond to that may be useful for debugging. These features correspond to
@@ -103,9 +105,12 @@ Configuration parameters
the decimal point to be printed in real or exponential mode in the decimal point to be printed in real or exponential mode in
normal unformatted printing (print, strprint, fprint) or in normal unformatted printing (print, strprint, fprint) or in
formatted printing (printf, strprintf, fprintf) when precision is not formatted printing (printf, strprintf, fprintf) when precision is not
specified. The initial value is 20. This parameter does not change specified. The initial value for oldstd is 20, for newstd 10.
the stored value of a number. Where rounding is necessary, the type The parameter may be changed to the value d by either
of rounding to be used is controlled by "outround". 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").
The "epsilon" parameter specifies the default accuracy for the The "epsilon" parameter specifies the default accuracy for the
calculation of functions for which exact values are not possible or calculation of functions for which exact values are not possible or
@@ -118,9 +123,10 @@ Configuration parameters
absolute value of the remainder usually does not exceed epsilon/2. absolute value of the remainder usually does not exceed epsilon/2.
Functions which require an epsilon value accept an Functions which require an epsilon value accept an
optional argument which overrides this default epsilon value for optional argument which overrides this default epsilon value for
that single call. (The value v can be assigned to the "epsilon" 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 parameter by either config("epsilon", v) or epsilon(v); each of
current value obtained by epsilon() as well as by config("epsilon").) 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 For the transcendental functions and the functions sqrt() and
appr(), the calculated value is always a multiple of epsilon. appr(), the calculated value is always a multiple of epsilon.
@@ -311,67 +317,72 @@ Configuration parameters
The default "blkfmt" is "hd". The default "blkfmt" is "hd".
With regards to "lib_debug", "calc_debug" and "user_debug": The "lib_debug" parameter is intended for controlling the possible
higher absolute values result in more detailed debugging and display of special information relating to functions, objects, and
more verbose debug messages. The default value is 0 in which other structures created by instructions in calc scripts.
a very amount of debugging will be performed with nil messages. Zero value of config("lib_debug") means that no such information
The -1 value is reserved for no debugging or messages. Any is displayed. For other values, the non-zero bits which currently
value <-1 will perform debugging silently (presumably collecting have meanings are as follows:
data to be displayed at a later time). Values >0 result in a
greater degree of debugging and more verbose messages.
The "lib_debug" is reserved by convention for calc library scripts. n Meaning of bit n of config("lib_debug")
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 0 When a function is defined, redefined or undefined at
debug actions and information may be collected interactive level, a message saying what has been done
is displayed.
-1 no debug messages are printed, no debug actions will be taken 1 When a function is defined, redefined or undefined during
the reading of a file, a message saying what has been done
is displayed.
0 only usage message regarding each important object are The value for config("lib_debug") in both oldstd and newstd is 3,
printed at the time of the read (default) 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.
>0 messages regarding each important object are The "calc_debug" is intended for controlling internal calc routines
printed at the time of the read in addition that test its operation, or collect or display information that
to other debug messages 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:
The "calc_debug" is reserved by convention for internal calc routines. n Meaning of bit n of config("calc_debug")
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 reserved for future use 0 outputs shell commands prior to execution
-1 no debug messages are printed, no debug actions will be taken 1 outputs currently active functions when a quit instruction
is executed
0 very little, if any debugging is performed (and then mostly 2 some details of shs, shs1 and md5 hash states are included
in alpha test code). The only output is as a result of in the output when these are printed
internal fatal errors (typically either math_error() or
exit() will be called). (default)
>0 a greater degree of debugging is performed and more 3 when a function constructs a block value, tests are
verbose messages are printed (regress.cal uses 1). 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.
Bits >= 4 are reserved for future use and should not be used at this time.
The "user_debug" is provided for use by users. Calc ignores this value 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"). 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 No calc code or shipped library should change this value. Users
during startup or during a config("all", xyz) call. 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". The "verbose_quit" controls the print of the message:
These are only suggestions: feel free to use it as you like:
<-1 no debug messages are printed though some internal Quit or abort executed
debug actions and information may be collected
-1 no debug messages are printed, no debug actions will be taken when a non-interactive quit or abort without an argument is encounted.
A quit of abort without an argument does not display a message when
0 very little, if any debugging is performed. The only output invoked at the interactive level.
are from fatal errors. (default)
>0 a greater degree of debugging is performed and more
verbose messages are printed
The following are synonyms for true: The following are synonyms for true:

View File

@@ -5,30 +5,27 @@ We welcome and encourage you to send us:
* custom functions that you have modified or written * custom functions that you have modified or written
* any other source code modifications * any other source code modifications
Prior to doing so, you should consider trying your changes on the most Prior to doing so, you should consider applying your changes to the most
recent alpha test code. To obtain the most recent code, look under recent version of calc.
Landon Noll maintains the official calc home page at:
http://reality.sgi.com/chongo/tech/comp/calc/ http://reality.sgi.com/chongo/tech/comp/calc/
You should also consider joining the calc testing group by sending a See:
request to:
calc-tester-request@postofc.corp.sgi.com http://reality.sgi.com/chongo/tech/comp/calc/calc-download.html
Your message body (not the subject) should consist of: for information on how to obtain up a recent version of calc.
subscribe calc-tester address =-=
end
name your_full_name
where "address" is your EMail address and "your_full_name"
is your full name.
In order to consider integrating your code, we need: In order to consider integrating your code, we need:
* help files (documentation) * the calc version you are working with (use the latest calc, see above)
* CHANGES text (brief description of what it does) * new help files or help file patches, if applicable (documentation)
* regress.cal test (to test non-custom code) * 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 (:-)) * your source code and/or source code changes (:-))
The best way to send us new code, if your changes are small, is The best way to send us new code, if your changes are small, is
@@ -45,6 +42,21 @@ 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 work by a number of people. It would not be what it is today without
your efforts and submissions! your efforts and submissions!
=-=
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.
Landon Curt Noll Landon Curt Noll
http://reality.sgi.com/chongo http://reality.sgi.com/chongo

View File

@@ -22,41 +22,10 @@ Credits
Most of this source and binary has one of the following copyrights: Most of this source and binary has one of the following copyrights:
Copyright (c) 19xx David I. Bell Copyright (c) year David I. Bell
Copyright (c) 19xx David I. Bell and Landon Curt Noll Copyright (c) year David I. Bell and Landon Curt Noll
Copyright (c) 19xx Landon Curt Noll Copyright (c) year Landon Curt Noll
Copyright (c) 19xx Ernest Bowen and Landon Curt Noll Copyright (c) year Ernest Bowen and Landon Curt Noll
Permission is granted to use, distribute, or modify this source, Permission is granted to use, distribute, or modify this source,
provided that this copyright notice remains intact. 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:
calc-tester@postofc.corp.sgi.com
Landon Noll maintains the official calc http/ftp archive at:
ftp://reality.sgi.com/users/chongo/src/calc
http://reality.sgi.com/chongo/src/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/tech/comp/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

@@ -1,5 +1,5 @@
NAME NAME
hash - hash value hash - FNV-1 hash value
SYNOPSIS SYNOPSIS
hash(x_1 [, x_2, x_3, ...]) hash(x_1 [, x_2, x_3, ...])
@@ -12,10 +12,32 @@ TYPES
DESCRIPTION DESCRIPTION
Returns a hash value for one or more values of arbitrary types. 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 EXAMPLE
> a = isqrt(2e1000); s = "xyz"; > a = isqrt(2e1000); s = "xyz";
> hash(a,s) > hash(a,s)
870000771 2378490456
LIMITS LIMITS
The number of arguments is not to exceed 100. The number of arguments is not to exceed 100.
@@ -24,3 +46,4 @@ LIBRARY
none none
SEE ALSO SEE ALSO
sha, sha1, md5

View File

@@ -71,6 +71,10 @@
help stdlib 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: A full and extensive overview of calc may be obtained by:
help full help full
@@ -160,5 +164,3 @@
These can contain both functions to be defined, and expressions These can contain both functions to be defined, and expressions
to be calculated. Global variables which are numbers can be to be calculated. Global variables which are numbers can be
saved to a file by using the 'write filename' command. saved to a file by using the 'write filename' command.
XXX - update this file and add in new major features

View File

@@ -10,28 +10,38 @@ Statements
expressions are optional and may be omitted (as in RETURN). expressions are optional and may be omitted (as in RETURN).
NOTE: Calc commands are in lower case. UPPER case is used below C-like statements
for emphasis only, and should be considered in lower case. -----------------
{ statement }
{ statement; ... statement }
IF (expr) statement if (expr) statement
IF (expr) statement ELSE statement if (expr) statement ELSE statement
FOR (optionalexpr ; optionalexpr ; optionalexpr) statement for (optionalexpr ; optionalexpr ; optionalexpr) statement
WHILE (expr) statement while (expr) statement
DO statement WHILE (expr) do statement while (expr)
CONTINUE continue
BREAK break
GOTO label goto label
These all work like in normal C. 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 This returns a value from a function. Functions always
have a return value, even if this statement is not used. have a return value, even if this statement is not used.
If no return statement is executed, or if no expression If no return statement is executed, or if no expression
is specified in the return statement, then the return is specified in the return statement, then the return
value from the function is the null type. value from the function is the null type.
SWITCH (expr) { caseclauses }
switch
------
switch (expr) { caseclauses }
Switch statements work similarly to C, except for the Switch statements work similarly to C, except for the
following. A switch can be done on any type of value, following. A switch can be done on any type of value,
and the case statements can be of any type of values. 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 is the exception, and only matches once all other cases
have been tested. 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] ... matrix
MAT variable [dimension, dimension, ...] ------
MAT variable [] = { value, ... } mat variable [dimension] [dimension] ...
mat variable [dimension, dimension, ...]
mat variable [] = { value, ... }
This creates a matrix variable with the specified dimensions. This creates a matrix variable with the specified dimensions.
Matrices can have from 1 to 4 dimensions. When specifying Matrices can have from 1 to 4 dimensions. When specifying
multiple dimensions, you can use either the standard C syntax, multiple dimensions, you can use either the standard C syntax,
@@ -119,8 +124,11 @@ Statements
local mat temp[5]; local mat temp[5];
static mat strtable[] = {"hi", "there", "folks"); 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 These create a new object type, or create one or more
variables of the specified type. For this calculator, variables of the specified type. For this calculator,
an object is just a structure which is implicitly acted an object is just a structure which is implicitly acted
@@ -183,33 +191,12 @@ Statements
static obj point temp2 = {4, 3}; static obj point temp2 = {4, 3};
global obj point p1, p2, p3; 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, print expressions
in order to stop a calculation cleanly. For example, -----------------
for a square root routine, an error can be given if the print expr
supplied parameter was a negative number, as in: print expr, ... expr
print expr: ... expr
define mysqrt(n)
{
if (n < 0)
quit "Negative argument";
...
}
Exit is an alias for quit.
PRINT exprs
For interactive expression evaluation, the values of all For interactive expression evaluation, the values of all
typed-in expressions are automatically displayed to the typed-in expressions are automatically displayed to the
user. However, within a function or loop, the printing of user. However, within a function or loop, the printing of
@@ -247,25 +234,9 @@ Statements
prints the name of the file that was opened. 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: Also see the help topic:
command top level commands command top level commands
expression calc expression syntax
builtin calc builtin functions
usage how to invoke the calc command and calc -options

View File

@@ -21,8 +21,33 @@ Very High priority items:
* Update the errmax about the meaning of errmax(-1). * Update the errmax about the meaning of errmax(-1).
* Document the new meanings for bit values and the sign of * Review and if needed, correct/update the help topics:
of config("lib_debug") in the appropriate help file(s).
topic description
----- -----------
intro introduction to calc
overview overview of calc
assoc using associations
command top level commands
config configuration parameters
define how to define functions
environment how environment variables effect calc
errorcodes calc generated error codes
expression expression sequences
file using files
history command history
interrupt how interrupts are handled
list using lists
mat using matrices
obj user defined data types
operator math, relational, logic and variable access ...
statement flow control and declaration statements
types builtin data types
unexpected unexpected syntax/usage surprises for C ...
variable variables and variable declarations
libcalc using the arbitrary precision routines in ...
bugs known bugs and mis-features
wishlist wish list of future enhancements of calc
* Fix any 'Known bugs' as noted in the BUGS file or as * Fix any 'Known bugs' as noted in the BUGS file or as
displayed by 'calc help bugs'. displayed by 'calc help bugs'.
@@ -61,6 +86,8 @@ High priority items:
ensure that they have not introduced new or re-introduced old bugs ensure that they have not introduced new or re-introduced old bugs
into calc. into calc.
* Consider using configure to build the calc Makefile.
=-= =-=
Medium priority items: Medium priority items:
@@ -91,3 +118,6 @@ Medium priority items:
other stuff) in a separate library. other stuff) in a separate library.
* Clean the source code and document it better. * Clean the source code and document it better.
* Add a builtin function to access the 64 bit FNV hash which
is currently being used internally in seed.c.

View File

@@ -19,6 +19,10 @@ Calc command line
will cause calc to try to process each line being read will cause calc to try to process each line being read
despite the errors that it encounters. despite the errors that it encounters.
By default, calc startup scripts ($CALCRC) are silently
ignored if not found. This flag will report missing
startup scripts unless -d is also given.
-C Permit the execution of custom builtin functions. Without -C Permit the execution of custom builtin functions. Without
this flag, calling the custom() builtin function will this flag, calling the custom() builtin function will
simply generate an error. simply generate an error.
@@ -48,6 +52,9 @@ Calc command line
It's nearly ten past six. It's nearly ten past six.
This flag disables the reporting of missing calc
startup scripts ($CALCRC).
-e Ignore any environment variables on startup. The -e Ignore any environment variables on startup. The
getenv() builtin will still return values, however. getenv() builtin will still return values, however.

View File

@@ -179,37 +179,3 @@ Calc Enhancement Wish List:
* Add read -once -try "filename" which would do nothing * Add read -once -try "filename" which would do nothing
if "filename" was not a readable file. if "filename" was not a readable file.
* Blocks should have the following features:
+ read/write to/from files (ala fread/fwrite)
+ misc memory functions (ala memcpy, memcmp, memset,
memchr, etc.)
+ scatter and gather functions (to send every n-th octet
to another block and to copy from n blocks, the 1st
then 2nd then 3rd ... octets)
* Printing of blocks should be under the control of the
config() interface. This should allow one to select
from any of the following formats:
+ as one long string
+ as a series of lines (< 80 chars wide)
+ in od command style (offset: value value value ...)
+ in hex dump style (offset: val val val val ... 3hf.Uas.c)
* In addition one should be able to control the following
aspects of printing blocks via the config() interface:
+ base (hex, octal, char, base 2)
+ amount of data (the first n octets or the entire block)
+ skipping printing of duplicate print lines (ala od)
+ have the ability to print the block as raw data

5
hist.c
View File

@@ -242,7 +242,7 @@ int
hist_getline(char *prompt, char *buf, int len) hist_getline(char *prompt, char *buf, int len)
{ {
if (!inited) if (!inited)
(void) hist_init((char *) NULL); (void) hist_init(calcbindings);
HS.prompt = prompt; HS.prompt = prompt;
HS.bufsize = len - 2; HS.bufsize = len - 2;
@@ -455,9 +455,10 @@ do_bind_line(KEY_MAP *map, char *line)
if (*cp == '?') { if (*cp == '?') {
key = 0177; key = 0177;
cp++; cp++;
} else } else {
key = CONTROL(*cp++); key = CONTROL(*cp++);
} }
}
else if (key == '\\') else if (key == '\\')
key = *cp++; key = *cp++;

34
input.c
View File

@@ -12,6 +12,12 @@
#include <pwd.h> #include <pwd.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include "have_unistd.h"
#if defined(HAVE_UNISTD_H)
#include <unistd.h>
#endif
#include "calc.h" #include "calc.h"
#include "conf.h" #include "conf.h"
#include "hist.h" #include "hist.h"
@@ -633,6 +639,9 @@ ttychar(void)
if (*cmd == '\0' || *cmd == '\n') if (*cmd == '\0' || *cmd == '\n')
cmd = shell; cmd = shell;
if (allow_exec) { if (allow_exec) {
if (conf->calc_debug & CALCDBG_SYSTEM) {
printf("%s\n", cmd);
}
system(cmd); system(cmd);
} else { } else {
fprintf(stderr, "execution disallowed by -m flag\n"); fprintf(stderr, "execution disallowed by -m flag\n");
@@ -719,34 +728,35 @@ runrcfiles(void)
{ {
char path[MAX_CALCRC+1+1]; /* name being searched for */ char path[MAX_CALCRC+1+1]; /* name being searched for */
char *cp; char *cp;
char *newcp;
char *p; char *p;
int i;
/* execute each file in the list */ /* execute each file in the list */
for (cp=calcrc, newcp=(char *)strchr(calcrc, LISTCHAR); while (calcrc != NULL && *calcrc) {
cp != NULL && *cp; cp = calcrc;
cp = newcp, calcrc = (char *) strchr(calcrc + 1, LISTCHAR);
newcp=(newcp) ? (char *)strchr(newcp+1, LISTCHAR) : NULL) {
/* load file name into the path */ /* load file name into the path */
if (newcp == NULL) { if (calcrc == NULL) {
strcpy(path, cp); strcpy(path, cp);
} else { } else {
strncpy(path, cp, newcp-cp); strncpy(path, cp, calcrc - cp);
path[newcp-cp] = '\0'; path[calcrc - cp] = '\0';
} }
/* find the start of the path */ /* find the start of the path */
p = (path[0] == ':') ? path+1 : path; p = (path[0] == ':') ? path + 1 : path;
if (p[0] == '\0') { if (p[0] == '\0') {
continue; continue;
} }
/* process the current file in the list */ /* process the current file in the list */
i = openfile(p); if (openfile(p) < 0) {
if (i < 0) /* Unable to open rcfile */
if (c_flag && !d_flag)
fprintf(stderr,
"Unable to open rcfile \"%s\"\n", p);
continue; continue;
}
getcommands(FALSE); getcommands(FALSE);
closeinput(); closeinput();
} }

View File

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

View File

@@ -17,7 +17,7 @@ For example:
will cause calc to load and execute the 'lucas.cal' library. will cause calc to load and execute the 'lucas.cal' library.
Executing the library will cause several functions to be defined. Executing the library will cause several functions to be defined.
Executing the lucas function Executing the lucas function:
> lucas(149,60) > lucas(149,60)
1 1
@@ -50,37 +50,41 @@ version of read:
This will cause the needed library files to be read once. If these This will cause the needed library files to be read once. If these
files have already been read, the read -once will act as a noop. files have already been read, the read -once will act as a noop.
By convention, the config parameter "lib_debug" is used to control The "lib_debug" parameter is intended for controlling the possible
the verbosity of debug information printed by lib files. By default, display of special information relating to functions, objects, and
the "lib_debug" has a value of 0. 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:
The "lib_debug" config parameter takes the place of the lib_debug n Meaning of bit n of config("lib_debug")
global variable. By convention, "lib_debug" has the following meanings:
<-1 no debug messages are printed though some internal 0 When a function is defined, redefined or undefined at
debug actions and information may be collected interactive level, a message saying what has been done
is displayed.
-1 no debug messages are printed, no debug actions will be taken 1 When a function is defined, redefined or undefined during
the reading of a file, a message saying what has been done
is displayed.
0 only usage message regarding each important object are The value for config("lib_debug") in both oldstd and newstd is 3,
printed at the time of the read (default) 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.
>0 messages regarding each important object are Sometimes the information printed is not enough. In addition to the
printed at the time of the read in addition standard information, one might want to print:
to other debug messages
When config("lib_debug") >= 0, function names and their arg are
printed as they are defined. Sometimes this printing is not enough
information. For example:
* useful obj definitions * useful obj definitions
* functions with optional args * functions with optional args
* functions with optional args where the param() interface is used * functions with optional args where the param() interface is used
For these cases we suggest that you place at the bottom of your code For these cases we suggest that you place at the bottom of your code
something like: something that prints extra information if config("lib_debug") has
either of the bottom 2 bits set:
if (config("lib_debug") >= 0) { if (config("lib_debug") & 3) {
print "obj xyz defined"; print "obj xyz defined";
print "funcA([val1 [, val2]]) defined"; print "funcA([val1 [, val2]]) defined";
print "funcB(size, mass, ...) defined"; print "funcB(size, mass, ...) defined";

View File

@@ -174,7 +174,7 @@ define chrem()
} }
} }
if (config("lib_debug") >= 0) { if (config("lib_debug") & 3) {
print "chrem(r1,m1 [,r2,m2 ...]) defined"; print "chrem(r1,m1 [,r2,m2 ...]) defined";
print "chrem(rlist [,mlist]) defined"; print "chrem(rlist [,mlist]) defined";
} }

View File

@@ -111,6 +111,6 @@ define fixdms(a)
a.deg %= 360; a.deg %= 360;
} }
if (config("lib_debug") >= 0) { if (config("lib_debug") & 3) {
print "obj dms {deg, min, sec} defined"; print "obj dms {deg, min, sec} defined";
} }

View File

@@ -1027,7 +1027,7 @@ gen_v1(h, n)
define define
ldebug(funct, str) ldebug(funct, str)
{ {
if (config("lib_debug") > 0) { if (config("lib_debug") & 3) {
print "DEBUG:", funct:":", str; print "DEBUG:", funct:":", str;
} }
return; return;

View File

@@ -331,7 +331,7 @@ lucas_chk(high_n, quiet)
/* skip primes where h>=2^n */ /* skip primes where h>=2^n */
if (highbit(h_p[i]) >= n_p[i]) { if (highbit(h_p[i]) >= n_p[i]) {
if (config("lib_debug") > 0) { if (config("lib_debug") & 3) {
print "h>=2^n skip:", h_p[i]:"*2^":n_p[i]:"-1"; print "h>=2^n skip:", h_p[i]:"*2^":n_p[i]:"-1";
} }
continue; continue;

View File

@@ -152,7 +152,7 @@ d_val[97]=1045; a_val[97]=33; b_val[97]=1; r_val[97]=44;
d_val[99]=9797; a_val[99]=97; b_val[99]=1; r_val[99]=388; d_val[99]=9797; a_val[99]=97; b_val[99]=1; r_val[99]=388;
d_val[100]= 51; a_val[100]= 7; b_val[100]=1; r_val[100]=2; d_val[100]= 51; a_val[100]= 7; b_val[100]=1; r_val[100]=2;
if (config("lib_debug") >= 0) { if (config("lib_debug") & 3) {
print "d_val[100] defined"; print "d_val[100] defined";
print "a_val[100] defined"; print "a_val[100] defined";
print "b_val[100] defined"; print "b_val[100] defined";

View File

@@ -312,6 +312,6 @@ define mfactor(n, start_k, rept_loop, p_elim)
return q; return q;
} }
if (config("lib_debug") >= 0) { if (config("lib_debug") & 3) {
print "mfactor(n [, start_k=1 [, rept_loop=10000 [, p_elim=17]]])" print "mfactor(n [, start_k=1 [, rept_loop=10000 [, p_elim=17]]])"
} }

View File

@@ -189,7 +189,7 @@ define mod_pow(a, b)
} }
if (config("lib_debug") >= 0) { if (config("lib_debug") & 3) {
print "obj mod {a} defined"; print "obj mod {a} defined";
print "mod_value defined"; print "mod_value defined";
print "set mod_value as needed"; print "set mod_value as needed";

View File

@@ -687,6 +687,6 @@ a=pol(1,4,4,2,3,1);
b=pol(5,16,8,1); b=pol(5,16,8,1);
c=pol(1+2i,3+4i,5+6i); c=pol(1+2i,3+4i,5+6i);
if (config("lib_debug") >= 0) { if (config("lib_debug") & 3) {
print "obj poly {p} defined"; print "obj poly {p} defined";
} }

View File

@@ -195,6 +195,6 @@ define quat_shift(a, b)
return x.s; return x.s;
} }
if (config("lib_debug") >= 0) { if (config("lib_debug") & 3) {
print "obj quat {s, v} defined"; print "obj quat {s, v} defined";
} }

View File

@@ -122,6 +122,6 @@ define randrun(run_cnt)
printf("max length=%d\n", max_run); printf("max length=%d\n", max_run);
} }
if (config("lib_debug") >= 0) { if (config("lib_debug") & 3) {
print "randrun([run_length]) defined"; print "randrun([run_length]) defined";
} }

View File

@@ -28,8 +28,9 @@ global ecnt; /* expected value of errcount() */
ecnt = 0; /* clear expected errcount() value */ ecnt = 0; /* clear expected errcount() value */
initcfg = config("all", "oldstd"); /* set config to startup default */ initcfg = config("all", "oldstd"); /* set config to startup default */
initcfg = config("lib_debug", -4); /* disable lib startup messages */ initcfg = config("lib_debug", 0); /* disable lib startup messages */
initcfg = config("calc_debug", 1); /* enable more internal debugging */ initcfg = config("calc_debug", 0); /* disable internal debugging */
initcnf = config("verbose_quit", 0); /* disable quit messages */
initcfg = config("all"); /* save state for later use */ initcfg = config("all"); /* save state for later use */
print '003: parsed global definitions'; print '003: parsed global definitions';
@@ -3302,7 +3303,7 @@ define test_fileops()
print '4261: Ending test_fileops'; print '4261: Ending test_fileops';
} }
print '071: parsed test_redc()'; print '071: parsed test_fileops()';
/* /*
@@ -6861,7 +6862,7 @@ print '181: parsed test_ptr()';
*/ */
define test_newstring() define test_newstring()
{ {
local A, B, C, D, S, p; local A, B, C, D, S, p, q;
print '7700: Beginning test_newstring'; print '7700: Beginning test_newstring';
@@ -6953,7 +6954,14 @@ define test_newstring()
print '7762: setbit(A, 16, 0);'; print '7762: setbit(A, 16, 0);';
vrfy(A == "A\255fdef", '7763: A == "A\255fdef"'); vrfy(A == "A\255fdef", '7763: A == "A\255fdef"');
print '7764: Ending test_newstring'; q = "curds" " and " "whey";
print '7764: q = "curds" " and " "whey"';
vrfy(q == "curds and whey", '7765: q == "curds and whey"');
q = "chongo" ' was ' "here";
print '7766: q = "chongo" \' was \' "here"';
vrfy(q == "chongo was here", '7767: q == "chongo was here"');
print '7768: Ending test_newstring';
} }
print '182: parsed test_newstring()'; print '182: parsed test_newstring()';
@@ -7115,6 +7123,8 @@ print '188: parsed test_natnumset()';
*/ */
define test_somenew() define test_somenew()
{ {
local a, s;
print '8200: Starting test_somenew'; print '8200: Starting test_somenew';
vrfy(char(-1) == char(255), '8201: char(-1) == char(255)'); vrfy(char(-1) == char(255), '8201: char(-1) == char(255)');
@@ -7139,11 +7149,32 @@ define test_somenew()
vrfy(1/(1/0) == 0, '8215: 1/(1/0) == 0'); vrfy(1/(1/0) == 0, '8215: 1/(1/0) == 0');
vrfy(inverse(1/0) == 0, '8216: inverse(1/0) == 0'); vrfy(inverse(1/0) == 0, '8216: inverse(1/0) == 0');
print '8217: Ending test_somenew'; a = isqrt(2e1000); s = "xyz";
print '8217: a = isqrt(2e1000); s = "xyz";';
vrfy(hash(a,s) == 2708885378, '8218: hash(a,s) == 2708885378');
vrfy(hash("curds n whey") == 2376141927,
'8219: hash("curds n whey") == 2376141927');
print '8220: Ending test_somenew';
} }
print '189: parsed test_somenew()'; print '189: parsed test_somenew()';
/*
* test_quit - test the QUIT functionality
*/
define test_quit()
{
print '8400: Starting test_quit';
quit;
prob('quit did not end the test_quit() function');
/* 8400 serise continued after return, do not print end here */
}
print '190: parsed test_quit()';
/* /*
* Reserved for top level test use * Reserved for top level test use
*/ */
@@ -7195,16 +7226,27 @@ print '1700: Beginning read test';
value = 0; value = 0;
vrfy(value == 0, '1701: value == 0'); vrfy(value == 0, '1701: value == 0');
read "test1700"; read "test1700";
vrfy(value == 1, '1702: value == 1'); print '1702: read "test1700";';
read -once "test1700";
vrfy(value == 1, '1703: value == 1'); vrfy(value == 1, '1703: value == 1');
read -once "test1700";
print '1704: read -once "test1700";';
vrfy(value == 1, '1705: value == 1');
read "test1700.cal"; read "test1700.cal";
vrfy(value == 2, '1704: value == 2'); print '1706: read "test1700.cal";';
vrfy(value == 2, '1707: value == 2');
read -once "test1700.cal"; read -once "test1700.cal";
vrfy(value == 2, '1705: value == 2'); print '1708: read -once "test1700.cal";';
vrfy(value == 2, '1709: value == 2');
read "test1700.cal"; read "test1700.cal";
vrfy(value == 3, '1706: value == 3'); print '1710: read "test1700.cal";';
print '1707: Ending read test'; vrfy(value == 3, '1711: value == 3');
{++value;} read "test1700.cal";
print '1712: {++value;} read "test1700.cal";';
vrfy(value == 5, '1713: value == 5');
{++value;} read -once "test1700.cal";
print '1714: {++value;} read -once "test1700.cal";';
vrfy(value == 6, '1715: value == 6');
print '1716: Ending read test';
print; print;
return test_obj(); return test_obj();
@@ -7279,6 +7321,9 @@ print;
return test_size(); return test_size();
print; print;
/*
* 5800 assignment tests
*/
return test_assign(5800, 1); return test_assign(5800, 1);
define xy5800_assign(a,b) { }; define xy5800_assign(a,b) { };
print '5812: define xy5800_assign(a,b) { }'; print '5812: define xy5800_assign(a,b) { }';
@@ -7323,7 +7368,7 @@ X5800 = obj xy5800 = {1,2};
print '5864: X5800 = obj xy5800 = {1,2}'; print '5864: X5800 = obj xy5800 = {1,2}';
vrfy(X5800 == (obj xy5800 = {1,2}), vrfy(X5800 == (obj xy5800 = {1,2}),
'5865: X5800 == (obj xy5800 = {1,2})'); '5865: X5800 == (obj xy5800 = {1,2})');
print '5899: End of 5800 sequence'; print '5866: End of 5800 sequence';
print; print;
return test_is(); return test_is();
@@ -7407,7 +7452,20 @@ print '8304: define h8300(x)=x^3;define i8300(x)=x-1;define j8300(x)=x+1;';
vrfy(h8300(10) == 1000, '8305: h8300(10) == 1000'); vrfy(h8300(10) == 1000, '8305: h8300(10) == 1000');
vrfy(i8300(10) == 9, '8306: i8300(10) == 9'); vrfy(i8300(10) == 9, '8306: i8300(10) == 9');
vrfy(j8300(10) == 11, '8307: j8300(10) == 11'); vrfy(j8300(10) == 11, '8307: j8300(10) == 11');
print '8308: Ending define tests'; {static k8300 = 5} define l8300(x) = k8300 + x;
print '8308: {static k8300 = 5} define l8300(x) = k8300 + x;';
vrfy(l8300(10) == 15, '8309: l8300(10) == 15');
print '8310: Ending define tests';
/*
* quit tests
*/
print;
return test_quit();
read -once test8400;
print '8402: read -once test8400';
print '8403: Ending test_quit';
/* /*
@@ -7423,7 +7481,7 @@ print '8308: Ending define tests';
* lucas_tbl.cal - duplicatres code already read by another file * lucas_tbl.cal - duplicatres code already read by another file
* regress.cal - this file * regress.cal - this file
* surd.cal - already read by this file * surd.cal - already read by this file
* testXXXX.cal - already read by this file * test9999.cal - files of this form are already read by this file
* xx_print.cal - prints a bunch of things when loaded * xx_print.cal - prints a bunch of things when loaded
* *
* We want to do this 2nd to last; ahead of any final cleanup and behind * We want to do this 2nd to last; ahead of any final cleanup and behind

View File

@@ -113,7 +113,7 @@ define seedrandom(seed1, seed2, size, trials)
p = 2*fp+1; p = 2*fp+1;
} while (ptest(p,1,0) == 0); } while (ptest(p,1,0) == 0);
} while(ptest(p, trials) == 0 || ptest(fp, trials) == 0); } while(ptest(p, trials) == 0 || ptest(fp, trials) == 0);
if (config("lib_debug") > 0) { if (config("lib_debug") & 3) {
print "/* 1st Blum prime */ p=", p; print "/* 1st Blum prime */ p=", p;
} }
@@ -127,7 +127,7 @@ define seedrandom(seed1, seed2, size, trials)
q = 2*fq+1; q = 2*fq+1;
} while (ptest(q,1,0) == 0); } while (ptest(q,1,0) == 0);
} while(ptest(q, trials) == 0 || ptest(fq, trials) == 0); } while(ptest(q, trials) == 0 || ptest(fq, trials) == 0);
if (config("lib_debug") > 0) { if (config("lib_debug") & 3) {
print "/* 2nd Blum prime */ q=", q; print "/* 2nd Blum prime */ q=", q;
} }
@@ -137,7 +137,7 @@ define seedrandom(seed1, seed2, size, trials)
n = p*q; /* the Blum modulus */ n = p*q; /* the Blum modulus */
binsize = highbit(n)+1; /* smallest power of 2 > p*q */ binsize = highbit(n)+1; /* smallest power of 2 > p*q */
r = pmod(rand(1<<ceil(binsize*4/5), 1<<(binsize-2)), 2, n); r = pmod(rand(1<<ceil(binsize*4/5), 1<<(binsize-2)), 2, n);
if (config("lib_debug") >= 0) { if (config("lib_debug") & 3) {
print "/* seed quadratic residue */ r=", r; print "/* seed quadratic residue */ r=", r;
print "/* newn", binsize, "bit quadratic residue*/ newn=", n; print "/* newn", binsize, "bit quadratic residue*/ newn=", n;
} }
@@ -154,6 +154,6 @@ define seedrandom(seed1, seed2, size, trials)
return old_state; return old_state;
} }
if (config("lib_debug") >= 0) { if (config("lib_debug") & 3) {
print "seedrandom(seed1, seed2, size [, trials]) defined"; print "seedrandom(seed1, seed2, size [, trials]) defined";
} }

View File

@@ -261,7 +261,7 @@ define surd_rel(a, b)
return sgn(x^2 - y^2 * surd_type) * sgn(x); return sgn(x^2 - y^2 * surd_type) * sgn(x);
} }
if (config("lib_debug") >= 0) { if (config("lib_debug") & 3) {
print "obj surd {a, b} defined"; print "obj surd {a, b} defined";
print "surd_type defined"; print "surd_type defined";
print "set surd_type as needed"; print "set surd_type as needed";

16
lib/test8400.cal Normal file
View File

@@ -0,0 +1,16 @@
/*
* Copyright (c) 1999 Landon Curt Noll
* Permission is granted to use, distribute, or modify this source,
* provided that this copyright notice remains intact.
*
* By: Landon Curt Noll
* http://reality.sgi.com/chongo
*
* chongo <was here> /\../\
*
* This library is used by the 8400 series of the regress.cal test suite.
*/
print "8401: in test8400.cal";
quit;
prob('quit did not end test8400.cal');

View File

@@ -23,6 +23,6 @@ define sc()
return s; return s;
} }
if (config("lib_debug") >= 0) { if (config("lib_debug") & 3) {
print "sc(a, b, ...) defined"; print "sc(a, b, ...) defined";
} }

View File

@@ -89,16 +89,17 @@ int i_flag = FALSE; /* TRUE => go interactive if permitted */
/* /*
* global values * global values
*/ */
char *calcpath; /* $CALCPATH or default */ char *calcpath = NULL; /* $CALCPATH or default */
char *calcrc; /* $CALCRC or default */ char *calcrc = NULL; /* $CALCRC or default */
char *calcbindings; /* $CALCBINDINGS or default */ char *calcbindings = NULL; /* $CALCBINDINGS or default */
char *home; /* $HOME or default */ char *home = NULL; /* $HOME or default */
char *pager; /* $PAGER or default */ char *pager = NULL; /* $PAGER or default */
char *shell; /* $SHELL or default */ char *shell = NULL; /* $SHELL or default */
int stdin_tty = FALSE; /* TRUE if stdin is a tty */ int stdin_tty = FALSE; /* TRUE if stdin is a tty */
int havecommands = FALSE; /* TRUE if have one or more cmd args */ int havecommands = FALSE; /* TRUE if have one or more cmd args */
int stoponerror = FALSE; /* >0 => stop, <0 => continue on error */ int stoponerror = FALSE; /* >0 => stop, <0 => continue on error */
int post_init = FALSE; /* TRUE setjmp for math_error is ready */ int post_init = FALSE; /* TRUE setjmp for math_error is ready */
BOOL abort_now = FALSE; /* TRUE => go interactive now, if permitted */
int no_env = FALSE; /* TRUE (-e) => ignore env vars on startup */ int no_env = FALSE; /* TRUE (-e) => ignore env vars on startup */
int errmax = ERRMAX; /* if >= 0, maximum value for errcount */ int errmax = ERRMAX; /* if >= 0, maximum value for errcount */

View File

@@ -1213,8 +1213,9 @@ matcopy(MATRIX *m)
if (v1->v_type == V_NUM) { if (v1->v_type == V_NUM) {
v2->v_type = V_NUM; v2->v_type = V_NUM;
v2->v_num = qlink(v1->v_num); v2->v_num = qlink(v1->v_num);
} else } else {
copyvalue(v1, v2); copyvalue(v1, v2);
}
v1++; v1++;
v2++; v2++;
} }

2
md5.c
View File

@@ -656,7 +656,7 @@ MD5_print(HASH *state)
/* /*
* form the hash value * form the hash value
*/ */
if (conf->calc_debug > 0) { if (conf->calc_debug & CALCDBG_HASH_STATE) {
char buf[DEBUG_SIZE+1]; /* hash value buffer */ char buf[DEBUG_SIZE+1]; /* hash value buffer */
/* /*

6
obj.c
View File

@@ -640,9 +640,10 @@ objfree(OBJECT *op)
for (i = op->o_actions->count; i-- > 0; vp++) { for (i = op->o_actions->count; i-- > 0; vp++) {
if (vp->v_type == V_NUM) { if (vp->v_type == V_NUM) {
qfree(vp->v_num); qfree(vp->v_num);
} else } else {
freevalue(vp); freevalue(vp);
} }
}
if (op->o_actions->count <= USUAL_ELEMENTS) if (op->o_actions->count <= USUAL_ELEMENTS)
free(op); free(op);
else else
@@ -678,8 +679,9 @@ objcopy(OBJECT *op)
if (v1->v_type == V_NUM) { if (v1->v_type == V_NUM) {
v2->v_num = qlink(v1->v_num); v2->v_num = qlink(v1->v_num);
v2->v_type = V_NUM; v2->v_type = V_NUM;
} else } else {
copyvalue(v1, v2); copyvalue(v1, v2);
}
v2->v_subtype = V_NOSUBTYPE; v2->v_subtype = V_NOSUBTYPE;
} }
return np; return np;

View File

@@ -2065,9 +2065,9 @@ o_isdefined(void)
} }
r = 0; r = 0;
index = getbuiltinfunc(vp->v_str->s_str); index = getbuiltinfunc(vp->v_str->s_str);
if (index >= 0) if (index >= 0) {
r = 1; r = 1;
else { } else {
index = getuserfunc(vp->v_str->s_str); index = getuserfunc(vp->v_str->s_str);
if (index >= 0) if (index >= 0)
r = 2; r = 2;
@@ -3138,14 +3138,22 @@ o_quit(FUNC *fp, long index)
} }
if (cp) if (cp)
printf("%s\n", cp); printf("%s\n", cp);
else else if (conf->verbose_quit)
printf("Quit statement executed\n"); printf("Quit or abort executed\n");
if (!inputisterminal() && fp->f_name[0] == '*') if (!inputisterminal() && fp->f_name[0] == '*')
closeinput(); closeinput();
go = FALSE; go = FALSE;
} }
static void
o_abort(FUNC *fp, long index)
{
abort_now = TRUE;
o_quit(fp, index);
}
static void static void
o_getepsilon(void) o_getepsilon(void)
{ {
@@ -3533,7 +3541,8 @@ static struct opcode opcodes[MAX_OPCODE+1] = {
{o_backslash, OPNUL, "BACKSLASH"}, /* unary backslash op */ {o_backslash, OPNUL, "BACKSLASH"}, /* unary backslash op */
{o_setminus, OPNUL, "SETMINUS"}, /* binary backslash op */ {o_setminus, OPNUL, "SETMINUS"}, /* binary backslash op */
{o_plus, OPNUL, "PLUS"}, /* unary + op */ {o_plus, OPNUL, "PLUS"}, /* unary + op */
{o_jumpnn, OPJMP, "JUMPNN"} /* jump if non-null */ {o_jumpnn, OPJMP, "JUMPNN"}, /* jump if non-null */
{o_abort, OPONE, "ABORT"} /* abort operation */
}; };
@@ -3567,6 +3576,7 @@ calculate(FUNC *fp, int argcount)
funcname = fp->f_name; funcname = fp->f_name;
funcline = 0; funcline = 0;
go = TRUE; go = TRUE;
abort_now = FALSE;
origargcount = argcount; origargcount = argcount;
while (argcount < fp->f_paramcount) { while (argcount < fp->f_paramcount) {
stack++; stack++;
@@ -3697,12 +3707,20 @@ calculate(FUNC *fp, int argcount)
freevalue(&locals[i]); freevalue(&locals[i]);
if (locals != localtable) if (locals != localtable)
free(locals); free(locals);
if (conf->calc_debug & 2) if (conf->calc_debug & CALCDBG_FUNC_QUIT)
printf("\t\"%s\": line %ld\n", funcname, funcline); printf("\t\"%s\": line %ld\n", funcname, funcline);
while (stack > beginstack) while (stack > beginstack)
freevalue(stack--); freevalue(stack--);
funcname = oldname; funcname = oldname;
funcline = oldline; funcline = oldline;
if (abort_now && stack == stackarray) {
if (!stdin_tty)
run_state = RUN_EXIT;
else if (run_state < RUN_PRE_TOP_LEVEL)
run_state = RUN_PRE_TOP_LEVEL;
freefunc(curfunc);
longjmp(jmpbuf, 1);
}
return; return;
} }
@@ -3748,8 +3766,10 @@ dumpop(unsigned long *pc)
case OP_PRINTSTRING: case OP_STRING: case OP_PRINTSTRING: case OP_STRING:
printf(" \"%s\"\n", findstring((long)(*pc))->s_str); printf(" \"%s\"\n", findstring((long)(*pc))->s_str);
return 2; return 2;
case OP_QUIT: case OP_QUIT: case OP_ABORT:
printf(" \"%s\"\n", findstring((long)(*pc))->s_str); if ((long)(*pc) >= 0)
printf(" \"%s\"", findstring((long)(*pc))->s_str);
putchar('\n');
return 2; return 2;
case OP_INDEXADDR: case OP_INDEXADDR:
printf(" %ld %ld\n", pc[0], pc[1]); printf(" %ld %ld\n", pc[0], pc[1]);

View File

@@ -144,7 +144,8 @@
#define OP_SETMINUS 129L /* binary backslash */ #define OP_SETMINUS 129L /* binary backslash */
#define OP_PLUS 130L /* unary + */ #define OP_PLUS 130L /* unary + */
#define OP_JUMPNN 131L /* jump if top value is non-null */ #define OP_JUMPNN 131L /* jump if top value is non-null */
#define MAX_OPCODE 131L /* highest legal opcode */ #define OP_ABORT 132L /* abort operation */
#define MAX_OPCODE 132L /* highest legal opcode */
/* /*

13
poly.c
View File

@@ -31,20 +31,17 @@ evp(LISTELEM *cp, LISTELEM *x, VALUE *vres)
freevalue(&tmp1); freevalue(&tmp1);
freevalue(vres); freevalue(vres);
*vres = tmp2; *vres = tmp2;
} } else {
else {
s = TRUE; s = TRUE;
*vres = tmp1; *vres = tmp1;
} }
} }
} } else {
else {
if (s) { if (s) {
addvalue(&v, vres, &tmp1); addvalue(&v, vres, &tmp1);
freevalue(vres); freevalue(vres);
*vres = tmp1; *vres = tmp1;
} } else {
else {
s = TRUE; s = TRUE;
copyvalue(&v, vres); copyvalue(&v, vres);
} }
@@ -126,9 +123,9 @@ addlistinv(LIST *lp, VALUE *vres)
VALUE tmp1, tmp2; VALUE tmp1, tmp2;
for (ep = lp->l_first; ep; ep = ep->e_next) { for (ep = lp->l_first; ep; ep = ep->e_next) {
if (ep->e_value.v_type == V_LIST) if (ep->e_value.v_type == V_LIST) {
addlistinv(ep->e_value.v_list, vres); addlistinv(ep->e_value.v_list, vres);
else { } else {
invertvalue(&ep->e_value, &tmp1); invertvalue(&ep->e_value, &tmp1);
addvalue(vres, &tmp1, &tmp2); addvalue(vres, &tmp1, &tmp2);
freevalue(&tmp1); freevalue(&tmp1);

View File

@@ -1156,9 +1156,9 @@ qcfappr(NUMBER *q, NUMBER *epsilon, long rnd)
s = -s; s = -s;
} }
if (bnddencase) { if (bnddencase) {
if (s > 0) if (s > 0) {
useold = TRUE; useold = TRUE;
else { } else {
zsub(zden, denbnd, &tmp1); zsub(zden, denbnd, &tmp1);
zquo(tmp1, oldden, &k, 1); zquo(tmp1, oldden, &k, 1);
zfree(tmp1); zfree(tmp1);

3
qio.c
View File

@@ -413,8 +413,9 @@ qprintfd(NUMBER *q, long width)
zquo(q->num, q->den, &z, conf->outround); zquo(q->num, q->den, &z, conf->outround);
zprintval(z, 0L, width); zprintval(z, 0L, width);
zfree(z); zfree(z);
} else } else {
zprintval(q->num, 0L, width); zprintval(q->num, 0L, width);
}
} }

12
qmod.c
View File

@@ -116,15 +116,13 @@ qquomod(NUMBER *q1, NUMBER *q2, NUMBER **retqdiv, NUMBER **retqmod)
zfree(tmp2); zfree(tmp2);
qq = qlink(&_qzero_); qq = qlink(&_qzero_);
qm = qlink(q1); qm = qlink(q1);
} } else {
else {
qq = qalloc(); qq = qalloc();
qq->num = tmp1; qq->num = tmp1;
if (ziszero(tmp2)) { if (ziszero(tmp2)) {
zfree(tmp2); zfree(tmp2);
qm = qlink(&_qzero_); qm = qlink(&_qzero_);
} } else {
else {
qm = qalloc(); qm = qalloc();
qm->num = tmp2; qm->num = tmp2;
} }
@@ -141,15 +139,13 @@ qquomod(NUMBER *q1, NUMBER *q2, NUMBER **retqdiv, NUMBER **retqmod)
zfree(tmp4); zfree(tmp4);
qq = qlink(&_qzero_); qq = qlink(&_qzero_);
qm = qlink(q1); qm = qlink(q1);
} } else {
else {
qq = qalloc(); qq = qalloc();
qq->num = tmp3; qq->num = tmp3;
if (ziszero(tmp4)) { if (ziszero(tmp4)) {
zfree(tmp4); zfree(tmp4);
qm = qlink(&_qzero_); qm = qlink(&_qzero_);
} } else {
else {
qm = qalloc(); qm = qalloc();
zmul(q1->den, q2->den, &tmp1); zmul(q1->den, q2->den, &tmp1);
zreduce(tmp4, tmp1, &qm->num, &qm->den); zreduce(tmp4, tmp1, &qm->num, &qm->den);

View File

@@ -1022,8 +1022,7 @@ qpower(NUMBER *q1, NUMBER *q2, NUMBER *epsilon)
tmp1 = itoq(m); tmp1 = itoq(m);
tmp2 = qmul(tmp1, q2tmp); tmp2 = qmul(tmp1, q2tmp);
m = qtoi(tmp2); m = qtoi(tmp2);
} } else {
else {
tmp1 = qdec(q1tmp); tmp1 = qdec(q1tmp);
tmp2 = qqdiv(tmp1, q1tmp); tmp2 = qqdiv(tmp1, q1tmp);
qfree(tmp1); qfree(tmp1);
@@ -1038,8 +1037,7 @@ qpower(NUMBER *q1, NUMBER *q2, NUMBER *epsilon)
tmp1 = itoq(m + 1); tmp1 = itoq(m + 1);
tmp2 = qmul(tmp1, q2tmp); tmp2 = qmul(tmp1, q2tmp);
m = qtoi(tmp2); m = qtoi(tmp2);
} } else {
else {
tmp1 = qdec(q1tmp); tmp1 = qdec(q1tmp);
tmp2 = qmul(tmp1, q2tmp); tmp2 = qmul(tmp1, q2tmp);
qfree(tmp1); qfree(tmp1);

View File

@@ -56,11 +56,6 @@
#include "zrand.h" #include "zrand.h"
#include "zrandom.h" #include "zrandom.h"
#define ZMOST 2 /* most significant HALFs to hash */
#define ZLEAST 2 /* least significant HALFs to hash */
#define ZMIDDLE 4 /* HALFs in the middle to hash */
/* /*
* forward declarations * forward declarations
*/ */
@@ -71,7 +66,8 @@ static QCKHASH objhash(OBJECT *op, QCKHASH val);
static QCKHASH randhash(RAND *r, QCKHASH val); static QCKHASH randhash(RAND *r, QCKHASH val);
static QCKHASH randomhash(RANDOM *state, QCKHASH val); static QCKHASH randomhash(RANDOM *state, QCKHASH val);
static QCKHASH config_hash(CONFIG *cfg, QCKHASH val); static QCKHASH config_hash(CONFIG *cfg, QCKHASH val);
static QCKHASH fnv_strhash(char *str, QCKHASH val); static QCKHASH fnv_strhash(char *ch, QCKHASH val);
static QCKHASH fnv_STRhash(STRING *str, QCKHASH val);
static QCKHASH fnv_fullhash(FULL *v, LEN len, QCKHASH val); static QCKHASH fnv_fullhash(FULL *v, LEN len, QCKHASH val);
static QCKHASH fnv_zhash(ZVALUE z, QCKHASH val); static QCKHASH fnv_zhash(ZVALUE z, QCKHASH val);
static QCKHASH hash_hash(HASH *hash, QCKHASH val); static QCKHASH hash_hash(HASH *hash, QCKHASH val);
@@ -79,22 +75,29 @@ static QCKHASH blk_hash(BLOCK *blk, QCKHASH val);
/* /*
* fnv - compute the next Fowler/Noll/Vo hash given a variable * FNV-0 - Fowler/Noll/Vo-0 32 bit hash
* *
* The basis of the hash algorithm was taken from an idea * The basis of this hash algorithm was taken from an idea sent
* sent by Email to the IEEE Posix P1003.2 mailing list from * as reviewer comments to the IEEE POSIX P1003.2 committee by:
* Phong Vo (kpv@research.att.com) and Glenn Fowler (gsf@research.att.com).
* Landon Curt Noll (http://reality.sgi.com/chongo) later improved on there
* algorithm to come up with Fowler/Noll/Vo hash.
* *
* The magic lies in the constant 16777619, which for 32 bit hashing * Phong Vo (http://www.research.att.com/info/kpv)
* is able to process 234936 words from the web2 dictionary without * Glenn Fowler (http://www.research.att.com/~gsf/)
* any collisions.
* *
* See: * In a subsequent ballot round:
* http://reality.sgi.com/chongo/src/fnv/fnv_hash.tar.gz *
* http://reality.sgi.com/chongo/src/fnv/h32.c * Landon Curt Noll (http://reality.sgi.com/chongo)
* http://reality.sgi.com/chongo/src/fnv/h64.c *
* 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.
* *
* given: * given:
* x the value to hash (must not be longer than 32 bits) * x the value to hash (must not be longer than 32 bits)
@@ -160,7 +163,7 @@ hashvalue(VALUE *vp, QCKHASH val)
case V_COM: case V_COM:
return fnv_chash(vp->v_com, val); return fnv_chash(vp->v_com, val);
case V_STR: case V_STR:
return fnv_strhash(vp->v_str->s_str, val); return fnv_STRhash(vp->v_str, val);
case V_NULL: case V_NULL:
return val; return val;
case V_OBJ: case V_OBJ:
@@ -404,6 +407,7 @@ config_hash(CONFIG *cfg, QCKHASH val)
value = (((value>>5) | (value<<27)) ^ (USB32)cfg->lib_debug); value = (((value>>5) | (value<<27)) ^ (USB32)cfg->lib_debug);
value = (((value>>5) | (value<<27)) ^ (USB32)cfg->calc_debug); value = (((value>>5) | (value<<27)) ^ (USB32)cfg->calc_debug);
value = (((value>>5) | (value<<27)) ^ (USB32)cfg->user_debug); value = (((value>>5) | (value<<27)) ^ (USB32)cfg->user_debug);
value = (((value>>5) | (value<<27)) ^ (USB32)cfg->verbose_quit);
/* /*
* hash the built up scalar * hash the built up scalar
@@ -431,7 +435,29 @@ config_hash(CONFIG *cfg, QCKHASH val)
/* /*
* fnv_strhash - Fowler/Noll/Vo 32 bit hash of a string * fnv_strhash - Fowler/Noll/Vo 32 bit hash of a null-terminated string
*
* given:
* ch the start of the string to hash
* val initial hash value
*
* returns:
* a 32 bit QCKHASH value
*/
static QCKHASH
fnv_strhash(char *ch, QCKHASH val)
{
/*
* hash each character in the string
*/
while (*ch) {
val = fnv(*ch++, val);
}
return val;
}
/*
* fnv_STRhash - Fowler/Noll/Vo 32 bit hash of a STRING
* *
* given: * given:
* str the string to hash * str the string to hash
@@ -441,13 +467,19 @@ config_hash(CONFIG *cfg, QCKHASH val)
* a 32 bit QCKHASH value * a 32 bit QCKHASH value
*/ */
static QCKHASH static QCKHASH
fnv_strhash(char *str, QCKHASH val) fnv_STRhash(STRING *str, QCKHASH val)
{ {
char *ch;
long n;
ch = str->s_str;
n = str->s_len;
/* /*
* hash each character in the string * hash each character in the string
*/ */
while (*str) { while (n-- > 0) {
val = fnv(*str++, val); val = fnv(*ch++, val);
} }
return val; return val;
} }
@@ -490,48 +522,36 @@ fnv_fullhash(FULL *v, LEN len, QCKHASH val)
static QCKHASH static QCKHASH
fnv_zhash(ZVALUE z, QCKHASH val) fnv_zhash(ZVALUE z, QCKHASH val)
{ {
int skip; /* HALFs to skip in the middle */ LEN n;
int i; HALF *hp;
#if BASEB == 16
FULL f;
#endif
/* /*
* hash the sign and length * hash the sign
*/ */
if (zisneg(z)) { val = fnv(z.sign, val + V_NUM);
val = fnv(-(z.len), val+V_NUM);
} else {
val = fnv(z.len, val+V_NUM);
}
/* n = z.len;
* if a ZVALUE is short enough, hash it all hp = z.v;
*/
if (z.len <= ZMOST+ZLEAST+ZMIDDLE) {
/* hash all HALFs of a short ZVALUE */
for (i=0; i < z.len; ++i) {
val = fnv(z.v[i], val);
}
/* #if BASEB == 16
* otherwise hash the ZLEAST significant HALFs followed by while (n > 1) {
* ZMIDDLE HALFs followed by the ZMOST significant HALFs. f = (FULL) *hp++;
*/ f |= (FULL) *hp++ << BASEB;
} else { val = fnv(f, val);
/* hash the ZLEAST significant HALFs */ n -= 2;
for (i=0; i < ZLEAST; ++i) {
val = fnv(z.v[i], val);
} }
if (n) {
/* hash ZMIDDLE HALFs in the middle */ val = fnv(*hp, val);
skip = (z.len-ZLEAST-ZMOST)/(ZMIDDLE + 1);
for (i=ZLEAST-1+skip; i < ZLEAST-1+skip*(ZMIDDLE+1); i+=skip) {
val = fnv(z.v[i], val);
}
/* hash the ZMOST significant HALFs */
for (i=z.len-1-ZMOST; i < z.len; ++i) {
val = fnv(z.v[i], val);
} }
#else
while (n-- > 0) {
val = fnv(*hp, val);
++hp;
} }
#endif
return val; return val;
} }

View File

@@ -33,18 +33,6 @@
*/ */
#if defined(__sgi)
# include "../longbits.h"
# if defined(HAVE_B64)
typedef USB64 k_sigset_t;
# else
typedef struct {
USB32 sigbits[2];
} k_sigset_t;
# endif
#endif
#include <sys/types.h> #include <sys/types.h>
#include <stdio.h> #include <stdio.h>
#include "../calc.h" #include "../calc.h"

View File

@@ -33,18 +33,6 @@
*/ */
#if defined(__sgi)
# include "../longbits.h"
# if defined(HAVE_B64)
typedef USB64 k_sigset_t;
# else
typedef struct {
USB32 sigbits[2];
} k_sigset_t;
# endif
#endif
#include <sys/types.h> #include <sys/types.h>
#include <stdio.h> #include <stdio.h>
#include "../calc.h" #include "../calc.h"

93
seed.c
View File

@@ -87,7 +87,51 @@ typedef struct s_hash64 hash64;
/* /*
* hash_buf - perform a 64 bit Fowler/Noll/Vo hash on a buffer * FNV-1 initial basis
*
* We start the hash at a non-zero value at the beginning so that
* hashing blocks of data with all 0 bits do not map onto the same
* 0 hash value. The virgin value that we use below is the hash value
* that we would get from following 32 ASCII characters:
*
* chongo <Landon Curt Noll> /\../\
*
* Note that the \'s above are not back-slashing escape characters.
* They are literal ASCII backslash 0x5c characters.
*
* The effect of this virgin initial value is the same as starting
* with 0 and pre-pending those 32 characters onto the data being
* hashed.
*
* Yes, even with this non-zero virgin value there is a set of data
* that will result in a zero hash value. Worse, appending any
* about of zero bytes will continue to produce a zero hash value.
* But that would happen with any initial value so long as the
* hash of the initial was the `inverse' of the virgin prefix string.
*
* But then again for any hash function, there exists sets of data
* which that the hash of every member is the same value. That is
* life with many to few mapping functions. All we do here is to
* prevent sets whose members consist of 0 or more bytes of 0's from
* being such an awkward set.
*
* And yes, someone can figure out what the magic 'inverse' of the
* 32 ASCII character are ... but this hash function is NOT intended
* to be a cryptographic hash function, just a fast and reasonably
* good hash function.
*/
#if defined(HAVE_B64)
# define FNV1_64_BASIS ((hash64)(0xcbf29ce484222325ULL))
#else
# define FNV1_64_BASIS_0 ((USB32)0x2325)
# define FNV1_64_BASIS_1 ((USB32)0x8422)
# define FNV1_64_BASIS_2 ((USB32)0x9ce4)
# define FNV1_64_BASIS_3 ((USB32)0xcbf2)
#endif
/*
* hash_buf - perform a Fowler/Noll/Vo-1 64 bit hash
* *
* input: * input:
* buf - start of buffer to hash * buf - start of buffer to hash
@@ -108,32 +152,33 @@ hash_buf(char *buf, unsigned len)
char *buf_end = buf+len; /* beyond end of hash area */ char *buf_end = buf+len; /* beyond end of hash area */
/* /*
* Fowler/Noll/Vo hash - hash each character in the string * FNV-1 - Fowler/Noll/Vo-1 64 bit hash
* *
* The basis of the hash algorithm was taken from an idea * The basis of this hash algorithm was taken from an idea sent
* sent by Email to the IEEE POSIX P1003.2 mailing list from * as reviewer comments to the IEEE POSIX P1003.2 committee by:
* Phong Vo (kpv@research.att.com) and Glenn Fowler
* (gsf@research.att.com).
* *
* See: * Phong Vo (http://www.research.att.com/info/kpv)
* http://reality.sgi.com/chongo/src/fnv/fnv_hash.tar.gz * Glenn Fowler (http://www.research.att.com/~gsf/)
* http://reality.sgi.com/chongo/src/fnv/h32.c
* http://reality.sgi.com/chongo/src/fnv/h64.c
* *
* for information on 32bit and 64bit Fowler/Noll/Vo hashes. * In a subsequent ballot round:
* *
* Landon Curt Noll (http://reality.sgi.com/chongo) later improved * Landon Curt Noll (http://reality.sgi.com/chongo)
* on their algorithm to come up with Fowler/Noll/Vo hash.
* *
* The 32 hash was able to process 234936 words from the web2 dictionary * improved on their algorithm. Some people tried this hash
* without any 32 bit collisions using a constant of * and found that it worked rather well. In an EMail message
* 16777619 = 0x1000193. * to Landon, they named it ``Fowler/Noll/Vo'' or the FNV hash.
* *
* The 64 bit hash uses 1099511628211 = 0x100000001b3 instead. * 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.
*/ */
#if defined(HAVE_B64) #if defined(HAVE_B64)
/* hash each octet of the buffer */ /* hash each octet of the buffer */
for (hval = (hash64)0ULL; buf < buf_end; ++buf) { for (hval = FNV1_64_BASIS; buf < buf_end; ++buf) {
/* multiply by 1099511628211ULL mod 2^64 using 64 bit longs */ /* multiply by 1099511628211ULL mod 2^64 using 64 bit longs */
hval *= (hash64)1099511628211ULL; hval *= (hash64)1099511628211ULL;
@@ -145,7 +190,11 @@ hash_buf(char *buf, unsigned len)
#else /* HAVE_B64 */ #else /* HAVE_B64 */
/* hash each octet of the buffer */ /* hash each octet of the buffer */
for (val[0]=val[1]=val[2]=val[3]=0; buf < buf_end; ++buf) { val[0] = FNV1_64_BASIS_0;
val[1] = FNV1_64_BASIS_1;
val[2] = FNV1_64_BASIS_2;
val[3] = FNV1_64_BASIS_3;
for (; buf < buf_end; ++buf) {
/* /*
* multiply by 1099511628211 mod 2^64 using 32 bit longs * multiply by 1099511628211 mod 2^64 using 32 bit longs
@@ -167,7 +216,7 @@ hash_buf(char *buf, unsigned len)
val[0] = tmp[0] & 0xffff; val[0] = tmp[0] & 0xffff;
tmp[2] += (tmp[1] >> 16); tmp[2] += (tmp[1] >> 16);
val[1] = tmp[1] & 0xffff; val[1] = tmp[1] & 0xffff;
val[3] += (tmp[2] >> 16); val[3] = tmp[3] + (tmp[2] >> 16);
val[2] = tmp[2] & 0xffff; val[2] = tmp[2] & 0xffff;
/* /*
* Doing a val[3] &= 0xffff; is not really needed since it simply * Doing a val[3] &= 0xffff; is not really needed since it simply
@@ -181,8 +230,8 @@ hash_buf(char *buf, unsigned len)
/* convert to hash64 */ /* convert to hash64 */
/* hval.w32[1] = 0xffff&(val[3]<<16)+val[2]; */ /* hval.w32[1] = 0xffff&(val[3]<<16)+val[2]; */
hval.w32[1] = val[3]<<16 + val[2]; hval.w32[1] = (val[3]<<16) + val[2];
hval.w32[0] = val[1]<<16 + val[0]; hval.w32[0] = (val[1]<<16) + val[0];
#endif /* HAVE_B64 */ #endif /* HAVE_B64 */

2
shs.c
View File

@@ -696,7 +696,7 @@ shs_print(HASH *state)
/* /*
* form the hash value * form the hash value
*/ */
if (conf->calc_debug > 0) { if (conf->calc_debug & CALCDBG_HASH_STATE) {
char buf[DEBUG_SIZE+1]; /* hash value buffer */ char buf[DEBUG_SIZE+1]; /* hash value buffer */
/* /*

2
shs1.c
View File

@@ -672,7 +672,7 @@ shs1_print(HASH *state)
/* /*
* form the hash value * form the hash value
*/ */
if (conf->calc_debug > 0) { if (conf->calc_debug & CALCDBG_HASH_STATE) {
char buf[DEBUG_SIZE+1]; /* hash value buffer */ char buf[DEBUG_SIZE+1]; /* hash value buffer */
/* /*

View File

@@ -1157,8 +1157,7 @@ addstring(char *str, long len)
if (stringconstavail <= 0) { if (stringconstavail <= 0) {
if (stringconsttable == NULL) { if (stringconsttable == NULL) {
initstrings(); initstrings();
} } else {
else {
sp = (STRING **) realloc((char *) stringconsttable, sp = (STRING **) realloc((char *) stringconsttable,
sizeof(STRING *) * (stringconstcount + STRCONSTALLOC)); sizeof(STRING *) * (stringconstcount + STRCONSTALLOC));
if (sp == NULL) { if (sp == NULL) {

13
token.c
View File

@@ -83,6 +83,7 @@ static struct keyword keywords[] = {
{"print", T_PRINT}, {"print", T_PRINT},
{"cd", T_CD}, {"cd", T_CD},
{"undefine", T_UNDEFINE}, {"undefine", T_UNDEFINE},
{"abort", T_ABORT},
{NULL, 0} {NULL, 0}
}; };
@@ -438,6 +439,18 @@ eatstring(int quotechar)
case '"': case '"':
case '\'': case '\'':
if (ch == quotechar) { if (ch == quotechar) {
for (;;) {
ch = nextchar();
if (ch != ' ' && ch != '\t' &&
(ch != '\n' ||
newlines))
break;
}
if (ch == '"' || ch == '\'') {
quotechar = ch;
continue;
}
reread();
done = TRUE; done = TRUE;
ch = '\0'; ch = '\0';
} }

View File

@@ -110,6 +110,7 @@
#define T_PRINT 124 /* print keyword */ #define T_PRINT 124 /* print keyword */
#define T_CD 125 /* change directory keyword */ #define T_CD 125 /* change directory keyword */
#define T_UNDEFINE 126 /* undefine keyword */ #define T_UNDEFINE 126 /* undefine keyword */
#define T_ABORT 127 /* abort operation */
#define iskeyword(n) ((n) > 100) /* TRUE if token is a keyword */ #define iskeyword(n) ((n) > 100) /* TRUE if token is a keyword */

View File

@@ -894,15 +894,17 @@ xorvalue(VALUE *v1, VALUE *v2, VALUE *vres)
if (v1->v_str->s_len) { if (v1->v_str->s_len) {
vres->v_str = stringcopy(v1->v_str); vres->v_str = stringcopy(v1->v_str);
*vres->v_str->s_str ^= *v2->v_octet; *vres->v_str->s_str ^= *v2->v_octet;
} else } else {
vres->v_str = charstring(*v2->v_octet); vres->v_str = charstring(*v2->v_octet);
}
return; return;
case (TWOVAL(V_OCTET, V_STR)): case (TWOVAL(V_OCTET, V_STR)):
if (v2->v_str->s_len) { if (v2->v_str->s_len) {
vres->v_str = stringcopy(v2->v_str); vres->v_str = stringcopy(v2->v_str);
*vres->v_str->s_str ^= *v1->v_octet; *vres->v_str->s_str ^= *v1->v_octet;
} else } else {
vres->v_str = charstring(*v1->v_octet); vres->v_str = charstring(*v1->v_octet);
}
return; return;
case (TWOVAL(V_OCTET, V_OCTET)): case (TWOVAL(V_OCTET, V_OCTET)):
vres->v_type = V_STR; vres->v_type = V_STR;

View File

@@ -12,7 +12,7 @@
#define MAJOR_VER 2 /* major version */ #define MAJOR_VER 2 /* major version */
#define MINOR_VER 11 /* minor version */ #define MINOR_VER 11 /* minor version */
#define MAJOR_PATCH 0 /* patch level or 0 if no patch */ #define MAJOR_PATCH 0 /* patch level or 0 if no patch */
#define MINOR_PATCH "8.1" /* test number or empty string if no patch */ #define MINOR_PATCH "8.9.1" /* test number or empty string if no patch */
/* /*
* calc version constants * calc version constants

33
zfunc.c
View File

@@ -269,8 +269,9 @@ zfib(ZVALUE z, ZVALUE *res)
fnm1 = fn; fnm1 = fn;
fn = fnp1; fn = fnp1;
zadd(fnm1, fn, &fnp1); zadd(fnm1, fn, &fnp1);
} else } else {
zsub(fnp1, fn, &fnm1); zsub(fnp1, fn, &fnm1);
}
i >>= (FULL)1; i >>= (FULL)1;
} }
zfree(fnm1); zfree(fnm1);
@@ -889,8 +890,7 @@ zgcd(ZVALUE z1, ZVALUE z2, ZVALUE *res)
*a = ~*a; *a = ~*a;
} }
} }
} } else { /* abs(a - b) case */
else { /* abs(a - b) case */
while (i && *a++ == *b++) i--; while (i && *a++ == *b++) i--;
q = n - i; q = n - i;
if (m == n) { /* a and b same length */ if (m == n) { /* a and b same length */
@@ -914,8 +914,7 @@ zgcd(ZVALUE z1, ZVALUE z2, ZVALUE *res)
f = -f & BASE1; f = -f & BASE1;
} }
} }
} } else { /* a has more digits than b */
else { /* a has more digits than b */
a = a0 + q; a = a0 + q;
b = b0 + q; b = b0 + q;
i = n - q; i = n - q;
@@ -1117,9 +1116,10 @@ zlog(ZVALUE z1, ZVALUE z2)
zfree(val); zfree(val);
val = temp; val = temp;
power += worth; power += worth;
} else } else {
zfree(temp); zfree(temp);
} }
}
if (zp != squares) if (zp != squares)
zfree(*zp); zfree(*zp);
} }
@@ -1170,10 +1170,11 @@ zlog10(ZVALUE z)
zfree(val); zfree(val);
val = temp; val = temp;
power += worth; power += worth;
} else } else {
zfree(temp); zfree(temp);
} }
} }
}
zfree(val); zfree(val);
return power; return power;
} }
@@ -1574,8 +1575,7 @@ zsqrt(ZVALUE z, ZVALUE *dest, long rnd)
x = ~x + !u; x = ~x + !u;
if (!(x & TOPHALF)) if (!(x & TOPHALF))
a[1] -= 1; a[1] -= 1;
} } else {
else {
f = *a - x * x; f = *a - x * x;
*a++ = (HALF)f; *a++ = (HALF)f;
u = -(HALF)(f >> BASEB); u = -(HALF)(f >> BASEB);
@@ -1623,9 +1623,9 @@ done: if (s == 0) {
} }
if (rnd & 16) { if (rnd & 16) {
if (s == 0) { if (s == 0) {
if (m != n) if (m != n) {
up = (m > n); up = (m > n);
else { } else {
i = n; i = n;
b = a0 + n; b = a0 + n;
a = A + n; a = A + n;
@@ -1633,13 +1633,12 @@ done: if (s == 0) {
i--; i--;
up = (i > 0 && *a > *b); up = (i > 0 && *a > *b);
} }
} } else {
else {
while (m > 1 && A[m - 1] == BASE1) while (m > 1 && A[m - 1] == BASE1)
m--; m--;
if (m != n) if (m != n) {
up = (m < n); up = (m < n);
else { } else {
i = n; i = n;
b = a0 + n; b = a0 + n;
a = A + n; a = A + n;
@@ -1660,9 +1659,9 @@ done: if (s == 0) {
a = a0; a = a0;
while (i-- && *a == BASE1) while (i-- && *a == BASE1)
*a++ = 0; *a++ = 0;
if (i >= 0) if (i >= 0) {
(*a)++; (*a)++;
else { } else {
n++; n++;
*a = 1; *a = 1;
} }

17
zmath.c
View File

@@ -687,8 +687,7 @@ zdiv(ZVALUE z1, ZVALUE z2, ZVALUE *quo, ZVALUE *rem, long rnd)
} }
s = *a + u; s = *a + u;
A[m] = (HALF) (~x + !s); A[m] = (HALF) (~x + !s);
} } else {
else {
while (i--) { while (i--) {
f = (FULL) *a - u - x * *b++; f = (FULL) *a - u - x * *b++;
*a++ = (HALF) f; *a++ = (HALF) f;
@@ -708,9 +707,9 @@ done: while (m > 0 && A[m - 1] == 0)
val = 0; val = 0;
if (a1[len - 1] == 0) if (a1[len - 1] == 0)
len--; len--;
if (len == 0) if (len == 0) {
*quo = _zero_; *quo = _zero_;
else { } else {
quo->len = len; quo->len = len;
quo->v = alloc(len); quo->v = alloc(len);
memcpy(quo->v, a1, len * sizeof(HALF)); memcpy(quo->v, a1, len * sizeof(HALF));
@@ -746,8 +745,7 @@ done: while (m > 0 && A[m - 1] == 0)
} }
else if (g >= BASE) else if (g >= BASE)
t = 1; t = 1;
} } else {
else {
while (--i > 0) { while (--i > 0) {
g = (FULL) *--a - (*--b >> 1 | f); g = (FULL) *--a - (*--b >> 1 | f);
if (g != 0) if (g != 0)
@@ -973,9 +971,9 @@ zequo(ZVALUE z1, ZVALUE z2, ZVALUE *res)
*a0++ = x; *a0++ = x;
p--; p--;
} }
if (k == 0) if (k == 0) {
*a0 = w * *a0; *a0 = w * *a0;
else { } else {
u = (HALF)(w * *a0) >> k; u = (HALF)(w * *a0) >> k;
x = (HALF)(((FULL) z1.v[z1.len - 1] << BASEB x = (HALF)(((FULL) z1.v[z1.len - 1] << BASEB
| z1.v[z1.len - 2]) | z1.v[z1.len - 2])
@@ -1890,8 +1888,9 @@ zshiftl(ZVALUE z, long n)
if (i > BASE1) { if (i > BASE1) {
mask = i >> BASEB; mask = i >> BASEB;
i &= BASE1; i &= BASE1;
} else } else {
mask = 0; mask = 0;
}
*h = (HALF) i; *h = (HALF) i;
++h; ++h;
} }

37
zmath.h
View File

@@ -144,6 +144,43 @@ typedef SB32 LEN; /* unit of length storage */
#endif /* LONG_BITS == 64 */ #endif /* LONG_BITS == 64 */
/*
* FNV-1 basis
*
* We start the hash at a non-zero value at the beginning so that
* hashing blocks of data with all 0 bits do not map onto the same
* 0 hash value. The virgin value that we use below is the hash value
* that we would get from following 32 ASCII characters:
*
* chongo <Landon Curt Noll> /\../\
*
* Note that the \'s above are not back-slashing escape characters.
* They are literal ASCII backslash 0x5c characters.
*
* The effect of this virgin initial value is the same as starting
* with 0 and pre-pending those 32 characters onto the data being
* hashed.
*
* Yes, even with this non-zero virgin value there is a set of data
* that will result in a zero hash value. Worse, appending any
* about of zero bytes will continue to produce a zero hash value.
* But that would happen with any initial value so long as the
* hash of the initial was the `inverse' of the virgin prefix string.
*
* But then again for any hash function, there exists sets of data
* which that the hash of every member is the same value. That is
* life with many to few mapping functions. All we do here is to
* prevent sets whose members consist of 0 or more bytes of 0's from
* being such an awkward set.
*
* And yes, someone can figure out what the magic 'inverse' of the
* 32 ASCII character are ... but this hash function is NOT intended
* to be a cryptographic hash function, just a fast and reasonably
* good hash function.
*/
#define FNV1_32_BASIS ((QCKHASH)(0x811c9dc5))
/* /*
* The largest power of 10 we will compute for our decimal conversion * The largest power of 10 we will compute for our decimal conversion
* internal constants is: 10^(2^TEN_MAX). * internal constants is: 10^(2^TEN_MAX).

3
zmod.c
View File

@@ -1746,8 +1746,7 @@ zredcsquare(REDC *rp, ZVALUE z1, ZVALUE *res)
carry.ivalue = (FULL) sival1.sihigh carry.ivalue = (FULL) sival1.sihigh
+ (FULL) sival2.sihigh; + (FULL) sival2.sihigh;
hd++; hd++;
} } else {
else {
muln = (HALF) (*hd * Ninv); muln = (HALF) (*hd * Ninv);
f = (muln * ((FULL) *h3++) + (FULL) *hd++) >> BASEB; f = (muln * ((FULL) *h3++) + (FULL) *hd++) >> BASEB;
j = i; j = i;