mirror of
https://github.com/lcn2/calc.git
synced 2025-08-16 01:03:29 +03:00
The config("triground") controls rounding for the following trigonometric and hyperbolic functions: sin, cos, tan, cot, sec, csc asin, acos, atan, acot, asec, acsc versin, coversin, vercos, covercos aversin, acoversin, avercos, acovercos haversin, hacoversin, havercos, hacovercos ahaversin, hacoversin, havercos, ahacovercos exsec, aexsec, excsc, aexcsc crd, acrd cas, cis sinh, cosh, tanh, coth, sech, csch asinh, acosh, atanh, acoth, asech, acsch In addition to taking a complex root (such as via the power function on a complex value), "triground" is used for: exp, polar For the above mentioned functions, the rounding mode used to round the result to the nearest epsilon value is controlled by, and defaults to: config("triground", 24) As with other config options, the call returns the previous mode, without a 2nd argument, returns the current mode without changing it: config("triground") Improved "SEE ALSO" for the hyperbolic function help files.
1059 lines
24 KiB
C
1059 lines
24 KiB
C
/*
|
|
* hash - one-way hash routines
|
|
*
|
|
* Copyright (C) 1999-2007,2021-2023 Landon Curt Noll
|
|
*
|
|
* Calc is open software; you can redistribute it and/or modify it under
|
|
* the terms of the version 2.1 of the GNU Lesser General Public License
|
|
* as published by the Free Software Foundation.
|
|
*
|
|
* Calc is distributed in the hope that it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
|
|
* Public License for more details.
|
|
*
|
|
* A copy of version 2.1 of the GNU Lesser General Public License is
|
|
* distributed with calc under the filename COPYING-LGPL. You should have
|
|
* received a copy with calc; if not, write to Free Software Foundation, Inc.
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*
|
|
* Under source code control: 1995/11/23 05:13:11
|
|
* File existed as early as: 1995
|
|
*
|
|
* chongo <was here> /\oo/\ http://www.isthe.com/chongo/
|
|
* Share and enjoy! :-) http://www.isthe.com/chongo/tech/comp/calc/
|
|
*/
|
|
|
|
|
|
#include <stdio.h>
|
|
#include "have_string.h"
|
|
#ifdef HAVE_STRING_H
|
|
# include <string.h>
|
|
#endif
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include "calc.h"
|
|
#include "alloc.h"
|
|
#include "value.h"
|
|
#include "zrand.h"
|
|
#include "zrandom.h"
|
|
#include "hash.h"
|
|
|
|
|
|
#include "errtbl.h"
|
|
#include "banned.h" /* include after system header <> includes */
|
|
|
|
|
|
/*
|
|
* external hash_setup functions
|
|
*/
|
|
E_FUNC void shs_init_state(HASH*);
|
|
E_FUNC void sha1_init_state(HASH*);
|
|
E_FUNC void MD5_init_state(HASH*);
|
|
|
|
|
|
/*
|
|
* hash_long can deal with bool's, int's, FLAGS's and LEN's
|
|
*/
|
|
#define hash_bool(type, val, state) (hash_long((type), (long)(val), (state)))
|
|
#define hash_int(type, val, state) (hash_long((type), (long)(val), (state)))
|
|
#define hash_flag(type, val, state) (hash_long((type), (long)(val), (state)))
|
|
#define hash_len(type, val, state) (hash_long((type), (long)(val), (state)))
|
|
|
|
|
|
/*
|
|
* hash_setup - setup the hash state for a given hash
|
|
*/
|
|
STATIC struct hash_setup {
|
|
int type; /* hash type (see XYZ_HASH_TYPE below) */
|
|
void (*init_state)(HASH*); /* initialize a hash state */
|
|
} htbl[] = {
|
|
{ SHA1_HASH_TYPE, sha1_init_state }, /* SHA-1 / SHA-1 */
|
|
{ -1, NULL } /* must be last */
|
|
};
|
|
|
|
|
|
/*
|
|
* hash_init - initialize a hash state
|
|
*
|
|
* given:
|
|
* type - hash type (see hash.h)
|
|
* state - the state to initialize, or NULL to malloc it
|
|
*
|
|
* returns:
|
|
* initialized state
|
|
*/
|
|
HASH *
|
|
hash_init(int type, HASH *state)
|
|
{
|
|
int i;
|
|
|
|
/*
|
|
* malloc if needed
|
|
*/
|
|
if (state == NULL) {
|
|
state = (HASH *)malloc(sizeof(HASH));
|
|
if (state == NULL) {
|
|
math_error("hash_init: cannot malloc HASH");
|
|
not_reached();
|
|
}
|
|
}
|
|
|
|
/*
|
|
* clear hash value
|
|
*/
|
|
memset((void*)state, 0, sizeof(HASH));
|
|
state->bytes = true;
|
|
|
|
/*
|
|
* search for the hash_setup function
|
|
*/
|
|
for (i=0; htbl[i].init_state != NULL; ++i) {
|
|
|
|
/* if we found the state that we were looking for */
|
|
if (type == htbl[i].type) {
|
|
|
|
/* initialize state and return */
|
|
(htbl[i].init_state)(state);
|
|
|
|
/* firewall - MAX_CHUNKSIZE must be >= chunksize */
|
|
if (state->chunksize > MAX_CHUNKSIZE) {
|
|
math_error(
|
|
"internal error: MAX_CHUNKSIZE is too small");
|
|
not_reached();
|
|
}
|
|
return state;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* no such hash state
|
|
*/
|
|
math_error("internal error: hash type not found in htbl[]");
|
|
return NULL;
|
|
}
|
|
|
|
|
|
/*
|
|
* hash_free - free the hash state
|
|
*/
|
|
void
|
|
hash_free(HASH *state)
|
|
{
|
|
/*
|
|
* do nothing if state is NULL
|
|
*/
|
|
if (state == NULL) {
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* free main state and return
|
|
*/
|
|
free(state);
|
|
return;
|
|
}
|
|
|
|
|
|
/*
|
|
* hash_copy - copy a hash state
|
|
*
|
|
* given:
|
|
* state - the state to copy
|
|
*
|
|
* returns:
|
|
* pointer to copy of state
|
|
*/
|
|
HASH *
|
|
hash_copy(HASH *state)
|
|
{
|
|
HASH *hnew; /* copy of state */
|
|
|
|
/*
|
|
* malloc new state
|
|
*/
|
|
hnew = (HASH *)malloc(sizeof(HASH));
|
|
if (hnew == NULL) {
|
|
math_error("hash_init: cannot malloc HASH");
|
|
not_reached();
|
|
}
|
|
|
|
/*
|
|
* duplicate state
|
|
*/
|
|
memcpy((void *)hnew, (void *)state, sizeof(HASH));
|
|
return hnew;
|
|
}
|
|
|
|
|
|
/*
|
|
* hash_cmp - compare hash values
|
|
*
|
|
* given:
|
|
* a first hash state
|
|
* b second hash state
|
|
*
|
|
* returns:
|
|
* true => hash states are different
|
|
* false => hash states are the same
|
|
*/
|
|
int
|
|
hash_cmp(HASH *a, HASH *b)
|
|
{
|
|
/*
|
|
* firewall and quick check
|
|
*/
|
|
if (a == b) {
|
|
/* pointers to the same object */
|
|
return false;
|
|
}
|
|
if (a == NULL || b == NULL) {
|
|
/* one pointer is NULL, so they differ */
|
|
return true;
|
|
}
|
|
if (a->cmp == NULL || b->cmp == NULL) {
|
|
/* one cmp function is NULL, so they differ */
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
* compare hash types
|
|
*/
|
|
if (a->hashtype != b->hashtype) {
|
|
/* different hash types are different */
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
* perform the hash specific comparison
|
|
*/
|
|
return ((a->cmp)(a,b));
|
|
}
|
|
|
|
|
|
/*
|
|
* hash_print - print the name and value of a hash
|
|
*
|
|
* given:
|
|
* state the hash state to print name and value of
|
|
*/
|
|
void
|
|
hash_print(HASH *state)
|
|
{
|
|
/* print the hash */
|
|
(state->print)(state);
|
|
return;
|
|
}
|
|
|
|
|
|
/*
|
|
* hash_final - finalize the state of a hash and return a ZVALUE
|
|
*
|
|
* given:
|
|
* state the hash state to finalize
|
|
*
|
|
* returns:
|
|
* hash state as a ZVALUE
|
|
*/
|
|
ZVALUE
|
|
hash_final(HASH *state)
|
|
{
|
|
/* return the finalized the hash value */
|
|
return (state->final)(state);
|
|
}
|
|
|
|
|
|
/*
|
|
* hash_long - note a long value
|
|
*
|
|
* given:
|
|
* type - hash type (see hash.h)
|
|
* longval - a long value
|
|
* state - the state to hash
|
|
*
|
|
* returns:
|
|
* the new state
|
|
*
|
|
* This function will hash a long value as if it were a 64 bit value.
|
|
* The input is a long. If a long is smaller than 64 bits, we will
|
|
* hash a final 32 bits of zeros.
|
|
*
|
|
* This function is OK to hash bool's, unsigned long's, unsigned int's
|
|
* signed int's as well as FLAG's and LEN's.
|
|
*/
|
|
HASH *
|
|
hash_long(int type, long longval, HASH *state)
|
|
{
|
|
long lval[64/LONG_BITS]; /* 64 bits of longs */
|
|
|
|
/*
|
|
* initialize if state is NULL
|
|
*/
|
|
if (state == NULL) {
|
|
state = hash_init(type, NULL);
|
|
}
|
|
|
|
/*
|
|
* setup for the hash_long
|
|
*/
|
|
(state->chkpt)(state);
|
|
state->bytes = false; /* data to be read as words */
|
|
|
|
/*
|
|
* catch the zero numeric value special case
|
|
*/
|
|
if (longval == 0) {
|
|
/* note a zero numeric value and return */
|
|
(state->note)(HASH_ZERO(state->base), state);
|
|
return state;
|
|
}
|
|
|
|
/*
|
|
* prep for a long value hash
|
|
*/
|
|
(state->note)(state->base, state);
|
|
|
|
/*
|
|
* hash as if we have a 64 bit value
|
|
*/
|
|
memset((char *)lval, 0, sizeof(lval));
|
|
lval[0] = longval;
|
|
(state->update)(state, (USB8 *)lval, sizeof(lval));
|
|
|
|
/*
|
|
* all done
|
|
*/
|
|
return state;
|
|
}
|
|
|
|
|
|
/*
|
|
* hash_zvalue - hash a ZVALUE
|
|
*
|
|
* given:
|
|
* type - hash type (see hash.h)
|
|
* zval - the ZVALUE
|
|
* state - the state to hash or NULL
|
|
*
|
|
* returns:
|
|
* the new state
|
|
*/
|
|
HASH *
|
|
hash_zvalue(int type, ZVALUE zval, HASH *state)
|
|
{
|
|
|
|
#if CALC_BYTE_ORDER == BIG_ENDIAN && BASEB == 16
|
|
int full_lim; /* HALFs in whole chunks in zval */
|
|
int chunkhalf; /* size of half buffer in HALFs */
|
|
int i;
|
|
int j;
|
|
#endif
|
|
#if BASEB == 16
|
|
HALF half[MAX_CHUNKSIZE]; /* For endian reversal */
|
|
#endif
|
|
|
|
/*
|
|
* initialize if state is NULL
|
|
*/
|
|
if (state == NULL) {
|
|
state = hash_init(type, NULL);
|
|
}
|
|
|
|
/*
|
|
* setup for the ZVALUE hash
|
|
*/
|
|
(state->chkpt)(state);
|
|
state->bytes = false; /* data to be read as words */
|
|
|
|
/*
|
|
* catch the zero numeric value special case
|
|
*/
|
|
if (ziszero(zval)) {
|
|
/* note a zero numeric value and return */
|
|
(state->note)(HASH_ZERO(state->base), state);
|
|
return state;
|
|
}
|
|
|
|
/*
|
|
* prep for a ZVALUE hash
|
|
*/
|
|
(state->note)(HASH_ZVALUE(state->base), state);
|
|
/* note if we have a negative value */
|
|
if (zisneg(zval)) {
|
|
(state->note)(HASH_NEG(state->base), state);
|
|
}
|
|
|
|
#if CALC_BYTE_ORDER == BIG_ENDIAN && BASEB == 16
|
|
|
|
/*
|
|
* hash full chunks
|
|
*
|
|
* We need to convert the array of HALFs into canonical architectural
|
|
* independent form -- 32 bit arrays. Because we have 16 bit values
|
|
* in Big Endian form, we need to swap 16 bit values so that they
|
|
* appear as 32 bit Big Endian values.
|
|
*/
|
|
chunkhalf = state->chunksize/sizeof(HALF);
|
|
full_lim = (zval.len / chunkhalf) * chunkhalf;
|
|
for (i=0; i < full_lim; i += chunkhalf) {
|
|
/* HALF swap copy a chunk into a data buffer */
|
|
for (j=0; j < chunkhalf; j += 2) {
|
|
half[j] = zval.v[i+j+1];
|
|
half[j+1] = zval.v[i+j];
|
|
}
|
|
(state->update)(state, (USB8*) half, state->chunksize);
|
|
}
|
|
|
|
/*
|
|
* hash the final partial chunk (if any)
|
|
*
|
|
* We need to convert the array of HALFs into canonical architectural
|
|
* independent form -- 32 bit arrays. Because we have 16 bit values
|
|
* in Big Endian form, we need to swap 16 bit values so that they
|
|
* appear as 32 bit Big Endian values.
|
|
*/
|
|
if (zval.len > full_lim) {
|
|
for (j=0; j < zval.len-full_lim-1; j += 2) {
|
|
half[j] = zval.v[full_lim+j+1];
|
|
half[j+1] = zval.v[full_lim+j];
|
|
}
|
|
if (j < zval.len-full_lim) {
|
|
half[j] = (HALF)0;
|
|
half[j+1] = zval.v[zval.len-1];
|
|
--full_lim;
|
|
}
|
|
(state->update)(state, (USB8 *) half,
|
|
(zval.len-full_lim)*sizeof(HALF));
|
|
}
|
|
|
|
#else
|
|
|
|
/*
|
|
* hash the array of HALFs
|
|
*
|
|
* The array of HALFs is equivalent to the canonical architectural
|
|
* independent form. We either have 32 bit HALFs (in which case
|
|
* we do not case the byte order) or we have 16 bit HALFs in Little
|
|
* Endian order (which happens to be laid out in the same order as
|
|
* 32 bit values).
|
|
*/
|
|
(state->update)(state, (USB8 *)zval.v, zval.len*sizeof(HALF));
|
|
|
|
#if BASEB == 16
|
|
if (zval.len & 1) { /* padding to complete word */
|
|
half[0] = 0;
|
|
(state->update)(state, (USB8 *) half, 2);
|
|
}
|
|
#endif
|
|
|
|
#endif
|
|
|
|
/*
|
|
* all done
|
|
*/
|
|
return state;
|
|
}
|
|
|
|
|
|
/*
|
|
* hash_number - hash a NUMBER
|
|
*
|
|
* given:
|
|
* type - hash type (see hash.h)
|
|
* n - the NUMBER
|
|
* state - the state to hash or NULL
|
|
*
|
|
* returns:
|
|
* the new state
|
|
*/
|
|
HASH *
|
|
hash_number(int type, void *n, HASH *state)
|
|
{
|
|
NUMBER *number = (NUMBER *)n; /* n as a NUMBER pointer */
|
|
bool sign; /* sign of the denominator */
|
|
|
|
/*
|
|
* initialize if state is NULL
|
|
*/
|
|
if (state == NULL) {
|
|
state = hash_init(type, NULL);
|
|
}
|
|
|
|
/*
|
|
* setup for the NUMBER hash
|
|
*/
|
|
(state->chkpt)(state);
|
|
state->bytes = false;
|
|
|
|
/*
|
|
* process the numerator
|
|
*/
|
|
state = hash_zvalue(type, number->num, state);
|
|
|
|
/*
|
|
* if the NUMBER is not an integer, process the denominator
|
|
*/
|
|
if (qisfrac(number)) {
|
|
|
|
/* note the division */
|
|
(state->note)(HASH_DIV(state->base), state);
|
|
|
|
/* hash denominator as positive -- just in case */
|
|
sign = number->den.sign;
|
|
number->den.sign = 0;
|
|
|
|
/* hash the denominator */
|
|
state = hash_zvalue(type, number->den, state);
|
|
|
|
/* restore the sign */
|
|
number->den.sign = sign;
|
|
}
|
|
|
|
/*
|
|
* all done
|
|
*/
|
|
return state;
|
|
}
|
|
|
|
|
|
/*
|
|
* hash_complex - hash a COMPLEX
|
|
*
|
|
* given:
|
|
* type - hash type (see hash.h)
|
|
* c - the COMPLEX
|
|
* state - the state to hash or NULL
|
|
*
|
|
* returns:
|
|
* the new state
|
|
*/
|
|
HASH *
|
|
hash_complex(int type, void *c, HASH *state)
|
|
{
|
|
COMPLEX *complex = (COMPLEX *)c; /* c as a COMPLEX pointer */
|
|
|
|
/*
|
|
* initialize if state is NULL
|
|
*/
|
|
if (state == NULL) {
|
|
state = hash_init(type, NULL);
|
|
}
|
|
|
|
/*
|
|
* setup for the COMPLEX hash
|
|
*/
|
|
(state->chkpt)(state);
|
|
state->bytes = false;
|
|
|
|
/*
|
|
* catch the zero special case
|
|
*/
|
|
if (ciszero(complex)) {
|
|
/* note a zero numeric value and return */
|
|
(state->note)(HASH_ZERO(state->base), state);
|
|
return state;
|
|
}
|
|
|
|
/*
|
|
* process the real value if not pure imaginary
|
|
*
|
|
* We will ignore the real part if the value is of the form 0+xi.
|
|
*/
|
|
if (!qiszero(complex->real)) {
|
|
state = hash_number(type, complex->real, state);
|
|
}
|
|
|
|
/*
|
|
* if the NUMBER is not real, process the imaginary value
|
|
*
|
|
* We will ignore the imaginary part of the value is of the form x+0i.
|
|
*/
|
|
if (!cisreal(complex)) {
|
|
|
|
/* note the sqrt(-1) */
|
|
(state->note)(HASH_COMPLEX(state->base), state);
|
|
|
|
/* hash the imaginary value */
|
|
state = hash_number(type, complex->imag, state);
|
|
}
|
|
|
|
/*
|
|
* all done
|
|
*/
|
|
return state;
|
|
}
|
|
|
|
|
|
/*
|
|
* hash_str - hash a null-terminated string
|
|
*
|
|
* given:
|
|
* type - hash type (see hash.h)
|
|
* str - the string
|
|
* state - the state to hash or NULL
|
|
*
|
|
* returns:
|
|
* the new state
|
|
*/
|
|
HASH *
|
|
hash_str(int type, char *str, HASH *state)
|
|
{
|
|
size_t len; /* string length */
|
|
|
|
/*
|
|
* initialize if state is NULL
|
|
*/
|
|
if (state == NULL) {
|
|
state = hash_init(type, NULL);
|
|
}
|
|
|
|
/*
|
|
* setup for the string hash
|
|
*/
|
|
if (!state->bytes) {
|
|
(state->chkpt)(state);
|
|
state->bytes = true;
|
|
}
|
|
|
|
len = strlen(str);
|
|
|
|
/*
|
|
* hash the string
|
|
*/
|
|
(state->update)(state, (USB8*)str, len);
|
|
|
|
/*
|
|
* all done
|
|
*/
|
|
return state;
|
|
}
|
|
|
|
|
|
/*
|
|
* hash_STR - hash a STRING
|
|
*
|
|
* given:
|
|
* type - hash type (see hash.h)
|
|
* str - the STRING
|
|
* state - the state to hash or NULL
|
|
*
|
|
* returns:
|
|
* the new state
|
|
*/
|
|
HASH *
|
|
hash_STR(int type, STRING *str, HASH *state)
|
|
{
|
|
/*
|
|
* initialize if state is NULL
|
|
*/
|
|
if (state == NULL) {
|
|
state = hash_init(type, NULL);
|
|
}
|
|
|
|
/*
|
|
* setup for the string hash
|
|
*/
|
|
if (!state->bytes) {
|
|
(state->chkpt)(state);
|
|
state->bytes = true;
|
|
}
|
|
|
|
/*
|
|
* hash the string
|
|
*/
|
|
(state->update)(state, (USB8*) str->s_str, (USB32) str->s_len);
|
|
|
|
/*
|
|
* all done
|
|
*/
|
|
return state;
|
|
}
|
|
|
|
|
|
/*
|
|
* hash_usb8 - hash an array of USB8s
|
|
*
|
|
* given:
|
|
* type - hash type (see hash.h)
|
|
* byte - pointer to an array of USB8s
|
|
* len - number of USB8s to hash
|
|
* state - the state to hash or NULL
|
|
*
|
|
* returns:
|
|
* the new state
|
|
*/
|
|
HASH *
|
|
hash_usb8(int type, USB8 *byte, int len, HASH *state)
|
|
{
|
|
/*
|
|
* initialize if state is NULL
|
|
*/
|
|
if (state == NULL) {
|
|
state = hash_init(type, NULL);
|
|
}
|
|
|
|
/*
|
|
* setup for the string hash
|
|
*/
|
|
if (!state->bytes) {
|
|
(state->chkpt)(state);
|
|
state->bytes = true;
|
|
}
|
|
|
|
/*
|
|
* hash the array of octets
|
|
*/
|
|
(state->update)(state, byte, (USB32)len);
|
|
|
|
/*
|
|
* all done
|
|
*/
|
|
return state;
|
|
}
|
|
|
|
|
|
/*
|
|
* hash_value - hash a value
|
|
*
|
|
* given:
|
|
* type - hash type (see hash.h)
|
|
* v - the value
|
|
* state - the state to hash or NULL
|
|
*
|
|
* returns:
|
|
* the new state
|
|
*/
|
|
HASH *
|
|
hash_value(int type, void *v, HASH *state)
|
|
{
|
|
LISTELEM *ep; /* list element pointer */
|
|
ASSOCELEM **assochead; /* association chain head */
|
|
ASSOCELEM *aep; /* current association value */
|
|
ASSOCELEM *nextaep; /* next association value */
|
|
VALUE *value = (VALUE *)v; /* v cast to a VALUE */
|
|
VALUE *vp; /* pointer to next OBJ table value */
|
|
ZVALUE fileval; /* size, position, dev, inode of a file */
|
|
int i;
|
|
|
|
/*
|
|
* initialize if state is NULL
|
|
*/
|
|
if (state == NULL) {
|
|
state = hash_init(type, NULL);
|
|
}
|
|
|
|
/*
|
|
* process the value type
|
|
*/
|
|
switch (value->v_type) {
|
|
case V_NULL:
|
|
(state->chkpt)(state);
|
|
state->bytes = true;
|
|
break;
|
|
|
|
case V_INT:
|
|
/* setup for the this value type */
|
|
(state->chkpt)(state);
|
|
(state->type)(value->v_type, state);
|
|
|
|
/* hash as if we have a 64 bit value */
|
|
state = hash_int(type, value->v_int, state);
|
|
break;
|
|
|
|
case V_NUM:
|
|
/* hash this type */
|
|
state = hash_number(type, value->v_num, state);
|
|
break;
|
|
|
|
case V_COM:
|
|
/* setup for the this value type */
|
|
(state->chkpt)(state);
|
|
(state->type)(value->v_type, state);
|
|
|
|
/* hash this type */
|
|
state = hash_complex(type, value->v_com, state);
|
|
break;
|
|
|
|
case V_ADDR:
|
|
/* there is nothing to setup, simply hash what we point at */
|
|
state = hash_value(type, value->v_addr, state);
|
|
break;
|
|
|
|
case V_STR:
|
|
/* strings have no setup */
|
|
|
|
/* hash this type */
|
|
state = hash_STR(type, value->v_str, state);
|
|
break;
|
|
|
|
case V_MAT:
|
|
/* setup for the this value type */
|
|
(state->chkpt)(state);
|
|
(state->type)(value->v_type, state);
|
|
state->bytes = true;
|
|
|
|
/* hash all the elements of the matrix */
|
|
for (i=0; i < value->v_mat->m_size; ++i) {
|
|
|
|
/* hash the next matrix value */
|
|
state = hash_value(type,
|
|
value->v_mat->m_table+i, state);
|
|
state->bytes = false; /* as if reading words */
|
|
}
|
|
break;
|
|
|
|
case V_LIST:
|
|
/* setup for the this value type */
|
|
(state->chkpt)(state);
|
|
(state->type)(value->v_type, state);
|
|
|
|
/* hash all the elements of the list */
|
|
for (i=0, ep = value->v_list->l_first;
|
|
ep != NULL && i < value->v_list->l_count;
|
|
++i, ep = ep->e_next) {
|
|
|
|
/* hash the next list value */
|
|
state = hash_value(type, &ep->e_value, state);
|
|
state->bytes = false; /* as if reading words */
|
|
}
|
|
break;
|
|
|
|
case V_ASSOC:
|
|
/* setup for the this value type */
|
|
(state->chkpt)(state);
|
|
(state->type)(value->v_type, state);
|
|
state->bytes = true;
|
|
|
|
/* hash the association */
|
|
assochead = value->v_assoc->a_table;
|
|
for (i = 0; i < value->v_assoc->a_size; i++) {
|
|
nextaep = *assochead;
|
|
while (nextaep) {
|
|
aep = nextaep;
|
|
nextaep = aep->e_next;
|
|
|
|
/* hash the next association value */
|
|
state = hash_value(type, &aep->e_value, state);
|
|
state->bytes = false; /* as if reading words */
|
|
}
|
|
assochead++;
|
|
}
|
|
break;
|
|
|
|
case V_OBJ:
|
|
/* setup for the this value type */
|
|
(state->chkpt)(state);
|
|
(state->type)(value->v_type, state);
|
|
state->bytes = true; /* reading bytes */
|
|
|
|
/* hash the object name and then the element values */
|
|
|
|
state = hash_str(type, objtypename(
|
|
value->v_obj->o_actions->oa_index), state);
|
|
(state->chkpt)(state);
|
|
|
|
for (i=value->v_obj->o_actions->oa_count,
|
|
vp=value->v_obj->o_table;
|
|
i-- > 0;
|
|
vp++) {
|
|
|
|
/* hash the next object value */
|
|
state = hash_value(type, vp, state);
|
|
state->bytes = false; /* as if reading words */
|
|
}
|
|
break;
|
|
|
|
case V_FILE:
|
|
/* setup for the this value type */
|
|
(state->chkpt)(state);
|
|
(state->type)(value->v_type, state);
|
|
|
|
/* hash file length if possible */
|
|
if (getsize(value->v_file, &fileval) == 0) {
|
|
state = hash_zvalue(type, fileval, state);
|
|
zfree(fileval);
|
|
} else {
|
|
/* hash -1 for invalid length */
|
|
state = hash_long(type, (long)-1, state);
|
|
}
|
|
/* hash the file position if possible */
|
|
if (getloc(value->v_file, &fileval) == 0) {
|
|
state = hash_zvalue(type, fileval, state);
|
|
zfree(fileval);
|
|
} else {
|
|
/* hash -1 for invalid location */
|
|
state = hash_long(type, (long)-1, state);
|
|
}
|
|
/* hash the file device if possible */
|
|
if (get_device(value->v_file, &fileval) == 0) {
|
|
state = hash_zvalue(type, fileval, state);
|
|
zfree(fileval);
|
|
} else {
|
|
/* hash -1 for invalid device */
|
|
state = hash_long(type, (long)-1, state);
|
|
}
|
|
/* hash the file inode if possible */
|
|
if (get_inode(value->v_file, &fileval) == 0) {
|
|
state = hash_zvalue(type, fileval, state);
|
|
zfree(fileval);
|
|
} else {
|
|
/* hash -1 for invalid inode */
|
|
state = hash_long(type, (long)-1, state);
|
|
}
|
|
break;
|
|
|
|
case V_RAND:
|
|
/* setup for the this value type */
|
|
(state->chkpt)(state);
|
|
(state->type)(value->v_type, state);
|
|
|
|
/* hash the RAND state */
|
|
state = hash_int(type, value->v_rand->seeded, state);
|
|
state = hash_int(type, value->v_rand->bits, state);
|
|
(state->update)(state,
|
|
(USB8 *)value->v_rand->buffer, SLEN*FULL_BITS/8);
|
|
state = hash_int(type, value->v_rand->j, state);
|
|
state = hash_int(type, value->v_rand->k, state);
|
|
state = hash_int(type, value->v_rand->need_to_skip, state);
|
|
(state->update)(state,
|
|
(USB8 *)value->v_rand->slot, SCNT*FULL_BITS/8);
|
|
(state->update)(state,
|
|
(USB8*)value->v_rand->shuf, SHUFLEN*FULL_BITS/8);
|
|
state->bytes = false; /* as if reading words */
|
|
break;
|
|
|
|
case V_RANDOM:
|
|
/* setup for the this value type */
|
|
(state->chkpt)(state);
|
|
(state->type)(value->v_type, state);
|
|
|
|
/* hash the RANDOM state */
|
|
state = hash_int(type, value->v_random->seeded, state);
|
|
state = hash_int(type, value->v_random->bits, state);
|
|
(state->update)(state,
|
|
(USB8 *)&(value->v_random->buffer), BASEB/8);
|
|
state = hash_zvalue(type, value->v_random->r, state);
|
|
state = hash_zvalue(type, value->v_random->n, state);
|
|
state->bytes = false; /* as if reading words */
|
|
break;
|
|
|
|
case V_CONFIG:
|
|
/* setup for the this value type */
|
|
(state->chkpt)(state);
|
|
(state->type)(value->v_type, state);
|
|
|
|
/* hash the CONFIG state */
|
|
state = hash_int(type, value->v_config->outmode, state);
|
|
state = hash_int(type, value->v_config->outmode2, state);
|
|
state = hash_long(type,(long)value->v_config->outdigits, state);
|
|
state = hash_number(type, value->v_config->epsilon, state);
|
|
state = hash_long(type,
|
|
(long)value->v_config->epsilonprec, state);
|
|
state = hash_flag(type, value->v_config->traceflags, state);
|
|
state = hash_long(type, (long)value->v_config->maxprint, state);
|
|
state = hash_len(type, value->v_config->mul2, state);
|
|
state = hash_len(type, value->v_config->sq2, state);
|
|
state = hash_len(type, value->v_config->pow2, state);
|
|
state = hash_len(type, value->v_config->redc2, state);
|
|
state = hash_bool(type, value->v_config->tilde_ok, state);
|
|
state = hash_bool(type, value->v_config->tilde_space, state);
|
|
state = hash_bool(type, value->v_config->tab_ok, state);
|
|
state = hash_long(type, (long)value->v_config->quomod, state);
|
|
state = hash_long(type, (long)value->v_config->quo, state);
|
|
state = hash_long(type, (long)value->v_config->mod, state);
|
|
state = hash_long(type, (long)value->v_config->sqrt, state);
|
|
state = hash_long(type, (long)value->v_config->appr, state);
|
|
state = hash_long(type, (long)value->v_config->cfappr, state);
|
|
state = hash_long(type, (long)value->v_config->cfsim, state);
|
|
state = hash_long(type, (long)value->v_config->outround, state);
|
|
state = hash_long(type, (long)value->v_config->round, state);
|
|
state = hash_long(type, (long)value->v_config->triground, state);
|
|
state = hash_bool(type, value->v_config->leadzero, state);
|
|
state = hash_bool(type, value->v_config->fullzero, state);
|
|
state = hash_long(type,
|
|
(long)value->v_config->maxscancount, state);
|
|
state = hash_str(type, value->v_config->prompt1, state);
|
|
state->bytes = false; /* as if just read words */
|
|
state = hash_str(type, value->v_config->prompt2, state);
|
|
state->bytes = false; /* as if just read words */
|
|
state = hash_int(type, value->v_config->blkmaxprint, state);
|
|
state = hash_bool(type, value->v_config->blkverbose, state);
|
|
state = hash_int(type, value->v_config->blkbase, state);
|
|
state = hash_int(type, value->v_config->blkfmt, state);
|
|
state = hash_long(type,
|
|
(long)value->v_config->resource_debug, state);
|
|
state = hash_long(type,
|
|
(long)value->v_config->calc_debug, state);
|
|
state = hash_long(type,
|
|
(long)value->v_config->user_debug, state);
|
|
state = hash_bool(type, value->v_config->verbose_quit, state);
|
|
state = hash_int(type, value->v_config->ctrl_d, state);
|
|
state = hash_str(type, value->v_config->program, state);
|
|
state = hash_str(type, value->v_config->base_name, state);
|
|
state = hash_bool(type, value->v_config->windows, state);
|
|
state = hash_bool(type, value->v_config->cygwin, state);
|
|
state = hash_bool(type, value->v_config->compile_custom, state);
|
|
if (value->v_config->allow_custom != NULL &&
|
|
*(value->v_config->allow_custom)) {
|
|
state = hash_bool(type, true, state);
|
|
} else {
|
|
state = hash_bool(type, false, state);
|
|
}
|
|
state = hash_str(type, value->v_config->version, state);
|
|
state = hash_int(type, value->v_config->baseb, state);
|
|
state = hash_bool(type, value->v_config->redecl_warn, state);
|
|
state = hash_bool(type, value->v_config->dupvar_warn, state);
|
|
state = hash_bool(type, value->v_config->fraction_space, state);
|
|
break;
|
|
|
|
case V_HASH:
|
|
/* setup for the this value type */
|
|
(state->chkpt)(state);
|
|
(state->type)(value->v_type, state);
|
|
|
|
/* hash the HASH state */
|
|
state = hash_int(type, value->v_hash->type, state);
|
|
state = hash_bool(type, value->v_hash->bytes,state);
|
|
state = hash_int(type, value->v_hash->base, state);
|
|
state = hash_int(type, value->v_hash->chunksize, state);
|
|
state = hash_int(type, value->v_hash->unionsize, state);
|
|
(state->update)(state,
|
|
value->v_hash->h_union.data, state->unionsize);
|
|
state->bytes = false; /* as if reading words */
|
|
break;
|
|
|
|
case V_BLOCK:
|
|
/* there is no setup for a BLOCK */
|
|
|
|
/* hash the octets in the BLOCK */
|
|
if (value->v_block->datalen > 0) {
|
|
state = hash_usb8(type, value->v_block->data,
|
|
value->v_block->datalen, state);
|
|
}
|
|
break;
|
|
|
|
case V_OCTET:
|
|
/* there is no setup for an OCTET */
|
|
|
|
/* hash the OCTET */
|
|
state = hash_usb8(type, value->v_octet, 1, state);
|
|
break;
|
|
|
|
case V_NBLOCK:
|
|
/* there is no setup for a NBLOCK */
|
|
|
|
/* hash the octets in the NBLOCK */
|
|
if (value->v_nblock->blk->datalen > 0) {
|
|
state = hash_usb8(type, value->v_nblock->blk->data,
|
|
value->v_nblock->blk->datalen,
|
|
state);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
math_error("hashing an unknown value");
|
|
not_reached();
|
|
}
|
|
return state;
|
|
}
|