/*
* This file is part of DGD, http://dgd-osr.sourceforge.net/
* Copyright (C) 1993-2010 Dworkin B.V.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
# ifndef FUNCDEF
# define INCLUDE_CTYPE
# include "kfun.h"
# include "parse.h"
# include "asn.h"
# endif
# ifdef FUNCDEF
FUNCDEF("encrypt", kf_encrypt, pt_encrypt, 0)
# else
char pt_encrypt[] = { C_TYPECHECKED | C_STATIC, 2, 1, 0, 9, T_MIXED, T_STRING,
T_STRING, T_STRING };
/*
* NAME: kfun->encrypt()
* DESCRIPTION: encrypt a string
*/
int kf_encrypt(f, nargs)
register frame *f;
register int nargs;
{
extern string *P_encrypt_des_key P((frame*, string*));
extern string *P_encrypt_des P((frame*, string*, string*));
string *str;
str = (string *) NULL;
if (nargs == 2) {
if (f->sp[1].u.string->len == 7 &&
strcmp(f->sp[1].u.string->text, "DES key") == 0) {
/*
* prepare key for encryption
*/
str = P_encrypt_des_key(f, f->sp->u.string);
}
} else {
if (f->sp[2].u.string->len == 3 &&
strcmp(f->sp[2].u.string->text, "DES") == 0) {
/*
* encrypt
*/
str = P_encrypt_des(f, f->sp[1].u.string, f->sp->u.string);
}
}
if (str == (string *) NULL) {
error("Unknown cipher");
}
while (--nargs != 0) {
str_del((f->sp++)->u.string);
}
str_del(f->sp->u.string);
PUT_STR(f->sp, str);
return 0;
}
# endif
# ifdef FUNCDEF
FUNCDEF("decrypt", kf_decrypt, pt_decrypt, 0)
# else
char pt_decrypt[] = { C_TYPECHECKED | C_STATIC, 2, 1, 0, 9, T_MIXED, T_STRING,
T_STRING, T_STRING };
/*
* NAME: kfun->decrypt()
* DESCRIPTION: decrypt a string
*/
int kf_decrypt(f, nargs)
register frame *f;
register int nargs;
{
extern string *P_decrypt_des_key P((frame*, string*));
extern string *P_encrypt_des P((frame*, string*, string*));
string *str;
str = (string *) NULL;
if (nargs == 2) {
if (f->sp[1].u.string->len == 7 &&
strcmp(f->sp[1].u.string->text, "DES key") == 0) {
/*
* prepare key for decryption
*/
str = P_decrypt_des_key(f, f->sp->u.string);
}
} else {
if (f->sp[2].u.string->len == 3 &&
strcmp(f->sp[2].u.string->text, "DES") == 0) {
/*
* decrypt
*/
str = P_encrypt_des(f, f->sp[1].u.string, f->sp->u.string);
}
}
if (str == (string *) NULL) {
error("Unknown cipher");
}
while (--nargs != 0) {
str_del((f->sp++)->u.string);
}
str_del(f->sp->u.string);
PUT_STR(f->sp, str);
return 0;
}
# endif
# ifdef FUNCDEF
FUNCDEF("ctime", kf_ctime, pt_ctime, 0)
# else
char pt_ctime[] = { C_TYPECHECKED | C_STATIC, 1, 0, 0, 7, T_STRING, T_INT };
/*
* NAME: kfun->ctime()
* DESCRIPTION: convert a time value to a string
*/
int kf_ctime(f)
frame *f;
{
char buf[26];
i_add_ticks(f, 5);
P_ctime(buf, f->sp->u.number);
PUT_STRVAL(f->sp, str_new(buf, 24L));
return 0;
}
# endif
# ifdef FUNCDEF
FUNCDEF("explode", kf_explode, pt_explode, 0)
# else
char pt_explode[] = { C_TYPECHECKED | C_STATIC, 2, 0, 0, 8,
T_STRING | (1 << REFSHIFT), T_STRING, T_STRING };
/*
* NAME: kfun->explode()
* DESCRIPTION: explode a string
*/
int kf_explode(f)
register frame *f;
{
register unsigned int len, slen, size;
register char *p, *s;
register value *v;
array *a;
p = f->sp[1].u.string->text;
len = f->sp[1].u.string->len;
s = f->sp->u.string->text;
slen = f->sp->u.string->len;
if (len == 0) {
/*
* exploding "" always gives an empty array
*/
a = arr_new(f->data, 0L);
} else if (slen == 0) {
/*
* the sepatator is ""; split string into single characters
*/
a = arr_new(f->data, (long) len);
for (v = a->elts; len > 0; v++, --len) {
PUT_STRVAL(v, str_new(p, 1L));
p++;
}
} else {
/*
* split up the string with the separator
*/
size = 1;
if (len >= slen && memcmp(p, s, slen) == 0) {
/* skip leading separator */
p += slen;
len -= slen;
}
while (len > slen) {
if (memcmp(p, s, slen) == 0) {
/* separator found */
p += slen;
len -= slen;
size++;
} else {
/* next char */
p++;
--len;
}
}
a = arr_new(f->data, (long) size);
v = a->elts;
p = f->sp[1].u.string->text;
len = f->sp[1].u.string->len;
size = 0;
if (len > slen && memcmp(p, s, slen) == 0) {
/* skip leading separator */
p += slen;
len -= slen;
}
while (len > slen) {
if (memcmp(p, s, slen) == 0) {
/* separator found */
PUT_STRVAL(v, str_new(p - size, (long) size));
v++;
p += slen;
len -= slen;
size = 0;
} else {
/* next char */
p++;
--len;
size++;
}
}
if (len != slen || memcmp(p, s, slen) != 0) {
/* remainder isn't a sepatator */
size += len;
p += len;
}
/* final array element */
PUT_STRVAL(v, str_new(p - size, (long) size));
}
str_del((f->sp++)->u.string);
str_del(f->sp->u.string);
PUT_ARRVAL(f->sp, a);
i_add_ticks(f, (Int) 2 * a->size);
return 0;
}
# endif
# ifdef FUNCDEF
FUNCDEF("implode", kf_implode, pt_implode, 0)
# else
char pt_implode[] = { C_TYPECHECKED | C_STATIC, 2, 0, 0, 8, T_STRING,
T_STRING | (1 << REFSHIFT), T_STRING };
/*
* NAME: kfun->implode()
* DESCRIPTION: implode an array
*/
int kf_implode(f)
register frame *f;
{
register long len;
register unsigned int i, slen;
register char *p, *s;
register value *v;
string *str;
s = f->sp->u.string->text;
slen = f->sp->u.string->len;
/* first, determine the size of the imploded string */
i = f->sp[1].u.array->size;
i_add_ticks(f, i);
if (i != 0) {
len = (i - 1) * (long) slen; /* size of all separators */
for (v = d_get_elts(f->sp[1].u.array); i > 0; v++, --i) {
if (v->type != T_STRING) {
/* not a (string *) */
return 1;
}
len += v->u.string->len;
}
str = str_new((char *) NULL, len);
/* create the imploded string */
p = str->text;
for (i = f->sp[1].u.array->size, v -= i; i > 1; --i, v++) {
/* copy array part */
memcpy(p, v->u.string->text, v->u.string->len);
p += v->u.string->len;
/* copy separator */
memcpy(p, s, slen);
p += slen;
}
/* copy final array part */
memcpy(p, v->u.string->text, v->u.string->len);
} else {
/* zero size array gives zero size string */
str = str_new((char *) NULL, 0L);
}
str_del((f->sp++)->u.string);
arr_del(f->sp->u.array);
PUT_STRVAL(f->sp, str);
return 0;
}
# endif
# ifdef FUNCDEF
FUNCDEF("random", kf_random, pt_random, 0)
# else
char pt_random[] = { C_TYPECHECKED | C_STATIC, 1, 0, 0, 7, T_INT, T_INT };
/*
* NAME: kfun->random()
* DESCRIPTION: return a random number
*/
int kf_random(f)
register frame *f;
{
i_add_ticks(f, 1);
PUT_INT(f->sp, (f->sp->u.number > 0) ? P_random() % f->sp->u.number : 0);
return 0;
}
# endif
# ifdef FUNCDEF
FUNCDEF("sscanf", kf_sscanf, pt_sscanf, 0)
# else
char pt_sscanf[] = { C_TYPECHECKED | C_STATIC | C_ELLIPSIS, 2, 1, 0, 9, T_INT,
T_STRING, T_STRING, T_LVALUE };
/*
* NAME: match
* DESCRIPTION: match a string possibly including %%, up to the next %[sdfc] or
* the end of the string
*/
static bool match(f, s, flenp, slenp)
register char *f, *s;
unsigned int *flenp, *slenp;
{
register char *p;
register unsigned int flen, slen;
flen = *flenp;
slen = *slenp;
while (flen > 0) {
/* look for first % */
p = (char *) memchr(f, '%', flen);
if (p == (char *) NULL) {
/* no remaining % */
if (memcmp(f, s, flen) == 0) {
*slenp -= slen - flen;
return TRUE;
} else {
return FALSE; /* no match */
}
}
if (p[1] == '%') {
/* %% */
if (memcmp(f, s, ++p - f) == 0) {
/* matched up to and including the first % */
s += p - f;
slen -= p - f;
flen -= ++p - f;
f = p;
} else {
return FALSE; /* no match */
}
} else if (memcmp(f, s, p - f) == 0) {
/* matched up to the first % */
*flenp -= flen - (p - f);
*slenp -= slen - (p - f);
return TRUE;
} else {
return FALSE; /* no match */
}
}
*slenp -= slen;
return TRUE;
}
/*
* NAME: kfun->sscanf()
* DESCRIPTION: scan a string
*/
int kf_sscanf(f, nargs)
register frame *f;
int nargs;
{
register unsigned int flen, slen, size;
register char *format, *x;
unsigned int fl, sl;
int matches;
char *s;
Int i;
xfloat flt;
bool skip;
if (nargs > MAX_LOCALS + 2) {
return 4;
}
s = f->sp[nargs - 1].u.string->text;
slen = f->sp[nargs - 1].u.string->len;
nargs -= 2;
format = f->sp[nargs].u.string->text;
flen = f->sp[nargs].u.string->len;
i_reverse(f, nargs);
i_add_ticks(f, 8 * nargs);
matches = 0;
while (flen > 0) {
if (format[0] != '%' || format[1] == '%') {
/* match initial part */
fl = flen;
sl = slen;
if (!match(format, s, &fl, &sl) || fl == flen) {
goto no_match;
}
format += fl;
flen -= fl;
s += sl;
slen -= sl;
}
/* skip first % */
format++;
--flen;
/*
* check for %*
*/
if (*format == '*') {
/* no assignment */
format++;
--flen;
skip = TRUE;
} else {
skip = FALSE;
}
--flen;
switch (*format++) {
case 's':
/* %s */
if (format[0] == '%' && format[1] != '%') {
switch ((format[1] == '*') ? format[2] : format[1]) {
case 'd':
/*
* %s%d
*/
size = slen;
x = s;
while (!isdigit(*x)) {
if (slen == 0) {
goto no_match;
}
if (x[0] == '-' && isdigit(x[1])) {
break;
}
x++;
--slen;
}
size -= slen;
break;
case 'f':
/*
* %s%f
*/
size = slen;
x = s;
while (!isdigit(*x)) {
if (slen == 0) {
goto no_match;
}
if ((x[0] == '-' || x[0] == '.') && isdigit(x[1])) {
break;
}
x++;
--slen;
}
size -= slen;
break;
default:
error("Bad sscanf format string");
}
} else {
/*
* %s followed by non-%
*/
if (flen == 0) {
/* match whole string */
size = slen;
x = s + slen;
slen = 0;
} else {
/* get # of chars to match after string */
for (x = format, size = 0; (x - format) != flen;
x++, size++) {
x = (char *) memchr(x, '%', flen - (x - format));
if (x == (char *) NULL) {
x = format + flen;
break;
} else if (x[1] != '%') {
break;
}
}
size = (x - format) - size;
x = s;
for (;;) {
sl = slen - (x - s);
if (sl < size) {
goto no_match;
}
x = (char *) memchr(x, format[0], sl - size + 1);
if (x == (char *) NULL) {
goto no_match;
}
fl = flen;
if (match(format, x, &fl, &sl)) {
format += fl;
flen -= fl;
size = x - s;
x += sl;
slen -= size + sl;
break;
}
x++;
}
}
}
if (!skip) {
if (nargs == 0) {
error("No lvalue for %%s");
}
--nargs;
PUSH_STRVAL(f, str_new(s, (long) size));
i_store(f);
f->sp->u.string->ref--;
f->sp += 2;
}
s = x;
break;
case 'd':
/* %d */
x = s;
while (slen != 0 && *x == ' ') {
x++;
--slen;
}
s = x;
i = strtoint(&s);
if (s == x) {
goto no_match;
}
slen -= (s - x);
if (!skip) {
if (nargs == 0) {
error("No lvalue for %%d");
}
--nargs;
PUSH_INTVAL(f, i);
i_store(f);
f->sp += 2;
}
break;
case 'f':
/* %f */
x = s;
while (slen != 0 && *x == ' ') {
x++;
--slen;
}
s = x;
if (!flt_atof(&s, &flt) || s == x) {
goto no_match;
}
slen -= (s - x);
if (!skip) {
if (nargs == 0) {
error("No lvalue for %%f");
}
--nargs;
PUSH_FLTVAL(f, flt);
i_store(f);
f->sp += 2;
}
break;
case 'c':
/* %c */
if (slen == 0) {
goto no_match;
}
if (!skip) {
if (nargs == 0) {
error("No lvalue for %%c");
}
--nargs;
PUSH_INTVAL(f, UCHAR(*s));
i_store(f);
f->sp += 2;
}
s++;
--slen;
break;
default:
error("Bad sscanf format string");
}
matches++;
}
no_match:
if (nargs > 0) {
i_pop(f, nargs); /* pop superfluous arguments */
}
str_del((f->sp++)->u.string);
str_del(f->sp->u.string);
PUT_INTVAL(f->sp, matches);
return 0;
}
# endif
# ifdef FUNCDEF
FUNCDEF("parse_string", kf_parse_string, pt_parse_string, 0)
# else
char pt_parse_string[] = { C_TYPECHECKED | C_STATIC, 2, 1, 0, 9,
T_MIXED | (1 << REFSHIFT), T_STRING, T_STRING,
T_INT };
/*
* NAME: kfun->parse_string()
* DESCRIPTION: parse a string
*/
int kf_parse_string(f, nargs)
register frame *f;
int nargs;
{
Int maxalt;
array *a;
if (nargs > 2) {
maxalt = (f->sp++)->u.number + 1;
if (maxalt <= 0) {
return 3;
}
} else {
maxalt = 1; /* default: just one valid parse tree */
}
if (OBJR(f->oindex)->flags & O_SPECIAL) {
error("parse_string() from special purpose object");
}
a = ps_parse_string(f, f->sp[1].u.string, f->sp->u.string, maxalt);
str_del((f->sp++)->u.string);
str_del(f->sp->u.string);
if (a != (array *) NULL) {
/* return parse tree */
PUT_ARRVAL(f->sp, a);
} else {
/* parsing failed */
*f->sp = nil_value;
}
return 0;
}
# endif
# ifdef FUNCDEF
FUNCDEF("hash_crc16", kf_hash_crc16, pt_hash_crc16, 0)
# else
char pt_hash_crc16[] = { C_TYPECHECKED | C_STATIC | C_ELLIPSIS, 1, 1, 0, 8,
T_INT, T_STRING, T_STRING };
/*
* NAME: kfun->hash_crc16()
* DESCRIPTION: Compute a 16 bit cyclic redundancy code for a string.
* Based on "A PAINLESS GUIDE TO CRC ERROR DETECTION ALGORITHMS",
* by Ross N. Williams.
*
* Name: "CRC-16/CCITT" (supposedly)
* Width: 16
* Poly: 1021 (X^16 + X^12 + X^5 + 1)
* Init: FFFF
* RefIn: False
* RefOut: False
* XorOut: 0000
* Check: 29B1
*/
int kf_hash_crc16(f, nargs)
register frame *f;
int nargs;
{
static unsigned short crctab[] = {
0x0000, 0x2110, 0x4220, 0x6330, 0x8440, 0xa550, 0xc660, 0xe770,
0x0881, 0x2991, 0x4aa1, 0x6bb1, 0x8cc1, 0xadd1, 0xcee1, 0xeff1,
0x3112, 0x1002, 0x7332, 0x5222, 0xb552, 0x9442, 0xf772, 0xd662,
0x3993, 0x1883, 0x7bb3, 0x5aa3, 0xbdd3, 0x9cc3, 0xfff3, 0xdee3,
0x6224, 0x4334, 0x2004, 0x0114, 0xe664, 0xc774, 0xa444, 0x8554,
0x6aa5, 0x4bb5, 0x2885, 0x0995, 0xeee5, 0xcff5, 0xacc5, 0x8dd5,
0x5336, 0x7226, 0x1116, 0x3006, 0xd776, 0xf666, 0x9556, 0xb446,
0x5bb7, 0x7aa7, 0x1997, 0x3887, 0xdff7, 0xfee7, 0x9dd7, 0xbcc7,
0xc448, 0xe558, 0x8668, 0xa778, 0x4008, 0x6118, 0x0228, 0x2338,
0xccc9, 0xedd9, 0x8ee9, 0xaff9, 0x4889, 0x6999, 0x0aa9, 0x2bb9,
0xf55a, 0xd44a, 0xb77a, 0x966a, 0x711a, 0x500a, 0x333a, 0x122a,
0xfddb, 0xdccb, 0xbffb, 0x9eeb, 0x799b, 0x588b, 0x3bbb, 0x1aab,
0xa66c, 0x877c, 0xe44c, 0xc55c, 0x222c, 0x033c, 0x600c, 0x411c,
0xaeed, 0x8ffd, 0xeccd, 0xcddd, 0x2aad, 0x0bbd, 0x688d, 0x499d,
0x977e, 0xb66e, 0xd55e, 0xf44e, 0x133e, 0x322e, 0x511e, 0x700e,
0x9fff, 0xbeef, 0xdddf, 0xfccf, 0x1bbf, 0x3aaf, 0x599f, 0x788f,
0x8891, 0xa981, 0xcab1, 0xeba1, 0x0cd1, 0x2dc1, 0x4ef1, 0x6fe1,
0x8010, 0xa100, 0xc230, 0xe320, 0x0450, 0x2540, 0x4670, 0x6760,
0xb983, 0x9893, 0xfba3, 0xdab3, 0x3dc3, 0x1cd3, 0x7fe3, 0x5ef3,
0xb102, 0x9012, 0xf322, 0xd232, 0x3542, 0x1452, 0x7762, 0x5672,
0xeab5, 0xcba5, 0xa895, 0x8985, 0x6ef5, 0x4fe5, 0x2cd5, 0x0dc5,
0xe234, 0xc324, 0xa014, 0x8104, 0x6674, 0x4764, 0x2454, 0x0544,
0xdba7, 0xfab7, 0x9987, 0xb897, 0x5fe7, 0x7ef7, 0x1dc7, 0x3cd7,
0xd326, 0xf236, 0x9106, 0xb016, 0x5766, 0x7676, 0x1546, 0x3456,
0x4cd9, 0x6dc9, 0x0ef9, 0x2fe9, 0xc899, 0xe989, 0x8ab9, 0xaba9,
0x4458, 0x6548, 0x0678, 0x2768, 0xc018, 0xe108, 0x8238, 0xa328,
0x7dcb, 0x5cdb, 0x3feb, 0x1efb, 0xf98b, 0xd89b, 0xbbab, 0x9abb,
0x754a, 0x545a, 0x376a, 0x167a, 0xf10a, 0xd01a, 0xb32a, 0x923a,
0x2efd, 0x0fed, 0x6cdd, 0x4dcd, 0xaabd, 0x8bad, 0xe89d, 0xc98d,
0x267c, 0x076c, 0x645c, 0x454c, 0xa23c, 0x832c, 0xe01c, 0xc10c,
0x1fef, 0x3eff, 0x5dcf, 0x7cdf, 0x9baf, 0xbabf, 0xd98f, 0xf89f,
0x176e, 0x367e, 0x554e, 0x745e, 0x932e, 0xb23e, 0xd10e, 0xf01e
};
register unsigned short crc;
register int i;
register ssizet len;
register char *p;
register Int cost;
cost = 0;
for (i = nargs; --i >= 0; ) {
cost += f->sp[i].u.string->len;
}
cost = 3 * nargs + (cost >> 2);
if (!f->rlim->noticks && f->rlim->ticks <= cost) {
f->rlim->ticks = 0;
error("Out of ticks");
}
i_add_ticks(f, cost);
crc = 0xffff;
for (i = nargs; --i >= 0; ) {
p = f->sp[i].u.string->text;
for (len = f->sp[i].u.string->len; len != 0; --len) {
crc = (crc >> 8) ^ crctab[UCHAR(crc ^ *p++)];
}
str_del(f->sp[i].u.string);
}
crc = (crc >> 8) + (crc << 8);
f->sp += nargs - 1;
PUT_INTVAL(f->sp, crc);
return 0;
}
# endif
# ifdef FUNCDEF
FUNCDEF("hash_crc32", kf_hash_crc32, pt_hash_crc32, 0)
# else
char pt_hash_crc32[] = { C_TYPECHECKED | C_STATIC | C_ELLIPSIS, 1, 1, 0, 8,
T_INT, T_STRING, T_STRING };
/*
* NAME: kfun->hash_crc32()
* DESCRIPTION: Compute a 32 bit cyclic redundancy code for a string.
* Based on "A PAINLESS GUIDE TO CRC ERROR DETECTION ALGORITHMS",
* by Ross N. Williams.
*
* Name: "CRC-32" (as in libz)
* Width: 16
* Poly: 04C11DB7
* Init: FFFFFFFF
* RefIn: True
* RefOut: True
* XorOut: FFFFFFFF
* Check: CBF43926
*/
int kf_hash_crc32(f, nargs)
register frame *f;
int nargs;
{
static Uint crctab[] = {
0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
0x2d02ef8dL
};
register Uint crc;
register int i;
register ssizet len;
register char *p;
register Int cost;
cost = 0;
for (i = nargs; --i >= 0; ) {
cost += f->sp[i].u.string->len;
}
cost = 3 * nargs + (cost >> 2);
if (!f->rlim->noticks && f->rlim->ticks <= cost) {
f->rlim->ticks = 0;
error("Out of ticks");
}
i_add_ticks(f, cost);
crc = 0xffffffff;
for (i = nargs; --i >= 0; ) {
p = f->sp[i].u.string->text;
for (len = f->sp[i].u.string->len; len != 0; --len) {
crc = (crc >> 8) ^ crctab[UCHAR(crc ^ *p++)];
}
str_del(f->sp[i].u.string);
}
crc ^= 0xffffffffL;
f->sp += nargs - 1;
PUT_INTVAL(f->sp, crc);
return 0;
}
# endif
# ifdef FUNCDEF
FUNCDEF("hash_string", kf_hash_string, pt_hash_string, 0)
# else
char pt_hash_string[] = { C_TYPECHECKED | C_STATIC | C_ELLIPSIS, 2, 1, 0, 9,
T_STRING, T_STRING, T_STRING, T_STRING };
/*
* NAME: hash->crypt()
* DESCRIPTION: hash a string with Unix password crypt
*/
static string *hash_crypt(f, passwd, salt)
register frame *f;
string *passwd, *salt;
{
extern char *P_crypt P((char*, char*));
static char salts[] =
"0123456789./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
char s[3];
if (salt != (string *) NULL && salt->text[0] != '\0' &&
salt->text[1] != '\0') {
/* fixed salt */
s[0] = salt->text[0];
s[1] = salt->text[1];
} else {
Uint n;
/* random salt */
n = P_random();
s[0] = salts[n & 63];
s[1] = salts[(n >> 8) & 63];
}
s[2] = '\0';
i_add_ticks(f, 900);
return str_new(P_crypt(passwd->text, s), 13);
}
# define ROTL(x, s) (((x) << s) | ((x) >> (32 - s)))
# define R1(a, b, c, d, Mj, s, ti) (a += (((c ^ d) & b) ^ d) + Mj + ti, \
a = b + ROTL(a, s))
# define R2(a, b, c, d, Mj, s, ti) (a += (((b ^ c) & d) ^ c) + Mj + ti, \
a = b + ROTL(a, s))
# define R3(a, b, c, d, Mj, s, ti) (a += (b ^ c ^ d) + Mj + ti, \
a = b + ROTL(a, s))
# define R4(a, b, c, d, Mj, s, ti) (a += (c ^ (b | ~d)) + Mj + ti, \
a = b + ROTL(a, s))
/*
* NAME: hash->md5_start()
* DESCRIPTION: MD5 message digest. See "Applied Cryptography" by Bruce
* Schneier, Second Edition, p. 436-441.
*/
static Int hash_md5_start(f, nargs, digest)
register frame *f;
register int nargs;
register Uint *digest;
{
register Int cost;
/*
* These constants must apparently be little-endianized, though AC2 does
* not explicitly say so.
*/
digest[0] = 0x67452301L;
digest[1] = 0xefcdab89L;
digest[2] = 0x98badcfeL;
digest[3] = 0x10325476L;
cost = 3 * nargs + 64;
while (--nargs >= 0) {
cost += f->sp[nargs].u.string->len;
}
return cost;
}
/*
* NAME: hash->md5_block()
* DESCRIPTION: add another 512 bit block to the message digest
*/
static void hash_md5_block(ABCD, block)
Uint *ABCD;
register char *block;
{
Uint M[16];
register int i, j;
register Uint a, b, c, d;
for (i = j = 0; i < 16; i++, j += 4) {
M[i] = UCHAR(block[j + 0]) | (UCHAR(block[j + 1]) << 8) |
(UCHAR(block[j + 2]) << 16) | (UCHAR(block[j + 3]) << 24);
}
a = ABCD[0];
b = ABCD[1];
c = ABCD[2];
d = ABCD[3];
R1(a, b, c, d, M[ 0], 7, 0xd76aa478L);
R1(d, a, b, c, M[ 1], 12, 0xe8c7b756L);
R1(c, d, a, b, M[ 2], 17, 0x242070dbL);
R1(b, c, d, a, M[ 3], 22, 0xc1bdceeeL);
R1(a, b, c, d, M[ 4], 7, 0xf57c0fafL);
R1(d, a, b, c, M[ 5], 12, 0x4787c62aL);
R1(c, d, a, b, M[ 6], 17, 0xa8304613L);
R1(b, c, d, a, M[ 7], 22, 0xfd469501L);
R1(a, b, c, d, M[ 8], 7, 0x698098d8L);
R1(d, a, b, c, M[ 9], 12, 0x8b44f7afL);
R1(c, d, a, b, M[10], 17, 0xffff5bb1L);
R1(b, c, d, a, M[11], 22, 0x895cd7beL);
R1(a, b, c, d, M[12], 7, 0x6b901122L);
R1(d, a, b, c, M[13], 12, 0xfd987193L);
R1(c, d, a, b, M[14], 17, 0xa679438eL);
R1(b, c, d, a, M[15], 22, 0x49b40821L);
R2(a, b, c, d, M[ 1], 5, 0xf61e2562L);
R2(d, a, b, c, M[ 6], 9, 0xc040b340L);
R2(c, d, a, b, M[11], 14, 0x265e5a51L);
R2(b, c, d, a, M[ 0], 20, 0xe9b6c7aaL);
R2(a, b, c, d, M[ 5], 5, 0xd62f105dL);
R2(d, a, b, c, M[10], 9, 0x02441453L);
R2(c, d, a, b, M[15], 14, 0xd8a1e681L);
R2(b, c, d, a, M[ 4], 20, 0xe7d3fbc8L);
R2(a, b, c, d, M[ 9], 5, 0x21e1cde6L);
R2(d, a, b, c, M[14], 9, 0xc33707d6L);
R2(c, d, a, b, M[ 3], 14, 0xf4d50d87L);
R2(b, c, d, a, M[ 8], 20, 0x455a14edL);
R2(a, b, c, d, M[13], 5, 0xa9e3e905L);
R2(d, a, b, c, M[ 2], 9, 0xfcefa3f8L);
R2(c, d, a, b, M[ 7], 14, 0x676f02d9L);
R2(b, c, d, a, M[12], 20, 0x8d2a4c8aL);
R3(a, b, c, d, M[ 5], 4, 0xfffa3942L);
R3(d, a, b, c, M[ 8], 11, 0x8771f681L);
R3(c, d, a, b, M[11], 16, 0x6d9d6122L);
R3(b, c, d, a, M[14], 23, 0xfde5380cL);
R3(a, b, c, d, M[ 1], 4, 0xa4beea44L);
R3(d, a, b, c, M[ 4], 11, 0x4bdecfa9L);
R3(c, d, a, b, M[ 7], 16, 0xf6bb4b60L);
R3(b, c, d, a, M[10], 23, 0xbebfbc70L);
R3(a, b, c, d, M[13], 4, 0x289b7ec6L);
R3(d, a, b, c, M[ 0], 11, 0xeaa127faL);
R3(c, d, a, b, M[ 3], 16, 0xd4ef3085L);
R3(b, c, d, a, M[ 6], 23, 0x04881d05L);
R3(a, b, c, d, M[ 9], 4, 0xd9d4d039L);
R3(d, a, b, c, M[12], 11, 0xe6db99e5L);
R3(c, d, a, b, M[15], 16, 0x1fa27cf8L);
R3(b, c, d, a, M[ 2], 23, 0xc4ac5665L);
R4(a, b, c, d, M[ 0], 6, 0xf4292244L);
R4(d, a, b, c, M[ 7], 10, 0x432aff97L);
R4(c, d, a, b, M[14], 15, 0xab9423a7L);
R4(b, c, d, a, M[ 5], 21, 0xfc93a039L);
R4(a, b, c, d, M[12], 6, 0x655b59c3L);
R4(d, a, b, c, M[ 3], 10, 0x8f0ccc92L);
R4(c, d, a, b, M[10], 15, 0xffeff47dL);
R4(b, c, d, a, M[ 1], 21, 0x85845dd1L);
R4(a, b, c, d, M[ 8], 6, 0x6fa87e4fL);
R4(d, a, b, c, M[15], 10, 0xfe2ce6e0L);
R4(c, d, a, b, M[ 6], 15, 0xa3014314L);
R4(b, c, d, a, M[13], 21, 0x4e0811a1L);
R4(a, b, c, d, M[ 4], 6, 0xf7537e82L);
R4(d, a, b, c, M[11], 10, 0xbd3af235L);
R4(c, d, a, b, M[ 2], 15, 0x2ad7d2bbL);
R4(b, c, d, a, M[ 9], 21, 0xeb86d391L);
ABCD[0] += a;
ABCD[1] += b;
ABCD[2] += c;
ABCD[3] += d;
}
/*
* NAME: hash->md5_end()
* DESCRIPTION: finish up MD5 hash
*/
static string *hash_md5_end(digest, buffer, bufsz, length)
register Uint *digest;
register char *buffer;
register unsigned int bufsz;
register Uint length;
{
register int i;
/* append padding and digest final block(s) */
buffer[bufsz++] = 0x80;
if (bufsz > 56) {
memset(buffer + bufsz, '\0', 64 - bufsz);
hash_md5_block(digest, buffer);
bufsz = 0;
}
memset(buffer + bufsz, '\0', 64 - bufsz);
buffer[56] = length << 3;
buffer[57] = length >> 5;
buffer[58] = length >> 13;
buffer[59] = length >> 21;
buffer[60] = length >> 29;
hash_md5_block(digest, buffer);
for (bufsz = i = 0; i < 4; bufsz += 4, i++) {
buffer[bufsz + 0] = digest[i];
buffer[bufsz + 1] = digest[i] >> 8;
buffer[bufsz + 2] = digest[i] >> 16;
buffer[bufsz + 3] = digest[i] >> 24;
}
return str_new(buffer, 16L);
}
/*
* NAME: hash->sha1_start()
* DESCRIPTION: SHA-1 message digest. See FIPS 180-2.
*/
static Int hash_sha1_start(f, nargs, digest)
register frame *f;
register int nargs;
register Uint *digest;
{
register Int cost;
digest[0] = 0x67452301L;
digest[1] = 0xefcdab89L;
digest[2] = 0x98badcfeL;
digest[3] = 0x10325476L;
digest[4] = 0xc3d2e1f0L;
cost = 3 * nargs + 64;
while (--nargs >= 0) {
cost += f->sp[nargs].u.string->len;
}
return cost;
}
/*
* NAME: hash->sha1_block()
* DESCRIPTION: add another 512 bit block to the message digest
*/
static void hash_sha1_block(ABCDE, block)
Uint *ABCDE;
register char *block;
{
Uint W[80];
register int i, j;
register Uint a, b, c, d, e, t;
for (i = j = 0; i < 16; i++, j += 4) {
W[i] = (UCHAR(block[j + 0]) << 24) | (UCHAR(block[j + 1]) << 16) |
(UCHAR(block[j + 2]) << 8) | UCHAR(block[j + 3]);
}
while (i < 80) {
W[i] = ROTL(W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16], 1);
i++;
}
a = ABCDE[0];
b = ABCDE[1];
c = ABCDE[2];
d = ABCDE[3];
e = ABCDE[4];
for (i = 0; i < 20; i++) {
t = ROTL(a, 5) + (((c ^ d) & b) ^ d) + e + W[i] + 0x5a827999L;
e = d;
d = c;
c = ROTL(b, 30);
b = a;
a = t;
}
while (i < 40) {
t = ROTL(a, 5) + (b ^ c ^ d) + e + W[i] + 0x6ed9eba1L;
e = d;
d = c;
c = ROTL(b, 30);
b = a;
a = t;
i++;
}
while (i < 60) {
t = ROTL(a, 5) + ((b & c) | ((b | c) & d)) + e + W[i] + 0x8f1bbcdcL;
e = d;
d = c;
c = ROTL(b, 30);
b = a;
a = t;
i++;
}
while (i < 80) {
t = ROTL(a, 5) + (b ^ c ^ d) + e + W[i] + 0xca62c1d6L;
e = d;
d = c;
c = ROTL(b, 30);
b = a;
a = t;
i++;
}
ABCDE[0] += a;
ABCDE[1] += b;
ABCDE[2] += c;
ABCDE[3] += d;
ABCDE[4] += e;
}
/*
* NAME: hash->sha1_end()
* DESCRIPTION: finish up SHA-1 hash
*/
static string *hash_sha1_end(digest, buffer, bufsz, length)
register Uint *digest, length;
register char *buffer;
register unsigned int bufsz;
{
register int i;
/* append padding and digest final block(s) */
buffer[bufsz++] = 0x80;
if (bufsz > 56) {
memset(buffer + bufsz, '\0', 64 - bufsz);
hash_sha1_block(digest, buffer);
bufsz = 0;
}
memset(buffer + bufsz, '\0', 64 - bufsz);
buffer[59] = length >> 29;
buffer[60] = length >> 21;
buffer[61] = length >> 13;
buffer[62] = length >> 5;
buffer[63] = length << 3;
hash_sha1_block(digest, buffer);
for (bufsz = i = 0; i < 5; bufsz += 4, i++) {
buffer[bufsz + 0] = digest[i] >> 24;
buffer[bufsz + 1] = digest[i] >> 16;
buffer[bufsz + 2] = digest[i] >> 8;
buffer[bufsz + 3] = digest[i];
}
return str_new(buffer, 20L);
}
/*
* NAME: hash->blocks()
* DESCRIPTION: hash string blocks with a given function
*/
static Uint hash_blocks(f, nargs, digest, buffer, bufsize, blocksz, hash_block)
register frame *f;
register int nargs;
Uint *digest;
char *buffer;
unsigned short *bufsize;
register unsigned int blocksz;
void (*hash_block) P((Uint*, char*));
{
register ssizet len;
register unsigned short bufsz;
register char *p;
register Uint length;
length = 0;
bufsz = 0;
while (--nargs >= 0) {
len = f->sp[nargs].u.string->len;
if (len != 0) {
length += len;
p = f->sp[nargs].u.string->text;
if (bufsz != 0) {
register unsigned short size;
/* fill buffer and digest */
size = blocksz - bufsz;
if (size > len) {
size = len;
}
memcpy(buffer + bufsz, p, size);
p += size;
len -= size;
bufsz += size;
if (bufsz == blocksz) {
(*hash_block)(digest, buffer);
bufsz = 0;
}
}
while (len >= blocksz) {
/* digest directly from string */
(*hash_block)(digest, p);
p += blocksz;
len -= blocksz;
}
if (len != 0) {
/* put remainder in buffer */
memcpy(buffer, p, bufsz = len);
}
}
str_del(f->sp[nargs].u.string);
}
*bufsize = bufsz;
return length;
}
/*
* NAME: kfun->hash_string()
* DESCRIPTION: hash a string
*/
int kf_hash_string(f, nargs)
register frame *f;
int nargs;
{
register string *str, *salt;
char buffer[64];
Uint digest[5];
Int cost;
Uint length;
unsigned short bufsz;
str = f->sp[nargs - 1].u.string;
switch (str->text[0]) {
case 'c':
if (str->len == 5 && strcmp(str->text, "crypt") == 0) {
if (nargs > 3) {
return 3;
}
if (nargs == 3) {
salt = f->sp->u.string;
f->sp++;
} else {
salt = (string *) NULL;
}
str = hash_crypt(f, f->sp->u.string, salt);
if (salt != (string *) NULL) {
str_del(salt);
}
str_del((f->sp++)->u.string);
str_del(f->sp->u.string);
PUT_STR(f->sp, str);
return 0;
}
break;
case 'M':
if (str->len == 3 && strcmp(str->text, "MD5") == 0) {
cost = hash_md5_start(f, nargs, digest);
if (!f->rlim->noticks && f->rlim->ticks <= cost) {
f->rlim->ticks = 0;
error("Out of ticks");
}
i_add_ticks(f, cost);
length = hash_blocks(f, --nargs, digest, buffer, &bufsz, 64,
&hash_md5_block);
f->sp += nargs;
str_del(f->sp->u.string);
PUT_STR(f->sp, hash_md5_end(digest, buffer, bufsz, length));
return 0;
}
break;
case 'S':
if (str->len == 4 && strcmp(str->text, "SHA1") == 0) {
cost = hash_sha1_start(f, nargs, digest);
if (!f->rlim->noticks && f->rlim->ticks <= cost) {
f->rlim->ticks = 0;
error("Out of ticks");
}
i_add_ticks(f, cost);
length = hash_blocks(f, --nargs, digest, buffer, &bufsz, 64,
&hash_sha1_block);
f->sp += nargs;
str_del(f->sp->u.string);
PUT_STR(f->sp, hash_sha1_end(digest, buffer, bufsz, length));
return 0;
}
break;
}
error("Unknown hash algorithm");
}
# endif
# ifdef FUNCDEF
FUNCDEF("crypt", kf_crypt, pt_crypt, 0)
# else
char pt_crypt[] = { C_TYPECHECKED | C_STATIC, 1, 1, 0, 8, T_STRING, T_STRING,
T_STRING };
/*
* NAME: kfun->crypt()
* DESCRIPTION: hash_string("crypt", ...)
*/
int kf_crypt(f, nargs)
register frame *f;
int nargs;
{
string *salt, *str;
if (nargs == 2) {
salt = f->sp->u.string;
f->sp++;
} else {
salt = (string *) NULL;
}
str = hash_crypt(f, f->sp->u.string, salt);
if (salt != (string *) NULL) {
str_del(salt);
}
str_del(f->sp->u.string);
PUT_STR(f->sp, str);
return 0;
}
# endif
# ifdef FUNCDEF
FUNCDEF("0.hash_md5", kf_hash_md5, pt_hash_md5, 0)
# else
char pt_hash_md5[] = { C_TYPECHECKED | C_STATIC | C_ELLIPSIS, 1, 1, 0, 8,
T_STRING, T_STRING, T_STRING };
/*
* NAME: kfun->hash_md5()
* DESCRIPTION: hash_string("MD5", ...)
*/
int kf_hash_md5(f, nargs)
register frame *f;
int nargs;
{
char buffer[64];
Uint digest[4];
Int cost;
Uint length;
unsigned short bufsz;
cost = hash_md5_start(f, nargs, digest);
if (!f->rlim->noticks && f->rlim->ticks <= cost) {
f->rlim->ticks = 0;
error("Out of ticks");
}
i_add_ticks(f, cost);
length = hash_blocks(f, nargs, digest, buffer, &bufsz, 64, &hash_md5_block);
f->sp += nargs - 1;
PUT_STR(f->sp, hash_md5_end(digest, buffer, bufsz, length));
return 0;
}
# endif
# ifdef FUNCDEF
FUNCDEF("0.hash_sha1", kf_hash_sha1, pt_hash_sha1, 0)
# else
char pt_hash_sha1[] = { C_TYPECHECKED | C_STATIC | C_ELLIPSIS, 1, 1, 0, 8,
T_STRING, T_STRING, T_STRING };
/*
* NAME: kfun->hash_sha1()
* DESCRIPTION: hash_string("SHA1", ...)
*/
int kf_hash_sha1(f, nargs)
register frame *f;
int nargs;
{
char buffer[64];
Uint digest[5];
Int cost;
Uint length;
unsigned short bufsz;
cost = hash_sha1_start(f, nargs, digest);
if (!f->rlim->noticks && f->rlim->ticks <= cost) {
f->rlim->ticks = 0;
error("Out of ticks");
}
i_add_ticks(f, cost);
length = hash_blocks(f, nargs, digest, buffer, &bufsz, 64,
&hash_sha1_block);
f->sp += nargs - 1;
PUT_STR(f->sp, hash_sha1_end(digest, buffer, bufsz, length));
return 0;
}
# endif
# ifdef FUNCDEF
FUNCDEF("asn_add", kf_asn_add, pt_asn_add, 0)
# else
char pt_asn_add[] = { C_TYPECHECKED | C_STATIC, 3, 0, 0, 9, T_STRING, T_STRING,
T_STRING, T_STRING };
/*
* NAME: kfun->asn_add()
* DESCRIPTION: add two arbitrary precision numbers
*/
int kf_asn_add(f)
register frame *f;
{
register string *str;
str = asn_add(f, f->sp[2].u.string, f->sp[1].u.string, f->sp[0].u.string);
str_del((f->sp++)->u.string);
str_del((f->sp++)->u.string);
str_del(f->sp->u.string);
PUT_STR(f->sp, str);
return 0;
}
# endif
# ifdef FUNCDEF
FUNCDEF("asn_sub", kf_asn_sub, pt_asn_sub, 0)
# else
char pt_asn_sub[] = { C_TYPECHECKED | C_STATIC, 3, 0, 0, 9, T_STRING, T_STRING,
T_STRING, T_STRING };
/*
* NAME: kfun->asn_sub()
* DESCRIPTION: subtract arbitrary precision numbers
*/
int kf_asn_sub(f)
register frame *f;
{
register string *str;
str = asn_sub(f, f->sp[2].u.string, f->sp[1].u.string, f->sp[0].u.string);
str_del((f->sp++)->u.string);
str_del((f->sp++)->u.string);
str_del(f->sp->u.string);
PUT_STR(f->sp, str);
return 0;
}
# endif
# ifdef FUNCDEF
FUNCDEF("asn_cmp", kf_asn_cmp, pt_asn_cmp, 0)
# else
char pt_asn_cmp[] = { C_TYPECHECKED | C_STATIC, 2, 0, 0, 8, T_INT, T_STRING,
T_STRING };
/*
* NAME: kfun->asn_cmp()
* DESCRIPTION: subtract arbitrary precision numbers
*/
int kf_asn_cmp(f)
register frame *f;
{
int cmp;
cmp = asn_cmp(f, f->sp[1].u.string, f->sp[0].u.string);
str_del((f->sp++)->u.string);
str_del(f->sp->u.string);
PUT_INTVAL(f->sp, cmp);
return 0;
}
# endif
# ifdef FUNCDEF
FUNCDEF("asn_mult", kf_asn_mult, pt_asn_mult, 0)
# else
char pt_asn_mult[] = { C_TYPECHECKED | C_STATIC, 3, 0, 0, 9, T_STRING, T_STRING,
T_STRING, T_STRING };
/*
* NAME: kfun->asn_mult()
* DESCRIPTION: multiply arbitrary precision numbers
*/
int kf_asn_mult(f)
register frame *f;
{
register string *str;
str = asn_mult(f, f->sp[2].u.string, f->sp[1].u.string, f->sp[0].u.string);
str_del((f->sp++)->u.string);
str_del((f->sp++)->u.string);
str_del(f->sp->u.string);
PUT_STR(f->sp, str);
return 0;
}
# endif
# ifdef FUNCDEF
FUNCDEF("asn_div", kf_asn_div, pt_asn_div, 0)
# else
char pt_asn_div[] = { C_TYPECHECKED | C_STATIC, 3, 0, 0, 9, T_STRING, T_STRING,
T_STRING, T_STRING };
/*
* NAME: kfun->asn_div()
* DESCRIPTION: divide arbitrary precision numbers
*/
int kf_asn_div(f)
register frame *f;
{
register string *str;
str = asn_div(f, f->sp[2].u.string, f->sp[1].u.string, f->sp[0].u.string);
str_del((f->sp++)->u.string);
str_del((f->sp++)->u.string);
str_del(f->sp->u.string);
PUT_STR(f->sp, str);
return 0;
}
# endif
# ifdef FUNCDEF
FUNCDEF("asn_mod", kf_asn_mod, pt_asn_mod, 0)
# else
char pt_asn_mod[] = { C_TYPECHECKED | C_STATIC, 2, 0, 0, 8, T_STRING, T_STRING,
T_STRING };
/*
* NAME: kfun->asn_mod()
* DESCRIPTION: modulus of arbitrary precision number
*/
int kf_asn_mod(f)
register frame *f;
{
register string *str;
str = asn_mod(f, f->sp[1].u.string, f->sp[0].u.string);
str_del((f->sp++)->u.string);
str_del(f->sp->u.string);
PUT_STR(f->sp, str);
return 0;
}
# endif
# ifdef FUNCDEF
FUNCDEF("asn_pow", kf_asn_pow, pt_asn_pow, 0)
# else
char pt_asn_pow[] = { C_TYPECHECKED | C_STATIC, 3, 0, 0, 9, T_STRING, T_STRING,
T_STRING, T_STRING };
/*
* NAME: kfun->asn_pow()
* DESCRIPTION: power of an arbitrary precision number
*/
int kf_asn_pow(f)
register frame *f;
{
register string *str;
str = asn_pow(f, f->sp[2].u.string, f->sp[1].u.string, f->sp[0].u.string);
str_del((f->sp++)->u.string);
str_del((f->sp++)->u.string);
str_del(f->sp->u.string);
PUT_STR(f->sp, str);
return 0;
}
# endif
# ifdef FUNCDEF
FUNCDEF("asn_lshift", kf_asn_lshift, pt_asn_lshift, 0)
# else
char pt_asn_lshift[] = { C_TYPECHECKED | C_STATIC, 3, 0, 0, 9, T_STRING,
T_STRING, T_INT, T_STRING };
/*
* NAME: kfun->asn_lshift()
* DESCRIPTION: left shift an arbitrary precision number
*/
int kf_asn_lshift(f)
register frame *f;
{
string *str;
str = asn_lshift(f, f->sp[2].u.string, f->sp[1].u.number, f->sp->u.string);
str_del(f->sp->u.string);
f->sp += 2;
str_del(f->sp->u.string);
PUT_STR(f->sp, str);
return 0;
}
# endif
# ifdef FUNCDEF
FUNCDEF("asn_rshift", kf_asn_rshift, pt_asn_rshift, 0)
# else
char pt_asn_rshift[] = { C_TYPECHECKED | C_STATIC, 2, 0, 0, 8, T_STRING,
T_STRING, T_INT };
/*
* NAME: kfun->asn_rshift()
* DESCRIPTION: right shift of arbitrary precision number
*/
int kf_asn_rshift(f)
register frame *f;
{
string *str;
str = asn_rshift(f, f->sp[1].u.string, f->sp->u.number);
f->sp++;
str_del(f->sp->u.string);
PUT_STR(f->sp, str);
return 0;
}
# endif
# ifdef FUNCDEF
FUNCDEF("asn_and", kf_asn_and, pt_asn_and, 0)
# else
char pt_asn_and[] = { C_TYPECHECKED | C_STATIC, 2, 0, 0, 8, T_STRING, T_STRING,
T_STRING };
/*
* NAME: kfun->asn_and()
* DESCRIPTION: logical and of arbitrary precision numbers
*/
int kf_asn_and(f)
register frame *f;
{
string *str;
str = asn_and(f, f->sp[1].u.string, f->sp->u.string);
str_del((f->sp++)->u.string);
str_del(f->sp->u.string);
PUT_STR(f->sp, str);
return 0;
}
# endif
# ifdef FUNCDEF
FUNCDEF("asn_or", kf_asn_or, pt_asn_or, 0)
# else
char pt_asn_or[] = { C_TYPECHECKED | C_STATIC, 2, 0, 0, 8, T_STRING, T_STRING,
T_STRING };
/*
* NAME: kfun->asn_or()
* DESCRIPTION: logical or of arbitrary precision numbers
*/
int kf_asn_or(f)
register frame *f;
{
string *str;
str = asn_or(f, f->sp[1].u.string, f->sp->u.string);
str_del((f->sp++)->u.string);
str_del(f->sp->u.string);
PUT_STR(f->sp, str);
return 0;
}
# endif
# ifdef FUNCDEF
FUNCDEF("asn_xor", kf_asn_xor, pt_asn_xor, 0)
# else
char pt_asn_xor[] = { C_TYPECHECKED | C_STATIC, 2, 0, 0, 8, T_STRING, T_STRING,
T_STRING };
/*
* NAME: kfun->asn_xor()
* DESCRIPTION: logical xor of arbitrary precision numbers
*/
int kf_asn_xor(f)
register frame *f;
{
string *str;
str = asn_xor(f, f->sp[1].u.string, f->sp->u.string);
str_del((f->sp++)->u.string);
str_del(f->sp->u.string);
PUT_STR(f->sp, str);
return 0;
}
# endif