2 * func - built-in functions implemented here
4 * Copyright (C) 1999-2007 David I. Bell, Landon Curt Noll and Ernest Bowen
6 * Primary author: David I. Bell
8 * Calc is open software; you can redistribute it and/or modify it under
9 * the terms of the version 2.1 of the GNU Lesser General Public License
10 * as published by the Free Software Foundation.
12 * Calc is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
15 * Public License for more details.
17 * A copy of version 2.1 of the GNU Lesser General Public License is
18 * distributed with calc under the filename COPYING-LGPL. You should have
19 * received a copy with calc; if not, write to Free Software Foundation, Inc.
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 * @(#) $Revision: 30.4 $
23 * @(#) $Id: func.c,v 30.4 2013/08/11 08:41:38 chongo Exp $
24 * @(#) $Source: /usr/local/src/bin/calc/RCS/func.c,v $
26 * Under source code control: 1990/02/15 01:48:15
27 * File existed as early as: before 1990
29 * Share and enjoy! :-) http://www.isthe.com/chongo/tech/comp/calc/
35 #include <sys/types.h>
41 # define _access access
46 #define CONST /* disabled for FUNCLIST in case NATIVE_CC doesn't have it */
55 #include "have_unistd.h"
56 #if defined(HAVE_UNISTD_H)
60 #include "have_stdlib.h"
61 #if defined(HAVE_STDLIB_H)
65 #include "have_string.h"
66 #if defined(HAVE_STRING_H)
70 #include "have_times.h"
71 #if defined(HAVE_TIME_H)
75 #if defined(HAVE_TIMES_H)
79 #if defined(HAVE_SYS_TIME_H)
83 #if defined(HAVE_SYS_TIMES_H)
84 #include <sys/times.h>
87 #include "have_strdup.h"
88 #if !defined(HAVE_STRDUP)
89 # define strdup(x) calc_strdup((CONST char *)(x))
92 #include "have_rusage.h"
93 #if defined(HAVE_GETRUSAGE)
94 # include <sys/resource.h>
97 #include "have_const.h"
98 #include "have_unused.h"
113 # define E_CUSTOM_ERROR E_NO_C_ARG
115 # define E_CUSTOM_ERROR E_NO_CUSTOM
120 * forward declarations
122 S_FUNC NUMBER
*base_value(long mode
, int defval
);
123 S_FUNC
int strscan(char *s
, int count
, VALUE
**vals
);
124 S_FUNC
int filescan(FILEID id
, int count
, VALUE
**vals
);
125 S_FUNC VALUE
f_eval(VALUE
*vp
);
126 S_FUNC VALUE
f_fsize(VALUE
*vp
);
127 S_FUNC
int malloced_putenv(char *str
);
132 * external declarations
134 EXTERN
char cmdbuf
[]; /* command line expression */
135 EXTERN CONST
char *error_table
[E__COUNT
+2]; /* calc coded error messages */
136 E_FUNC
void matrandperm(MATRIX
*M
);
137 E_FUNC
void listrandperm(LIST
*lp
);
138 E_FUNC
int idungetc(FILEID id
, int ch
);
139 E_FUNC LIST
* associndices(ASSOC
*ap
, long index
);
140 E_FUNC LIST
* matindices(MATRIX
*mp
, long index
);
144 * malloced environment storage
146 #define ENV_POOL_CHUNK 10 /* env_pool elements to allocate at a time */
148 char *getenv
; /* what getenv() would return, NULL => unused */
149 char *putenv
; /* pointer given to putenv() */
151 STATIC
int env_pool_cnt
= 0; /* number of env_pool elements in use */
152 STATIC
int env_pool_max
= 0; /* number of env_pool elements allocated */
153 STATIC
struct env_pool
*e_pool
= NULL
; /* env_pool elements */
157 * user-defined error strings
159 STATIC
short nexterrnum
= E_USERDEF
;
160 STATIC STRINGHEAD newerrorstr
;
162 #endif /* !FUNCLIST */
166 * arg count definitions
168 #define IN 1024 /* maximum number of arguments */
169 #define FE 0x01 /* flag to indicate default epsilon argument */
170 #define FA 0x02 /* preserve addresses of variables */
174 * builtins - List of primitive built-in functions
177 char *b_name
; /* name of built-in function */
178 short b_minargs
; /* minimum number of arguments */
179 short b_maxargs
; /* maximum number of arguments */
180 short b_flags
; /* special handling flags */
181 short b_opcode
; /* opcode which makes the call quick */
182 NUMBER
*(*b_numfunc
)(); /* routine to calculate numeric function */
183 VALUE (*b_valfunc
)(); /* routine to calculate general values */
184 char *b_desc
; /* description of function */
188 #if !defined(FUNCLIST)
198 long temp_stoponerror
; /* temp value of stoponerror */
200 if (vp
->v_type
!= V_STR
)
201 return error_value(E_EVAL2
);
202 str
= vp
->v_str
->s_str
;
203 num
= vp
->v_str
->s_len
;
204 switch (openstring(str
, num
)) {
206 return error_value(E_EVAL3
);
208 return error_value(E_EVAL4
);
212 temp_stoponerror
= stoponerror
;
214 if (evaluate(TRUE
)) {
215 stoponerror
= temp_stoponerror
;
221 result
= newfunc
->f_savedvalue
;
222 newfunc
->f_savedvalue
.v_type
= V_NULL
;
223 newfunc
->f_savedvalue
.v_subtype
= V_NOSUBTYPE
;
224 freenumbers(newfunc
);
225 if (newfunc
!= oldfunc
)
229 stoponerror
= temp_stoponerror
;
234 freevalue(&newfunc
->f_savedvalue
);
235 newfunc
->f_savedvalue
.v_type
= V_NULL
;
236 newfunc
->f_savedvalue
.v_subtype
= V_NOSUBTYPE
;
237 freenumbers(newfunc
);
238 if (newfunc
!= oldfunc
)
240 return error_value(E_EVAL
);
252 /* initialize VALUE */
253 result
.v_type
= V_STR
;
254 result
.v_subtype
= V_NOSUBTYPE
;
257 printvalue(vp
, PRINT_SHORT
);
262 result
.v_type
= V_NULL
;
266 result
.v_str
= slink(&_nullstring_
);
270 newcp
= (char *) malloc(len
+ 1);
272 math_error("Cannot allocate string");
275 strncpy(newcp
, cp
, len
+1);
276 result
.v_str
= makestring(newcp
);
282 f_display(int count
, VALUE
**vals
)
287 /* initialize VALUE */
289 res
.v_subtype
= V_NOSUBTYPE
;
291 oldvalue
= conf
->outdigits
;
294 if (vals
[0]->v_type
!= V_NUM
|| qisfrac(vals
[0]->v_num
) ||
295 qisneg(vals
[0]->v_num
) || zge31b(vals
[0]->v_num
->num
))
297 "Out-of-range arg for display ignored\n");
299 conf
->outdigits
= (LEN
) qtoi(vals
[0]->v_num
);
301 res
.v_num
= itoq((long) oldvalue
);
308 f_null(int UNUSED count
, VALUE UNUSED
**vals
)
312 /* initialize VALUE */
314 res
.v_subtype
= V_NOSUBTYPE
;
326 /* initialize VALUE */
327 result
.v_type
= V_STR
;
328 result
.v_subtype
= V_NOSUBTYPE
;
330 switch (vp
->v_type
) {
332 result
.v_str
= makenewstring(vp
->v_str
->s_str
);
335 result
.v_str
= slink(&_nullstring_
);
338 result
.v_str
= charstring(*vp
->v_octet
);
342 qprintnum(vp
->v_num
, MODE_DEFAULT
);
343 cp
= math_getdivertedio();
344 result
.v_str
= makestring(cp
);
349 cp
= math_getdivertedio();
350 result
.v_str
= makestring(cp
);
353 return error_value(E_STR
);
365 /* initialize result */
366 result
.v_type
= V_STR
;
367 result
.v_subtype
= V_NOSUBTYPE
;
371 cp
= math_getdivertedio();
372 result
.v_str
= makestring(cp
);
384 /* initialize VALUE */
385 result
.v_type
= V_STR
;
386 result
.v_subtype
= V_NOSUBTYPE
;
388 switch (vp
->v_type
) {
390 result
.v_type
= V_STR
;
391 result
.v_str
= makenewstring(vp
->v_nblock
->name
);
394 name
= findfname(vp
->v_file
);
396 result
.v_type
= V_NULL
;
401 cp
= math_getdivertedio();
404 result
.v_type
= V_NULL
;
407 result
.v_str
= makestring(cp
);
414 f_poly(int count
, VALUE
**vals
)
420 /* initialize VALUEs */
421 result
.v_subtype
= V_NOSUBTYPE
;
422 tmp
.v_subtype
= V_NOSUBTYPE
;
424 if (vals
[0]->v_type
== V_LIST
) {
425 clist
= vals
[0]->v_list
;
427 while (--count
> 0) {
428 if ((*++vals
)->v_type
== V_LIST
)
429 insertitems(lp
, (*vals
)->v_list
);
431 insertlistlast(lp
, *vals
);
433 if (!evalpoly(clist
, lp
->l_first
, &result
)) {
434 result
.v_type
= V_NUM
;
435 result
.v_num
= qlink(&_qzero_
);
441 copyvalue(*vals
++, &result
);
442 while (--count
> 0) {
443 mulvalue(&result
, x
, &tmp
);
445 addvalue(*vals
++, &tmp
, &result
);
453 f_mne(NUMBER
*val1
, NUMBER
*val2
, NUMBER
*val3
)
457 tmp
= qsub(val1
, val2
);
458 res
= itoq((long) !qdivides(tmp
, val3
));
465 f_isrel(NUMBER
*val1
, NUMBER
*val2
)
467 if (qisfrac(val1
) || qisfrac(val2
)) {
468 math_error("Non-integer for isrel");
471 return itoq((long) zrelprime(val1
->num
, val2
->num
));
476 f_issquare(NUMBER
*vp
)
478 return itoq((long) qissquare(vp
));
483 f_isprime(int count
, NUMBER
**vals
)
485 NUMBER
*err
; /* error return, NULL => use math_error */
487 /* determine the way we report problems */
489 if (qisfrac(vals
[1])) {
490 math_error("2nd isprime arg must be an integer");
498 /* firewall - must be an integer */
499 if (qisfrac(vals
[0])) {
503 math_error("non-integral arg for builtin function isprime");
507 /* test the integer */
508 switch (zisprime(vals
[0]->num
)) {
509 case 0: return qlink(&_qzero_
);
510 case 1: return qlink(&_qone_
);
515 math_error("isprime argument is an odd value > 2^32");
523 f_nprime(int count
, NUMBER
**vals
)
525 NUMBER
*err
; /* error return, NULL => use math_error */
526 FULL nxt_prime
; /* next prime or 0 */
528 /* determine the way we report problems */
530 if (qisfrac(vals
[1])) {
531 math_error("2nd nextprime arg must be an integer");
539 /* firewall - must be an integer */
540 if (qisfrac(vals
[0])) {
544 math_error("non-integral arg 1 for builtin function nextprime");
548 /* test the integer */
549 nxt_prime
= znprime(vals
[0]->num
);
551 return utoq(nxt_prime
);
552 } else if (nxt_prime
== 0) {
554 return qlink(&_nxtprime_
);
559 math_error("nextprime arg 1 is >= 2^32");
567 f_pprime(int count
, NUMBER
**vals
)
569 NUMBER
*err
; /* error return, NULL => use math_error */
570 FULL prev_prime
; /* previous prime or 0 */
572 /* determine the way we report problems */
574 if (qisfrac(vals
[1])) {
575 math_error("2nd prevprime arg must be an integer");
583 /* firewall - must be an integer */
584 if (qisfrac(vals
[0])) {
588 math_error("non-integral arg 1 for builtin function prevprime");
592 /* test the integer */
593 prev_prime
= zpprime(vals
[0]->num
);
594 if (prev_prime
> 1) {
595 return utoq(prev_prime
);
597 if (prev_prime
== 0) {
598 return qlink(&_qzero_
);
602 if (prev_prime
== 0) {
603 math_error("prevprime arg 1 is <= 2");
606 math_error("prevprime arg 1 is >= 2^32");
615 f_factor(int count
, NUMBER
**vals
)
617 NUMBER
*err
; /* error return, NULL => use math_error */
618 ZVALUE limit
; /* highest prime factor in search */
619 ZVALUE n
; /* number to factor */
620 NUMBER
*factor
; /* the prime factor found */
621 int res
; /* -1 => error, 0 => not found, 1 => factor found */
627 if (qisfrac(vals
[2])) {
628 math_error("3rd factor arg must be an integer");
636 if (qisfrac(vals
[1])) {
640 math_error("non-integral arg 2 for builtin factor");
643 limit
= vals
[1]->num
;
645 /* default limit is 2^32-1 */
646 utoz((FULL
)0xffffffff, &limit
);
648 if (qisfrac(vals
[0])) {
654 math_error("non-integral arg 1 for builtin pfactor");
660 * find the smallest prime factor in the range
663 res
= zfactor(n
, limit
, &(factor
->num
));
665 /* error processing */
669 math_error("limit >= 2^32 for builtin factor");
671 } else if (res
== 0) {
674 /* no factor found - qalloc set factor to 1, return 1 */
679 * return the factor found
688 f_pix(int count
, NUMBER
**vals
)
690 NUMBER
*err
; /* error return, NULL => use math_error */
691 long value
; /* primes <= x, or 0 ==> error */
693 /* determine the way we report problems */
695 if (qisfrac(vals
[1])) {
696 math_error("2nd pix arg must be an integer");
704 /* firewall - must be an integer */
705 if (qisfrac(vals
[0])) {
709 math_error("non-integral arg 1 for builtin function pix");
713 /* determine the number of primes <= x */
714 value
= zpix(vals
[0]->num
);
721 math_error("pix arg 1 is >= 2^32");
729 f_prevcand(int count
, NUMBER
**vals
)
734 ZVALUE
*zcount
= NULL
; /* ptest trial count */
736 NUMBER
*ans
; /* candidate for primality */
742 * check on the number of args passed and that args passed are ints
746 if (!qisint(vals
[4])) {
747 math_error( "prevcand 5th arg must both be integer");
750 zmodulus
= vals
[4]->num
;
753 if (!qisint(vals
[3])) {
754 math_error( "prevcand 4th arg must both be integer");
757 zresidue
= vals
[3]->num
;
760 if (!qisint(vals
[2])) {
762 "prevcand skip arg (3rd) must be an integer or omitted");
765 zskip
= vals
[2]->num
;
768 if (!qisint(vals
[1])) {
770 "prevcand count arg (2nd) must be an integer or omitted");
773 zcount
= &vals
[1]->num
;
776 if (!qisint(vals
[0])) {
778 "prevcand search arg (1st) must be an integer");
783 math_error("invalid number of args passed to prevcand");
787 if (zcount
== NULL
) {
788 count
= 1; /* default is 1 ptest */
790 if (zge24b(*zcount
)) {
791 math_error("prevcand count arg (2nd) must be < 2^24");
794 count
= ztoi(*zcount
);
800 if (zprevcand(vals
[0]->num
, count
, zskip
, zresidue
, zmodulus
, &tmp
)) {
805 return qlink(&_qzero_
);
810 f_nextcand(int count
, NUMBER
**vals
)
815 ZVALUE
*zcount
= NULL
; /* ptest trial count */
817 NUMBER
*ans
; /* candidate for primality */
823 * check on the number of args passed and that args passed are ints
827 if (!qisint(vals
[4])) {
829 "nextcand 5th args must be integer");
832 zmodulus
= vals
[4]->num
;
835 if (!qisint(vals
[3])) {
837 "nextcand 5th args must be integer");
840 zresidue
= vals
[3]->num
;
843 if (!qisint(vals
[2])) {
845 "nextcand skip arg (3rd) must be an integer or omitted");
848 zskip
= vals
[2]->num
;
851 if (!qisint(vals
[1])) {
853 "nextcand count arg (2nd) must be an integer or omitted");
856 zcount
= &vals
[1]->num
;
859 if (!qisint(vals
[0])) {
861 "nextcand search arg (1st) must be an integer");
866 math_error("invalid number of args passed to nextcand");
871 * check ranges on integers passed
873 if (zcount
== NULL
) {
874 count
= 1; /* default is 1 ptest */
876 if (zge24b(*zcount
)) {
877 math_error("prevcand count arg (2nd) must be < 2^24");
880 count
= ztoi(*zcount
);
886 if (znextcand(vals
[0]->num
, count
, zskip
, zresidue
, zmodulus
, &tmp
)) {
891 return qlink(&_qzero_
);
898 return pseudo_seed();
903 f_rand(int count
, NUMBER
**vals
)
909 case 0: /* rand() == rand(2^64) */
910 /* generate an a55 random number */
912 zrand(SBITS
, &ans
->num
);
915 case 1: /* rand(limit) */
916 if (!qisint(vals
[0])) {
917 math_error("rand limit must be an integer");
920 if (zislezero(vals
[0]->num
)) {
921 math_error("rand limit must > 0");
925 zrandrange(_zero_
, vals
[0]->num
, &ans
->num
);
928 case 2: /* rand(low, limit) */
930 if (!qisint(vals
[0]) || !qisint(vals
[1])) {
931 math_error("rand range must be integers");
935 zrandrange(vals
[0]->num
, vals
[1]->num
, &ans
->num
);
939 math_error("invalid number of args passed to rand");
944 /* return the a55 random number */
950 f_randbit(int count
, NUMBER
**vals
)
954 long cnt
; /* bits needed or skipped */
959 ans
= ziszero(ztmp
) ? qlink(&_qzero_
) : qlink(&_qone_
);
967 if (!qisint(vals
[0])) {
968 math_error("rand bit count must be an integer");
971 if (zge31b(vals
[0]->num
)) {
972 math_error("huge rand bit count");
977 * generate an a55 random number or skip random bits
980 cnt
= ztolong(vals
[0]->num
);
981 if (zisneg(vals
[0]->num
)) {
984 itoz(cnt
, &ans
->num
);
987 zrand(cnt
, &ans
->num
);
991 * return the a55 random number
998 f_srand(int count
, VALUE
**vals
)
1002 /* initialize VALUE */
1003 result
.v_type
= V_RAND
;
1004 result
.v_subtype
= V_NOSUBTYPE
;
1009 /* get the current a55 state */
1010 result
.v_rand
= zsrand(NULL
, NULL
);
1014 switch (vals
[0]->v_type
) {
1015 case V_NUM
: /* srand(seed) */
1016 /* seed a55 and return previous state */
1017 if (!qisint(vals
[0]->v_num
)) {
1019 "srand number seed must be an integer");
1022 result
.v_rand
= zsrand(&vals
[0]->v_num
->num
, NULL
);
1025 case V_RAND
: /* srand(state) */
1026 /* set a55 state and return previous state */
1027 result
.v_rand
= zsetrand(vals
[0]->v_rand
);
1031 /* load additive 55 table and return previous state */
1032 result
.v_rand
= zsrand(NULL
, vals
[0]->v_mat
);
1036 math_error("illegal type of arg passed to srand()");
1043 math_error("bad arg count to srand()");
1048 /* return the current state */
1054 f_random(int count
, NUMBER
**vals
)
1060 case 0: /* random() == random(2^64) */
1061 /* generate a Blum-Blum-Shub random number */
1063 zrandom(SBITS
, &ans
->num
);
1066 case 1: /* random(limit) */
1067 if (!qisint(vals
[0])) {
1068 math_error("random limit must be an integer");
1071 if (zislezero(vals
[0]->num
)) {
1072 math_error("random limit must > 0");
1076 zrandomrange(_zero_
, vals
[0]->num
, &ans
->num
);
1079 case 2: /* random(low, limit) */
1081 if (!qisint(vals
[0]) || !qisint(vals
[1])) {
1082 math_error("random range must be integers");
1086 zrandomrange(vals
[0]->num
, vals
[1]->num
, &ans
->num
);
1090 math_error("invalid number of args passed to random");
1095 /* return the Blum-Blum-Shub random number */
1101 f_randombit(int count
, NUMBER
**vals
)
1105 long cnt
; /* bits needed or skipped */
1110 ans
= ziszero(ztmp
) ? qlink(&_qzero_
) : qlink(&_qone_
);
1118 if (!qisint(vals
[0])) {
1119 math_error("random bit count must be an integer");
1122 if (zge31b(vals
[0]->num
)) {
1123 math_error("huge random bit count");
1128 * generate a Blum-Blum-Shub random number or skip random bits
1131 cnt
= ztolong(vals
[0]->num
);
1132 if (zisneg(vals
[0]->num
)) {
1135 itoz(cnt
, &ans
->num
);
1138 zrandom(cnt
, &ans
->num
);
1142 * return the Blum-Blum-Shub random number
1149 f_srandom(int count
, VALUE
**vals
)
1153 /* initialize VALUE */
1154 result
.v_type
= V_RANDOM
;
1155 result
.v_subtype
= V_NOSUBTYPE
;
1159 case 0: /* srandom() */
1160 /* get the current random state */
1161 result
.v_random
= zsetrandom(NULL
);
1164 case 1: /* srandom(seed) or srandom(state) */
1165 switch (vals
[0]->v_type
) {
1166 case V_NUM
: /* srand(seed) */
1167 /* seed Blum and return previous state */
1168 if (!qisint(vals
[0]->v_num
)) {
1170 "srandom number seed must be an integer");
1173 result
.v_random
= zsrandom1(vals
[0]->v_num
->num
, TRUE
);
1176 case V_RANDOM
: /* srandom(state) */
1177 /* set a55 state and return previous state */
1178 result
.v_random
= zsetrandom(vals
[0]->v_random
);
1182 math_error("illegal type of arg passed to srandom()");
1188 case 2: /* srandom(seed, newn) */
1189 if (vals
[0]->v_type
!= V_NUM
|| !qisint(vals
[0]->v_num
)) {
1190 math_error("srandom seed must be an integer");
1193 if (vals
[1]->v_type
!= V_NUM
|| !qisint(vals
[1]->v_num
)) {
1194 math_error("srandom Blum modulus must be an integer");
1197 result
.v_random
= zsrandom2(vals
[0]->v_num
->num
,
1198 vals
[1]->v_num
->num
);
1201 case 4: /* srandom(seed, ip, iq, trials) */
1202 if (vals
[0]->v_type
!= V_NUM
|| !qisint(vals
[0]->v_num
)) {
1203 math_error("srandom seed must be an integer");
1206 if (vals
[1]->v_type
!= V_NUM
|| !qisint(vals
[1]->v_num
)) {
1207 math_error("srandom 2nd arg must be an integer");
1210 if (vals
[2]->v_type
!= V_NUM
|| !qisint(vals
[2]->v_num
)) {
1211 math_error("srandom 3rd arg must be an integer");
1214 if (vals
[3]->v_type
!= V_NUM
|| !qisint(vals
[3]->v_num
)) {
1215 math_error("srandom 4th arg must be an integer");
1218 if (zge24b(vals
[3]->v_num
->num
)) {
1219 math_error("srandom trials count is excessive");
1222 result
.v_random
= zsrandom4(vals
[0]->v_num
->num
,
1223 vals
[1]->v_num
->num
,
1224 vals
[2]->v_num
->num
,
1225 ztoi(vals
[3]->v_num
->num
));
1229 math_error("bad arg count to srandom()");
1234 /* return the current state */
1240 f_primetest(int count
, NUMBER
**vals
)
1244 case 1: return itoq((long) qprimetest(vals
[0],
1245 qlink(&_qone_
), qlink(&_qone_
)));
1246 case 2: return itoq((long) qprimetest(vals
[0],
1247 vals
[1], qlink(&_qone_
)));
1248 default: return itoq((long) qprimetest(vals
[0], vals
[1], vals
[2]));
1254 f_setbit(int count
, VALUE
**vals
)
1260 /* initialize VALUE */
1261 result
.v_type
= V_NULL
;
1262 result
.v_subtype
= V_NOSUBTYPE
;
1264 r
= (count
== 3) ? testvalue(vals
[2]) : 1;
1266 if (vals
[1]->v_type
!= V_NUM
|| qisfrac(vals
[1]->v_num
))
1267 return error_value(E_SETBIT1
);
1268 if (zge31b(vals
[1]->v_num
->num
))
1269 return error_value(E_SETBIT2
);
1270 if (vals
[0]->v_type
!= V_STR
)
1271 return error_value(E_SETBIT3
);
1272 index
= qtoi(vals
[1]->v_num
);
1273 if (stringsetbit(vals
[0]->v_str
, index
, r
))
1274 return error_value(E_SETBIT2
);
1280 f_digit(int count
, VALUE
**vals
)
1285 if (vals
[0]->v_type
!= V_NUM
)
1286 return error_value(E_DGT1
);
1288 if (vals
[1]->v_type
!= V_NUM
|| qisfrac(vals
[1]->v_num
))
1289 return error_value(E_DGT2
);
1292 if (vals
[2]->v_type
!= V_NUM
|| qisfrac(vals
[2]->v_num
))
1293 return error_value(E_DGT3
);
1294 base
= vals
[2]->v_num
->num
;
1299 res
.v_num
= qdigit(vals
[0]->v_num
, vals
[1]->v_num
->num
, base
);
1300 if (res
.v_num
== NULL
)
1301 return error_value(E_DGT3
);
1308 f_digits(int count
, VALUE
**vals
)
1313 if (vals
[0]->v_type
!= V_NUM
)
1314 return error_value(E_DGTS1
);
1316 if (vals
[1]->v_type
!= V_NUM
|| qisfrac(vals
[1]->v_num
)
1317 || qiszero(vals
[1]->v_num
) || qisunit(vals
[1]->v_num
))
1318 return error_value(E_DGTS2
);
1319 base
= vals
[1]->v_num
->num
;
1324 res
.v_num
= itoq(qdigits(vals
[0]->v_num
, base
));
1330 f_places(int count
, VALUE
**vals
)
1335 if (vals
[0]->v_type
!= V_NUM
)
1336 return error_value(E_PLCS1
);
1338 if (vals
[1]->v_type
!= V_NUM
|| qisfrac(vals
[1]->v_num
))
1339 return error_value(E_PLCS2
);
1340 places
= qplaces(vals
[0]->v_num
, vals
[1]->v_num
->num
);
1342 return error_value(E_PLCS2
);
1344 places
= qdecplaces(vals
[0]->v_num
);
1347 res
.v_num
= itoq(places
);
1353 f_popcnt(int count
, NUMBER
**vals
)
1360 if (count
== 2 && qiszero(vals
[1])) {
1367 if (qisint(vals
[0])) {
1368 return itoq(zpopcnt(vals
[0]->num
, bitval
));
1370 return itoq(zpopcnt(vals
[0]->num
, bitval
) +
1371 zpopcnt(vals
[0]->den
, bitval
));
1377 f_xor(int count
, VALUE
**vals
)
1385 type
= vals
[0]->v_type
;
1386 result
.v_type
= type
;
1387 result
.v_subtype
= vals
[0]->v_subtype
;
1388 for (i
= 1; i
< count
; i
++) {
1389 if (vals
[i
]->v_type
!= type
)
1390 return error_value(E_XOR1
);
1394 q
= qlink(vals
[0]->v_num
);
1395 for (i
= 1; i
< count
; i
++) {
1396 qtmp
= qxor(q
, vals
[i
]->v_num
);
1403 s
= slink(vals
[0]->v_str
);
1404 for (i
= 1; i
< count
; i
++) {
1405 stmp
= stringxor(s
, vals
[i
]->v_str
);
1412 return error_value(E_XOR2
);
1419 minlistitems(LIST
*lp
)
1427 /* initialize VALUEs */
1428 min
.v_type
= V_NULL
;
1429 min
.v_subtype
= V_NOSUBTYPE
;
1430 term
.v_type
= V_NULL
;
1431 term
.v_subtype
= V_NOSUBTYPE
;
1433 for (ep
= lp
->l_first
; ep
; ep
= ep
->e_next
) {
1435 switch(vp
->v_type
) {
1437 term
= minlistitems(vp
->v_list
);
1440 term
= objcall(OBJ_MIN
, vp
,
1441 NULL_VALUE
, NULL_VALUE
);
1444 copyvalue(vp
, &term
);
1446 if (min
.v_type
== V_NULL
) {
1450 if (term
.v_type
== V_NULL
)
1452 relvalue(&term
, &min
, &rel
);
1453 if (rel
.v_type
!= V_NUM
) {
1457 return error_value(E_LISTMIN
);
1459 if (qisneg(rel
.v_num
)) {
1472 maxlistitems(LIST
*lp
)
1480 /* initialize VALUEs */
1481 max
.v_type
= V_NULL
;
1482 max
.v_subtype
= V_NOSUBTYPE
;
1483 term
.v_type
= V_NULL
;
1484 term
.v_subtype
= V_NOSUBTYPE
;
1486 for (ep
= lp
->l_first
; ep
; ep
= ep
->e_next
) {
1488 switch(vp
->v_type
) {
1490 term
= maxlistitems(vp
->v_list
);
1493 term
= objcall(OBJ_MAX
, vp
,
1494 NULL_VALUE
, NULL_VALUE
);
1497 copyvalue(vp
, &term
);
1499 if (max
.v_type
== V_NULL
) {
1503 if (term
.v_type
== V_NULL
)
1505 relvalue(&max
, &term
, &rel
);
1506 if (rel
.v_type
!= V_NUM
) {
1510 return error_value(E_LISTMAX
);
1512 if (qisneg(rel
.v_num
)) {
1525 f_min(int count
, VALUE
**vals
)
1532 /* initialize VALUEs */
1533 min
.v_type
= V_NULL
;
1534 min
.v_subtype
= V_NOSUBTYPE
;
1535 term
.v_type
= V_NULL
;
1536 term
.v_subtype
= V_NOSUBTYPE
;
1538 while (count
-- > 0) {
1540 switch(vp
->v_type
) {
1542 term
= minlistitems(vp
->v_list
);
1545 term
= objcall(OBJ_MIN
, vp
,
1546 NULL_VALUE
, NULL_VALUE
);
1549 copyvalue(vp
, &term
);
1551 if (min
.v_type
== V_NULL
) {
1555 if (term
.v_type
== V_NULL
)
1557 if (term
.v_type
< 0) {
1561 relvalue(&term
, &min
, &rel
);
1562 if (rel
.v_type
!= V_NUM
) {
1566 return error_value(E_MIN
);
1568 if (qisneg(rel
.v_num
)) {
1581 f_max(int count
, VALUE
**vals
)
1588 /* initialize VALUEs */
1589 max
.v_type
= V_NULL
;
1590 max
.v_subtype
= V_NOSUBTYPE
;
1591 term
.v_type
= V_NULL
;
1592 term
.v_subtype
= V_NOSUBTYPE
;
1594 while (count
-- > 0) {
1596 switch(vp
->v_type
) {
1598 term
= maxlistitems(vp
->v_list
);
1601 term
= objcall(OBJ_MAX
, vp
,
1602 NULL_VALUE
, NULL_VALUE
);
1605 copyvalue(vp
, &term
);
1607 if (max
.v_type
== V_NULL
) {
1611 if (term
.v_type
== V_NULL
)
1613 if (term
.v_type
< 0) {
1617 relvalue(&max
, &term
, &rel
);
1618 if (rel
.v_type
!= V_NUM
) {
1622 return error_value(E_MAX
);
1624 if (qisneg(rel
.v_num
)) {
1637 f_gcd(int count
, NUMBER
**vals
)
1642 while (--count
> 0) {
1643 tmp
= qgcd(val
, *++vals
);
1652 f_lcm(int count
, NUMBER
**vals
)
1657 while (--count
> 0) {
1658 tmp
= qlcm(val
, *++vals
);
1669 f_hash(int count
, VALUE
**vals
)
1674 /* initialize VALUE */
1675 result
.v_type
= V_NUM
;
1676 result
.v_subtype
= V_NOSUBTYPE
;
1678 hash
= FNV1_32_BASIS
;
1680 hash
= hashvalue(*vals
++, hash
);
1681 result
.v_num
= utoq((FULL
) hash
);
1687 sumlistitems(LIST
*lp
)
1695 /* initialize VALUEs */
1696 term
.v_type
= V_NULL
;
1697 term
.v_subtype
= V_NOSUBTYPE
;
1698 tmp
.v_type
= V_NULL
;
1699 tmp
.v_subtype
= V_NOSUBTYPE
;
1700 sum
.v_type
= V_NULL
;
1701 sum
.v_subtype
= V_NOSUBTYPE
;
1703 for (ep
= lp
->l_first
; ep
; ep
= ep
->e_next
) {
1705 switch(vp
->v_type
) {
1707 term
= sumlistitems(vp
->v_list
);
1710 term
= objcall(OBJ_SUM
, vp
,
1711 NULL_VALUE
, NULL_VALUE
);
1714 addvalue(&sum
, vp
, &tmp
);
1721 addvalue(&sum
, &term
, &tmp
);
1733 f_sum(int count
, VALUE
**vals
)
1740 /* initialize VALUEs */
1741 tmp
.v_type
= V_NULL
;
1742 tmp
.v_subtype
= V_NOSUBTYPE
;
1743 sum
.v_type
= V_NULL
;
1744 sum
.v_subtype
= V_NOSUBTYPE
;
1745 term
.v_type
= V_NULL
;
1746 term
.v_subtype
= V_NOSUBTYPE
;
1747 while (count
-- > 0) {
1749 switch(vp
->v_type
) {
1751 term
= sumlistitems(vp
->v_list
);
1754 term
= objcall(OBJ_SUM
, vp
,
1755 NULL_VALUE
, NULL_VALUE
);
1758 addvalue(&sum
, vp
, &tmp
);
1765 addvalue(&sum
, &term
, &tmp
);
1777 f_avg(int count
, VALUE
**vals
)
1784 /* initialize VALUEs */
1785 tmp
.v_type
= V_NULL
;
1786 tmp
.v_subtype
= V_NOSUBTYPE
;
1787 sum
.v_type
= V_NULL
;
1788 sum
.v_subtype
= V_NOSUBTYPE
;
1789 div
.v_type
= V_NULL
;
1790 div
.v_subtype
= V_NOSUBTYPE
;
1793 while (count
-- > 0) {
1794 if ((*vals
)->v_type
== V_LIST
) {
1795 addlistitems((*vals
)->v_list
, &sum
);
1796 n
+= countlistitems((*vals
++)->v_list
);
1798 addvalue(&sum
, *vals
++, &tmp
);
1808 div
.v_num
= itoq(n
);
1810 div
.v_subtype
= V_NOSUBTYPE
;
1811 divvalue(&sum
, &div
, &tmp
);
1823 /* initialize VALUE */
1825 res
.v_subtype
= V_NOSUBTYPE
;
1827 if (vp
->v_type
== V_OBJ
) {
1828 return objcall(OBJ_FACT
, vp
, NULL_VALUE
, NULL_VALUE
);
1830 if (vp
->v_type
!= V_NUM
) {
1831 math_error("Non-real argument for fact()");
1834 res
.v_num
= qfact(vp
->v_num
);
1840 f_hmean(int count
, VALUE
**vals
)
1842 VALUE sum
, tmp1
, tmp2
;
1845 /* initialize VALUEs */
1846 sum
.v_type
= V_NULL
;
1847 sum
.v_subtype
= V_NOSUBTYPE
;
1848 tmp1
.v_type
= V_NULL
;
1849 tmp1
.v_subtype
= V_NOSUBTYPE
;
1850 tmp2
.v_type
= V_NULL
;
1851 tmp2
.v_subtype
= V_NOSUBTYPE
;
1853 while (count
-- > 0) {
1854 if ((*vals
)->v_type
== V_LIST
) {
1855 addlistinv((*vals
)->v_list
, &sum
);
1856 n
+= countlistitems((*vals
++)->v_list
);
1858 invertvalue(*vals
++, &tmp1
);
1859 addvalue(&sum
, &tmp1
, &tmp2
);
1868 tmp1
.v_type
= V_NUM
;
1869 tmp1
.v_subtype
= V_NOSUBTYPE
;
1870 tmp1
.v_num
= itoq(n
);
1871 divvalue(&tmp1
, &sum
, &tmp2
);
1879 f_hnrmod(NUMBER
*val1
, NUMBER
*val2
, NUMBER
*val3
, NUMBER
*val4
)
1881 ZVALUE answer
; /* v mod h*2^n+r */
1882 NUMBER
*res
; /* v mod h*2^n+r */
1887 if (qisfrac(val1
)) {
1888 math_error("1st arg of hnrmod (v) must be an integer");
1891 if (qisfrac(val2
) || qisneg(val2
) || qiszero(val2
)) {
1892 math_error("2nd arg of hnrmod (h) must be an integer > 0");
1895 if (qisfrac(val3
) || qisneg(val3
) || qiszero(val3
)) {
1896 math_error("3rd arg of hnrmod (n) must be an integer > 0");
1899 if (qisfrac(val4
) || !zisabsleone(val4
->num
)) {
1900 math_error("4th arg of hnrmod (r) must be -1, 0 or 1");
1905 * perform the val1 mod (val2 * 2^val3 + val4) operation
1907 zhnrmod(val1
->num
, val2
->num
, val3
->num
, val4
->num
, &answer
);
1918 ssqlistitems(LIST
*lp
)
1926 /* initialize VALUEs */
1927 term
.v_type
= V_NULL
;
1928 term
.v_subtype
= V_NOSUBTYPE
;
1929 tmp
.v_type
= V_NULL
;
1930 tmp
.v_subtype
= V_NOSUBTYPE
;
1931 sum
.v_type
= V_NULL
;
1932 sum
.v_subtype
= V_NOSUBTYPE
;
1934 for (ep
= lp
->l_first
; ep
; ep
= ep
->e_next
) {
1936 if (vp
->v_type
== V_LIST
) {
1937 term
= ssqlistitems(vp
->v_list
);
1939 squarevalue(vp
, &term
);
1941 addvalue(&sum
, &term
, &tmp
);
1952 f_ssq(int count
, VALUE
**vals
)
1959 /* initialize VALUEs */
1960 tmp
.v_type
= V_NULL
;
1961 tmp
.v_subtype
= V_NOSUBTYPE
;
1962 sum
.v_type
= V_NULL
;
1963 sum
.v_subtype
= V_NOSUBTYPE
;
1964 term
.v_type
= V_NULL
;
1965 term
.v_subtype
= V_NOSUBTYPE
;
1966 while (count
-- > 0) {
1968 if (vp
->v_type
== V_LIST
) {
1969 term
= ssqlistitems(vp
->v_list
);
1971 squarevalue(vp
, &term
);
1973 addvalue(&sum
, &term
, &tmp
);
1985 f_ismult(NUMBER
*val1
, NUMBER
*val2
)
1987 return itoq((long) qdivides(val1
, val2
));
1992 f_meq(NUMBER
*val1
, NUMBER
*val2
, NUMBER
*val3
)
1996 tmp
= qsub(val1
, val2
);
1997 res
= itoq((long) qdivides(tmp
, val3
));
2004 f_exp(int count
, VALUE
**vals
)
2011 /* initialize VALUE */
2012 result
.v_subtype
= V_NOSUBTYPE
;
2014 eps
= conf
->epsilon
;
2016 if (vals
[1]->v_type
!= V_NUM
|| qiszero(vals
[1]->v_num
))
2017 return error_value(E_EXP1
);
2018 eps
= vals
[1]->v_num
;
2020 switch (vals
[0]->v_type
) {
2022 q
= qexp(vals
[0]->v_num
, eps
);
2024 return error_value(E_EXP3
);
2026 result
.v_type
= V_NUM
;
2029 c
= c_exp(vals
[0]->v_com
, eps
);
2031 return error_value(E_EXP3
);
2033 result
.v_type
= V_COM
;
2035 result
.v_num
= qlink(c
->real
);
2036 result
.v_type
= V_NUM
;
2041 return error_value(E_EXP2
);
2048 f_ln(int count
, VALUE
**vals
)
2054 /* initialize VALUE */
2055 result
.v_subtype
= V_NOSUBTYPE
;
2057 err
= conf
->epsilon
;
2059 if (vals
[1]->v_type
!= V_NUM
)
2060 return error_value(E_LN1
);
2061 err
= vals
[1]->v_num
;
2063 switch (vals
[0]->v_type
) {
2065 if (!qisneg(vals
[0]->v_num
) &&
2066 !qiszero(vals
[0]->v_num
)) {
2067 result
.v_num
= qln(vals
[0]->v_num
, err
);
2068 result
.v_type
= V_NUM
;
2071 ctmp
.real
= vals
[0]->v_num
;
2072 ctmp
.imag
= qlink(&_qzero_
);
2074 c
= c_ln(&ctmp
, err
);
2077 c
= c_ln(vals
[0]->v_com
, err
);
2080 return error_value(E_LN2
);
2082 result
.v_type
= V_COM
;
2085 result
.v_num
= qlink(c
->real
);
2086 result
.v_type
= V_NUM
;
2094 f_log(int count
, VALUE
**vals
)
2100 /* initialize VALUE */
2101 result
.v_subtype
= V_NOSUBTYPE
;
2103 err
= conf
->epsilon
;
2105 if (vals
[1]->v_type
!= V_NUM
)
2106 return error_value(E_LOG1
);
2107 err
= vals
[1]->v_num
;
2109 switch (vals
[0]->v_type
) {
2111 if (!qisneg(vals
[0]->v_num
) &&
2112 !qiszero(vals
[0]->v_num
)) {
2113 result
.v_num
= qlog(vals
[0]->v_num
, err
);
2114 result
.v_type
= V_NUM
;
2117 ctmp
.real
= vals
[0]->v_num
;
2118 ctmp
.imag
= qlink(&_qzero_
);
2120 c
= c_log(&ctmp
, err
);
2123 c
= c_log(vals
[0]->v_com
, err
);
2126 return error_value(E_LOG2
);
2128 result
.v_type
= V_COM
;
2131 result
.v_num
= qlink(c
->real
);
2132 result
.v_type
= V_NUM
;
2140 f_cos(int count
, VALUE
**vals
)
2146 /* initialize VALUE */
2147 result
.v_subtype
= V_NOSUBTYPE
;
2149 eps
= conf
->epsilon
;
2151 if (vals
[1]->v_type
!= V_NUM
|| qiszero(vals
[1]->v_num
))
2152 return error_value(E_COS1
);
2153 eps
= vals
[1]->v_num
;
2155 switch (vals
[0]->v_type
) {
2157 result
.v_num
= qcos(vals
[0]->v_num
, eps
);
2158 result
.v_type
= V_NUM
;
2161 c
= c_cos(vals
[0]->v_com
, eps
);
2163 return error_value(E_COS3
);
2165 result
.v_type
= V_COM
;
2167 result
.v_num
= qlink(c
->real
);
2168 result
.v_type
= V_NUM
;
2173 return error_value(E_COS2
);
2180 f_sin(int count
, VALUE
**vals
)
2186 /* initialize VALUE */
2187 result
.v_subtype
= V_NOSUBTYPE
;
2189 eps
= conf
->epsilon
;
2191 if (vals
[1]->v_type
!= V_NUM
|| qiszero(vals
[1]->v_num
))
2192 return error_value(E_SIN1
);
2193 eps
= vals
[1]->v_num
;
2195 switch (vals
[0]->v_type
) {
2197 result
.v_num
= qsin(vals
[0]->v_num
, eps
);
2198 result
.v_type
= V_NUM
;
2201 c
= c_sin(vals
[0]->v_com
, eps
);
2203 return error_value(E_SIN3
);
2205 result
.v_type
= V_COM
;
2207 result
.v_num
= qlink(c
->real
);
2208 result
.v_type
= V_NUM
;
2213 return error_value(E_SIN2
);
2220 f_tan(int count
, VALUE
**vals
)
2226 /* initialize VALUEs */
2227 result
.v_subtype
= V_NOSUBTYPE
;
2228 tmp1
.v_subtype
= V_NOSUBTYPE
;
2229 tmp2
.v_subtype
= V_NOSUBTYPE
;
2231 err
= conf
->epsilon
;
2233 if (vals
[1]->v_type
!= V_NUM
|| qiszero(vals
[1]->v_num
))
2234 return error_value(E_TAN1
);
2235 err
= vals
[1]->v_num
;
2237 switch (vals
[0]->v_type
) {
2239 result
.v_num
= qtan(vals
[0]->v_num
, err
);
2240 result
.v_type
= V_NUM
;
2243 tmp1
.v_type
= V_COM
;
2244 tmp1
.v_com
= c_sin(vals
[0]->v_com
, err
);
2245 tmp2
.v_type
= V_COM
;
2246 tmp2
.v_com
= c_cos(vals
[0]->v_com
, err
);
2247 divvalue(&tmp1
, &tmp2
, &result
);
2248 comfree(tmp1
.v_com
);
2249 comfree(tmp2
.v_com
);
2252 return error_value(E_TAN2
);
2258 f_sec(int count
, VALUE
**vals
)
2264 /* initialize VALUEs */
2265 result
.v_subtype
= V_NOSUBTYPE
;
2266 tmp
.v_subtype
= V_NOSUBTYPE
;
2268 err
= conf
->epsilon
;
2270 if (vals
[1]->v_type
!= V_NUM
|| qiszero(vals
[1]->v_num
))
2271 return error_value(E_SEC1
);
2272 err
= vals
[1]->v_num
;
2274 switch (vals
[0]->v_type
) {
2276 result
.v_num
= qsec(vals
[0]->v_num
, err
);
2277 result
.v_type
= V_NUM
;
2281 tmp
.v_com
= c_cos(vals
[0]->v_com
, err
);
2282 invertvalue(&tmp
, &result
);
2286 return error_value(E_SEC2
);
2293 f_cot(int count
, VALUE
**vals
)
2299 /* initialize VALUEs */
2300 result
.v_subtype
= V_NOSUBTYPE
;
2301 tmp1
.v_subtype
= V_NOSUBTYPE
;
2302 tmp2
.v_subtype
= V_NOSUBTYPE
;
2304 err
= conf
->epsilon
;
2306 if (vals
[1]->v_type
!= V_NUM
|| qiszero(vals
[1]->v_num
))
2307 return error_value(E_COT1
);
2308 err
= vals
[1]->v_num
;
2310 switch (vals
[0]->v_type
) {
2312 if (qiszero(vals
[0]->v_num
))
2313 return error_value(E_1OVER0
);
2314 result
.v_num
= qcot(vals
[0]->v_num
, err
);
2315 result
.v_type
= V_NUM
;
2318 tmp1
.v_type
= V_COM
;
2319 tmp1
.v_com
= c_cos(vals
[0]->v_com
, err
);
2320 tmp2
.v_type
= V_COM
;
2321 tmp2
.v_com
= c_sin(vals
[0]->v_com
, err
);
2322 divvalue(&tmp1
, &tmp2
, &result
);
2323 comfree(tmp1
.v_com
);
2324 comfree(tmp2
.v_com
);
2327 return error_value(E_COT2
);
2334 f_csc(int count
, VALUE
**vals
)
2340 /* initialize VALUEs */
2341 result
.v_subtype
= V_NOSUBTYPE
;
2342 tmp
.v_subtype
= V_NOSUBTYPE
;
2344 err
= conf
->epsilon
;
2346 if (vals
[1]->v_type
!= V_NUM
|| qiszero(vals
[1]->v_num
))
2347 return error_value(E_CSC1
);
2348 err
= vals
[1]->v_num
;
2350 switch (vals
[0]->v_type
) {
2352 if (qiszero(vals
[0]->v_num
))
2353 return error_value(E_1OVER0
);
2354 result
.v_num
= qcsc(vals
[0]->v_num
, err
);
2355 result
.v_type
= V_NUM
;
2359 tmp
.v_com
= c_sin(vals
[0]->v_com
, err
);
2360 invertvalue(&tmp
, &result
);
2364 return error_value(E_CSC2
);
2370 f_sinh(int count
, VALUE
**vals
)
2377 /* initialize VALUE */
2378 result
.v_subtype
= V_NOSUBTYPE
;
2380 eps
= conf
->epsilon
;
2382 if (vals
[1]->v_type
!= V_NUM
|| qiszero(vals
[1]->v_num
))
2383 return error_value(E_SINH1
);
2384 eps
= vals
[1]->v_num
;
2386 switch (vals
[0]->v_type
) {
2388 q
= qsinh(vals
[0]->v_num
, eps
);
2390 return error_value(E_SINH3
);
2392 result
.v_type
= V_NUM
;
2395 c
= c_sinh(vals
[0]->v_com
, eps
);
2397 return error_value(E_SINH3
);
2399 result
.v_type
= V_COM
;
2401 result
.v_num
= qlink(c
->real
);
2403 result
.v_type
= V_NUM
;
2407 return error_value(E_SINH2
);
2413 f_cosh(int count
, VALUE
**vals
)
2420 /* initialize VALUE */
2421 result
.v_subtype
= V_NOSUBTYPE
;
2423 eps
= conf
->epsilon
;
2425 if (vals
[1]->v_type
!= V_NUM
|| qiszero(vals
[1]->v_num
))
2426 return error_value(E_COSH1
);
2427 eps
= vals
[1]->v_num
;
2429 switch (vals
[0]->v_type
) {
2431 q
= qcosh(vals
[0]->v_num
, eps
);
2433 return error_value(E_COSH3
);
2435 result
.v_type
= V_NUM
;
2438 c
= c_cosh(vals
[0]->v_com
, eps
);
2440 return error_value(E_COSH3
);
2442 result
.v_type
= V_COM
;
2444 result
.v_num
= qlink(c
->real
);
2446 result
.v_type
= V_NUM
;
2450 return error_value(E_COSH2
);
2457 f_tanh(int count
, VALUE
**vals
)
2463 /* initialize VALUEs */
2464 result
.v_subtype
= V_NOSUBTYPE
;
2465 tmp1
.v_subtype
= V_NOSUBTYPE
;
2466 tmp2
.v_subtype
= V_NOSUBTYPE
;
2468 err
= conf
->epsilon
;
2470 if (vals
[1]->v_type
!= V_NUM
|| qiszero(vals
[1]->v_num
))
2471 return error_value(E_TANH1
);
2472 err
= vals
[1]->v_num
;
2474 switch (vals
[0]->v_type
) {
2476 result
.v_num
= qtanh(vals
[0]->v_num
, err
);
2477 result
.v_type
= V_NUM
;
2480 tmp1
.v_type
= V_COM
;
2481 tmp1
.v_com
= c_sinh(vals
[0]->v_com
, err
);
2482 tmp2
.v_type
= V_COM
;
2483 tmp2
.v_com
= c_cosh(vals
[0]->v_com
, err
);
2484 divvalue(&tmp1
, &tmp2
, &result
);
2485 comfree(tmp1
.v_com
);
2486 comfree(tmp2
.v_com
);
2489 return error_value(E_TANH2
);
2496 f_coth(int count
, VALUE
**vals
)
2502 /* initialize VALUEs */
2503 result
.v_subtype
= V_NOSUBTYPE
;
2504 tmp1
.v_subtype
= V_NOSUBTYPE
;
2505 tmp2
.v_subtype
= V_NOSUBTYPE
;
2507 err
= conf
->epsilon
;
2509 if (vals
[1]->v_type
!= V_NUM
|| qiszero(vals
[1]->v_num
))
2510 return error_value(E_COTH1
);
2511 err
= vals
[1]->v_num
;
2513 switch (vals
[0]->v_type
) {
2515 if (qiszero(vals
[0]->v_num
))
2516 return error_value(E_1OVER0
);
2517 result
.v_num
= qcoth(vals
[0]->v_num
, err
);
2518 result
.v_type
= V_NUM
;
2521 tmp1
.v_type
= V_COM
;
2522 tmp1
.v_com
= c_cosh(vals
[0]->v_com
, err
);
2523 tmp2
.v_type
= V_COM
;
2524 tmp2
.v_com
= c_sinh(vals
[0]->v_com
, err
);
2525 divvalue(&tmp1
, &tmp2
, &result
);
2526 comfree(tmp1
.v_com
);
2527 comfree(tmp2
.v_com
);
2530 return error_value(E_COTH2
);
2537 f_sech(int count
, VALUE
**vals
)
2543 /* initialize VALUEs */
2544 result
.v_subtype
= V_NOSUBTYPE
;
2545 tmp
.v_subtype
= V_NOSUBTYPE
;
2547 err
= conf
->epsilon
;
2549 if (vals
[1]->v_type
!= V_NUM
|| qiszero(vals
[1]->v_num
))
2550 return error_value(E_SECH1
);
2551 err
= vals
[1]->v_num
;
2553 switch (vals
[0]->v_type
) {
2555 result
.v_num
= qsech(vals
[0]->v_num
, err
);
2556 result
.v_type
= V_NUM
;
2560 tmp
.v_com
= c_cosh(vals
[0]->v_com
, err
);
2561 invertvalue(&tmp
, &result
);
2565 return error_value(E_SECH2
);
2572 f_csch(int count
, VALUE
**vals
)
2578 /* initialize VALUEs */
2579 result
.v_subtype
= V_NOSUBTYPE
;
2580 tmp
.v_subtype
= V_NOSUBTYPE
;
2582 err
= conf
->epsilon
;
2584 if (vals
[1]->v_type
!= V_NUM
|| qiszero(vals
[1]->v_num
))
2585 return error_value(E_CSCH1
);
2586 err
= vals
[1]->v_num
;
2588 switch (vals
[0]->v_type
) {
2590 if (qiszero(vals
[0]->v_num
))
2591 return error_value(E_1OVER0
);
2592 result
.v_num
= qcsch(vals
[0]->v_num
, err
);
2593 result
.v_type
= V_NUM
;
2597 tmp
.v_com
= c_sinh(vals
[0]->v_com
, err
);
2598 invertvalue(&tmp
, &result
);
2602 return error_value(E_CSCH2
);
2609 f_atan(int count
, VALUE
**vals
)
2615 /* initialize VALUE */
2616 result
.v_subtype
= V_NOSUBTYPE
;
2618 err
= conf
->epsilon
;
2620 if (vals
[1]->v_type
!= V_NUM
|| qiszero(vals
[1]->v_num
))
2621 return error_value(E_ATAN1
);
2622 err
= vals
[1]->v_num
;
2624 switch (vals
[0]->v_type
) {
2626 result
.v_num
= qatan(vals
[0]->v_num
, err
);
2627 result
.v_type
= V_NUM
;
2630 tmp
= c_atan(vals
[0]->v_com
, err
);
2632 return error_value(E_LOGINF
);
2633 result
.v_type
= V_COM
;
2636 result
.v_num
= qlink(tmp
->real
);
2637 result
.v_type
= V_NUM
;
2642 return error_value(E_ATAN2
);
2649 f_acot(int count
, VALUE
**vals
)
2655 /* initialize VALUE */
2656 result
.v_subtype
= V_NOSUBTYPE
;
2658 err
= conf
->epsilon
;
2660 if (vals
[1]->v_type
!= V_NUM
|| qiszero(vals
[1]->v_num
))
2661 return error_value(E_ACOT1
);
2662 err
= vals
[1]->v_num
;
2664 switch (vals
[0]->v_type
) {
2666 result
.v_num
= qacot(vals
[0]->v_num
, err
);
2667 result
.v_type
= V_NUM
;
2670 tmp
= c_acot(vals
[0]->v_com
, err
);
2672 return error_value(E_LOGINF
);
2673 result
.v_type
= V_COM
;
2676 result
.v_num
= qlink(tmp
->real
);
2677 result
.v_type
= V_NUM
;
2682 return error_value(E_ACOT2
);
2688 f_asin(int count
, VALUE
**vals
)
2695 /* initialize VALUE */
2696 result
.v_subtype
= V_NOSUBTYPE
;
2698 err
= conf
->epsilon
;
2700 if (vals
[1]->v_type
!= V_NUM
|| qiszero(vals
[1]->v_num
))
2701 return error_value(E_ASIN1
);
2702 err
= vals
[1]->v_num
;
2704 switch (vals
[0]->v_type
) {
2706 result
.v_num
= qasin(vals
[0]->v_num
, err
);
2707 result
.v_type
= V_NUM
;
2708 if (result
.v_num
== NULL
) {
2711 tmp
->real
= qlink(vals
[0]->v_num
);
2712 result
.v_type
= V_COM
;
2713 result
.v_com
= c_asin(tmp
, err
);
2718 result
.v_com
= c_asin(vals
[0]->v_com
, err
);
2719 result
.v_type
= V_COM
;
2722 return error_value(E_ASIN2
);
2724 if (result
.v_type
== V_COM
&& cisreal(result
.v_com
)) {
2725 q
= qlink(result
.v_com
->real
);
2726 comfree(result
.v_com
);
2727 result
.v_type
= V_NUM
;
2734 f_acos(int count
, VALUE
**vals
)
2741 /* initialize VALUE */
2742 result
.v_subtype
= V_NOSUBTYPE
;
2744 err
= conf
->epsilon
;
2746 if (vals
[1]->v_type
!= V_NUM
|| qiszero(vals
[1]->v_num
))
2747 return error_value(E_ACOS1
);
2748 err
= vals
[1]->v_num
;
2750 switch (vals
[0]->v_type
) {
2752 result
.v_num
= qacos(vals
[0]->v_num
, err
);
2753 result
.v_type
= V_NUM
;
2754 if (result
.v_num
== NULL
) {
2757 tmp
->real
= qlink(vals
[0]->v_num
);
2758 result
.v_type
= V_COM
;
2759 result
.v_com
= c_acos(tmp
, err
);
2764 result
.v_com
= c_acos(vals
[0]->v_com
, err
);
2765 result
.v_type
= V_COM
;
2768 return error_value(E_ACOS2
);
2770 if (result
.v_type
== V_COM
&& cisreal(result
.v_com
)) {
2771 q
= qlink(result
.v_com
->real
);
2772 comfree(result
.v_com
);
2773 result
.v_type
= V_NUM
;
2781 f_asec(int count
, VALUE
**vals
)
2788 /* initialize VALUE */
2789 result
.v_subtype
= V_NOSUBTYPE
;
2791 err
= conf
->epsilon
;
2793 if (vals
[1]->v_type
!= V_NUM
|| qiszero(vals
[1]->v_num
))
2794 return error_value(E_ASEC1
);
2795 err
= vals
[1]->v_num
;
2797 switch (vals
[0]->v_type
) {
2799 if (qiszero(vals
[0]->v_num
))
2800 return error_value(E_LOGINF
);
2801 result
.v_num
= qasec(vals
[0]->v_num
, err
);
2802 result
.v_type
= V_NUM
;
2803 if (result
.v_num
== NULL
) {
2806 tmp
->real
= qlink(vals
[0]->v_num
);
2807 result
.v_com
= c_asec(tmp
, err
);
2808 result
.v_type
= V_COM
;
2813 result
.v_com
= c_asec(vals
[0]->v_com
, err
);
2814 result
.v_type
= V_COM
;
2817 return error_value(E_ASEC2
);
2819 if (result
.v_type
== V_COM
) {
2820 if (result
.v_com
== NULL
)
2821 return error_value(E_LOGINF
);
2822 if (cisreal(result
.v_com
)) {
2823 q
= qlink(result
.v_com
->real
);
2824 comfree(result
.v_com
);
2825 result
.v_type
= V_NUM
;
2834 f_acsc(int count
, VALUE
**vals
)
2841 /* initialize VALUE */
2842 result
.v_subtype
= V_NOSUBTYPE
;
2844 err
= conf
->epsilon
;
2846 if (vals
[1]->v_type
!= V_NUM
|| qiszero(vals
[1]->v_num
))
2847 return error_value(E_ACSC1
);
2848 err
= vals
[1]->v_num
;
2850 switch (vals
[0]->v_type
) {
2852 if (qiszero(vals
[0]->v_num
))
2853 return error_value(E_LOGINF
);
2854 result
.v_num
= qacsc(vals
[0]->v_num
, err
);
2855 result
.v_type
= V_NUM
;
2856 if (result
.v_num
== NULL
) {
2859 tmp
->real
= qlink(vals
[0]->v_num
);
2860 result
.v_com
= c_acsc(tmp
, err
);
2861 result
.v_type
= V_COM
;
2866 result
.v_com
= c_acsc(vals
[0]->v_com
, err
);
2867 result
.v_type
= V_COM
;
2870 return error_value(E_ACSC2
);
2872 if (result
.v_type
== V_COM
) {
2873 if (result
.v_com
== NULL
)
2874 return error_value(E_LOGINF
);
2875 if (cisreal(result
.v_com
)) {
2876 q
= qlink(result
.v_com
->real
);
2877 comfree(result
.v_com
);
2878 result
.v_type
= V_NUM
;
2887 f_asinh(int count
, VALUE
**vals
)
2893 /* initialize VALUE */
2894 result
.v_subtype
= V_NOSUBTYPE
;
2896 err
= conf
->epsilon
;
2898 if (vals
[1]->v_type
!= V_NUM
|| qiszero(vals
[1]->v_num
))
2899 return error_value(E_ASINH1
);
2900 err
= vals
[1]->v_num
;
2902 switch (vals
[0]->v_type
) {
2904 result
.v_num
= qasinh(vals
[0]->v_num
, err
);
2905 result
.v_type
= V_NUM
;
2908 tmp
= c_asinh(vals
[0]->v_com
, err
);
2909 result
.v_type
= V_COM
;
2912 result
.v_num
= qlink(tmp
->real
);
2913 result
.v_type
= V_NUM
;
2918 return error_value(E_ASINH2
);
2925 f_acosh(int count
, VALUE
**vals
)
2932 /* initialize VALUE */
2933 result
.v_subtype
= V_NOSUBTYPE
;
2935 err
= conf
->epsilon
;
2937 if (vals
[1]->v_type
!= V_NUM
|| qiszero(vals
[1]->v_num
))
2938 return error_value(E_ACOSH1
);
2939 err
= vals
[1]->v_num
;
2941 switch (vals
[0]->v_type
) {
2943 result
.v_num
= qacosh(vals
[0]->v_num
, err
);
2944 result
.v_type
= V_NUM
;
2945 if (result
.v_num
== NULL
) {
2948 tmp
->real
= qlink(vals
[0]->v_num
);
2949 result
.v_com
= c_acosh(tmp
, err
);
2950 result
.v_type
= V_COM
;
2955 result
.v_com
= c_acosh(vals
[0]->v_com
, err
);
2956 result
.v_type
= V_COM
;
2959 return error_value(E_ACOSH2
);
2961 if (result
.v_type
== V_COM
&& cisreal(result
.v_com
)) {
2962 q
= qlink(result
.v_com
->real
);
2963 comfree(result
.v_com
);
2964 result
.v_type
= V_NUM
;
2972 f_atanh(int count
, VALUE
**vals
)
2979 /* initialize VALUE */
2980 result
.v_subtype
= V_NOSUBTYPE
;
2982 err
= conf
->epsilon
;
2984 if (vals
[1]->v_type
!= V_NUM
|| qiszero(vals
[1]->v_num
))
2985 return error_value(E_ATANH1
);
2986 err
= vals
[1]->v_num
;
2988 switch (vals
[0]->v_type
) {
2990 result
.v_num
= qatanh(vals
[0]->v_num
, err
);
2991 result
.v_type
= V_NUM
;
2992 if (result
.v_num
== NULL
) {
2995 tmp
->real
= qlink(vals
[0]->v_num
);
2996 result
.v_com
= c_atanh(tmp
, err
);
2997 result
.v_type
= V_COM
;
3002 result
.v_com
= c_atanh(vals
[0]->v_com
, err
);
3003 result
.v_type
= V_COM
;
3006 return error_value(E_ATANH2
);
3008 if (result
.v_type
== V_COM
) {
3009 if (result
.v_com
== NULL
)
3010 return error_value(E_LOGINF
);
3011 if (cisreal(result
.v_com
)) {
3012 q
= qlink(result
.v_com
->real
);
3013 comfree(result
.v_com
);
3014 result
.v_type
= V_NUM
;
3023 f_acoth(int count
, VALUE
**vals
)
3030 /* initialize VALUE */
3031 result
.v_subtype
= V_NOSUBTYPE
;
3033 err
= conf
->epsilon
;
3035 if (vals
[1]->v_type
!= V_NUM
|| qiszero(vals
[1]->v_num
))
3036 return error_value(E_ACOTH1
);
3037 err
= vals
[1]->v_num
;
3039 switch (vals
[0]->v_type
) {
3041 result
.v_num
= qacoth(vals
[0]->v_num
, err
);
3042 result
.v_type
= V_NUM
;
3043 if (result
.v_num
== NULL
) {
3046 tmp
->real
= qlink(vals
[0]->v_num
);
3047 result
.v_com
= c_acoth(tmp
, err
);
3048 result
.v_type
= V_COM
;
3053 result
.v_com
= c_acoth(vals
[0]->v_com
, err
);
3054 result
.v_type
= V_COM
;
3057 return error_value(E_ACOTH2
);
3059 if (result
.v_type
== V_COM
) {
3060 if (result
.v_com
== NULL
)
3061 return error_value(E_LOGINF
);
3062 if (cisreal(result
.v_com
)) {
3063 q
= qlink(result
.v_com
->real
);
3064 comfree(result
.v_com
);
3065 result
.v_type
= V_NUM
;
3074 f_asech(int count
, VALUE
**vals
)
3081 /* initialize VALUE */
3082 result
.v_subtype
= V_NOSUBTYPE
;
3084 err
= conf
->epsilon
;
3086 if (vals
[1]->v_type
!= V_NUM
|| qiszero(vals
[1]->v_num
))
3087 return error_value(E_SECH1
);
3088 err
= vals
[1]->v_num
;
3090 switch (vals
[0]->v_type
) {
3092 if (qiszero(vals
[0]->v_num
))
3093 return error_value(E_LOGINF
);
3094 result
.v_num
= qasech(vals
[0]->v_num
, err
);
3095 result
.v_type
= V_NUM
;
3096 if (result
.v_num
== NULL
) {
3099 tmp
->real
= qlink(vals
[0]->v_num
);
3100 result
.v_com
= c_asech(tmp
, err
);
3101 result
.v_type
= V_COM
;
3106 result
.v_com
= c_asech(vals
[0]->v_com
, err
);
3107 result
.v_type
= V_COM
;
3110 return error_value(E_ASECH2
);
3112 if (result
.v_type
== V_COM
) {
3113 if (result
.v_com
== NULL
)
3114 return error_value(E_LOGINF
);
3115 if (cisreal(result
.v_com
)) {
3116 q
= qlink(result
.v_com
->real
);
3117 comfree(result
.v_com
);
3118 result
.v_type
= V_NUM
;
3127 f_acsch(int count
, VALUE
**vals
)
3134 /* initialize VALUE */
3135 result
.v_subtype
= V_NOSUBTYPE
;
3137 err
= conf
->epsilon
;
3139 if (vals
[1]->v_type
!= V_NUM
|| qiszero(vals
[1]->v_num
))
3140 return error_value(E_ACSCH1
);
3141 err
= vals
[1]->v_num
;
3143 switch (vals
[0]->v_type
) {
3145 if (qiszero(vals
[0]->v_num
))
3146 return error_value(E_LOGINF
);
3147 result
.v_num
= qacsch(vals
[0]->v_num
, err
);
3148 result
.v_type
= V_NUM
;
3149 if (result
.v_num
== NULL
) {
3152 tmp
->real
= qlink(vals
[0]->v_num
);
3153 result
.v_com
= c_acsch(tmp
, err
);
3154 result
.v_type
= V_COM
;
3159 result
.v_com
= c_acsch(vals
[0]->v_com
, err
);
3160 result
.v_type
= V_COM
;
3163 return error_value(E_ACSCH2
);
3165 if (result
.v_type
== V_COM
) {
3166 if (result
.v_com
== NULL
)
3167 return error_value(E_LOGINF
);
3168 if (cisreal(result
.v_com
)) {
3169 q
= qlink(result
.v_com
->real
);
3170 comfree(result
.v_com
);
3171 result
.v_type
= V_NUM
;
3180 f_gd(int count
, VALUE
**vals
)
3187 /* initialize VALUE */
3188 result
.v_subtype
= V_NOSUBTYPE
;
3190 eps
= conf
->epsilon
;
3192 if (vals
[1]->v_type
!= V_NUM
|| qiszero(vals
[1]->v_num
))
3193 return error_value(E_GD1
);
3194 eps
= vals
[1]->v_num
;
3196 result
.v_type
= V_COM
;
3197 switch (vals
[0]->v_type
) {
3199 if (qiszero(vals
[0]->v_num
)) {
3200 result
.v_type
= V_NUM
;
3201 result
.v_num
= qlink(&_qzero_
);
3206 tmp
->real
= qlink(vals
[0]->v_num
);
3207 result
.v_com
= c_gd(tmp
, eps
);
3211 result
.v_com
= c_gd(vals
[0]->v_com
, eps
);
3214 return error_value(E_GD2
);
3216 if (result
.v_com
== NULL
)
3217 return error_value(E_GD3
);
3218 if (cisreal(result
.v_com
)) {
3219 q
= qlink(result
.v_com
->real
);
3220 comfree(result
.v_com
);
3222 result
.v_type
= V_NUM
;
3229 f_agd(int count
, VALUE
**vals
)
3236 /* initialize VALUE */
3237 result
.v_subtype
= V_NOSUBTYPE
;
3239 eps
= conf
->epsilon
;
3241 if (vals
[1]->v_type
!= V_NUM
|| qiszero(vals
[1]->v_num
))
3242 return error_value(E_AGD1
);
3243 eps
= vals
[1]->v_num
;
3245 result
.v_type
= V_COM
;
3246 switch (vals
[0]->v_type
) {
3248 if (qiszero(vals
[0]->v_num
)) {
3249 result
.v_type
= V_NUM
;
3250 result
.v_num
= qlink(&_qzero_
);
3255 tmp
->real
= qlink(vals
[0]->v_num
);
3256 result
.v_com
= c_agd(tmp
, eps
);
3260 result
.v_com
= c_agd(vals
[0]->v_com
, eps
);
3263 return error_value(E_AGD2
);
3265 if (result
.v_com
== NULL
)
3266 return error_value(E_AGD3
);
3267 if (cisreal(result
.v_com
)) {
3268 q
= qlink(result
.v_com
->real
);
3269 comfree(result
.v_com
);
3271 result
.v_type
= V_NUM
;
3278 f_comb(VALUE
*v1
, VALUE
*v2
)
3282 VALUE tmp1
, tmp2
, div
;
3284 if (v2
->v_type
!= V_NUM
|| qisfrac(v2
->v_num
))
3285 return error_value(E_COMB1
);
3286 result
.v_subtype
= V_NOSUBTYPE
;
3287 result
.v_type
= V_NUM
;
3288 if (qisneg(v2
->v_num
)) {
3289 result
.v_num
= qlink(&_qzero_
);
3292 if (qiszero(v2
->v_num
)) {
3293 result
.v_num
= qlink(&_qone_
);
3296 if (qisone(v2
->v_num
)) {
3297 copyvalue(v1
, &result
);
3300 if (v1
->v_type
== V_NUM
) {
3301 result
.v_num
= qcomb(v1
->v_num
, v2
->v_num
);
3302 if (result
.v_num
== NULL
)
3303 return error_value(E_COMB2
);
3306 if (zge24b(v2
->v_num
->num
))
3307 return error_value(E_COMB2
);
3308 n
= qtoi(v2
->v_num
);
3309 copyvalue(v1
, &result
);
3310 decvalue(v1
, &tmp1
);
3312 div
.v_num
= qlink(&_qtwo_
);
3315 mulvalue(&result
, &tmp1
, &tmp2
);
3317 divvalue(&tmp2
, &div
, &result
);
3319 if (--n
== 0 || !testvalue(&result
) || result
.v_type
< 0) {
3324 decvalue(&tmp1
, &tmp2
);
3327 incvalue(&div
, &tmp2
);
3339 if (vp
->v_type
!= V_NUM
|| qisfrac(vp
->v_num
))
3340 return error_value(E_BERN
);
3342 res
.v_subtype
= V_NOSUBTYPE
;
3344 res
.v_num
= qbern(vp
->v_num
->num
);
3345 if (res
.v_num
== NULL
)
3346 return error_value(E_BERN
);
3357 res
.v_type
= V_NULL
;
3358 res
.v_subtype
= V_NOSUBTYPE
;
3368 if (vp
->v_type
!=V_NUM
|| qisfrac(vp
->v_num
))
3369 return error_value(E_EULER
);
3370 res
.v_subtype
= V_NOSUBTYPE
;
3372 res
.v_num
= qeuler(vp
->v_num
->num
);
3373 if (res
.v_num
== NULL
)
3374 return error_value(E_EULER
);
3385 res
.v_type
= V_NULL
;
3386 res
.v_subtype
= V_NOSUBTYPE
;
3392 f_catalan(VALUE
*vp
)
3396 if (vp
->v_type
!=V_NUM
|| qisfrac(vp
->v_num
) || zge31b(vp
->v_num
->num
))
3397 return error_value(E_CTLN
);
3399 res
.v_subtype
= V_NOSUBTYPE
;
3400 res
.v_num
= qcatalan(vp
->v_num
);
3401 if (res
.v_num
== NULL
)
3402 return error_value(E_CTLN
);
3407 f_arg(int count
, VALUE
**vals
)
3413 /* initialize VALUE */
3414 result
.v_subtype
= V_NOSUBTYPE
;
3416 err
= conf
->epsilon
;
3418 if (vals
[1]->v_type
!= V_NUM
|| qiszero(vals
[1]->v_num
))
3419 return error_value(E_ARG1
);
3420 err
= vals
[1]->v_num
;
3422 result
.v_type
= V_NUM
;
3423 switch (vals
[0]->v_type
) {
3425 if (qisneg(vals
[0]->v_num
))
3426 result
.v_num
= qpi(err
);
3428 result
.v_num
= qlink(&_qzero_
);
3433 result
.v_num
= qlink(&_qzero_
);
3435 result
.v_num
= qatan2(c
->imag
, c
->real
, err
);
3438 return error_value(E_ARG2
);
3445 f_legtoleg(NUMBER
*val1
, NUMBER
*val2
)
3447 return qlegtoleg(val1
, val2
, FALSE
);
3452 f_trunc(int count
, NUMBER
**vals
)
3456 val
= qlink(&_qzero_
);
3459 return qtrunc(*vals
, val
);
3464 f_bround(int count
, VALUE
**vals
)
3466 VALUE tmp1
, tmp2
, res
;
3468 /* initialize VALUEs */
3469 res
.v_subtype
= V_NOSUBTYPE
;
3470 tmp1
.v_subtype
= V_NOSUBTYPE
;
3471 tmp2
.v_subtype
= V_NOSUBTYPE
;
3476 tmp2
.v_type
= V_NULL
;
3480 tmp1
.v_type
= V_NULL
;
3481 broundvalue(vals
[0], &tmp1
, &tmp2
, &res
);
3487 f_appr(int count
, VALUE
**vals
)
3489 VALUE tmp1
, tmp2
, res
;
3491 /* initialize VALUEs */
3492 res
.v_subtype
= V_NOSUBTYPE
;
3493 tmp1
.v_subtype
= V_NOSUBTYPE
;
3494 tmp2
.v_subtype
= V_NOSUBTYPE
;
3497 copyvalue(vals
[2], &tmp2
);
3499 tmp2
.v_type
= V_NULL
;
3501 copyvalue(vals
[1], &tmp1
);
3503 tmp1
.v_type
= V_NULL
;
3504 apprvalue(vals
[0], &tmp1
, &tmp2
, &res
);
3511 f_round(int count
, VALUE
**vals
)
3513 VALUE tmp1
, tmp2
, res
;
3515 /* initialize VALUEs */
3516 res
.v_subtype
= V_NOSUBTYPE
;
3517 tmp1
.v_subtype
= V_NOSUBTYPE
;
3518 tmp2
.v_subtype
= V_NOSUBTYPE
;
3523 tmp2
.v_type
= V_NULL
;
3527 tmp1
.v_type
= V_NULL
;
3528 roundvalue(vals
[0], &tmp1
, &tmp2
, &res
);
3534 f_btrunc(int count
, NUMBER
**vals
)
3538 val
= qlink(&_qzero_
);
3541 return qbtrunc(*vals
, val
);
3546 f_quo(int count
, VALUE
**vals
)
3550 /* initialize VALUEs */
3551 res
.v_subtype
= V_NOSUBTYPE
;
3552 tmp
.v_subtype
= V_NOSUBTYPE
;
3557 tmp
.v_type
= V_NULL
;
3558 quovalue(vals
[0], vals
[1], &tmp
, &res
);
3564 f_mod(int count
, VALUE
**vals
)
3568 /* initialize VALUEs */
3569 res
.v_subtype
= V_NOSUBTYPE
;
3570 tmp
.v_subtype
= V_NOSUBTYPE
;
3575 tmp
.v_type
= V_NULL
;
3576 modvalue(vals
[0], vals
[1], &tmp
, &res
);
3581 f_quomod(int count
, VALUE
**vals
)
3583 VALUE
*v1
, *v2
, *v3
, *v4
, *v5
;
3587 short s3
, s4
; /* to preserve subtypes of v3, v4 */
3594 if (v3
->v_type
!= V_ADDR
|| v4
->v_type
!= V_ADDR
||
3595 v3
->v_addr
== v4
->v_addr
)
3596 return error_value(E_QUOMOD1
);
3599 if (v5
->v_type
== V_ADDR
)
3601 if (v5
->v_type
!= V_NUM
|| qisfrac(v5
->v_num
) ||
3602 qisneg(v5
->v_num
) || zge31b(v5
->v_num
->num
))
3603 return error_value(E_QUOMOD2
);
3604 rnd
= qtoi(v5
->v_num
);
3608 if (v1
->v_type
== V_ADDR
)
3610 if (v2
->v_type
== V_ADDR
)
3615 if (v1
->v_type
!= V_NUM
|| v2
->v_type
!= V_NUM
||
3616 (v3
->v_type
!= V_NUM
&& v3
->v_type
!= V_NULL
) ||
3617 (v4
->v_type
!= V_NUM
&& v4
->v_type
!= V_NULL
))
3618 return error_value(E_QUOMOD2
);
3623 if ((s3
| s4
) & V_NOASSIGNTO
)
3624 return error_value(E_QUOMOD3
);
3635 res
= qquomod(v1
->v_num
, v2
->v_num
, &v3
->v_num
, &v4
->v_num
, rnd
);
3636 result
.v_type
= V_NUM
;
3637 result
.v_subtype
= V_NOSUBTYPE
;
3638 result
.v_num
= res
? qlink(&_qone_
) : qlink(&_qzero_
);
3643 f_mmin(VALUE
*v1
, VALUE
*v2
)
3647 /* initialize VALUEs */
3648 sixteen
.v_subtype
= V_NOSUBTYPE
;
3649 res
.v_subtype
= V_NOSUBTYPE
;
3651 sixteen
.v_type
= V_NUM
;
3652 sixteen
.v_num
= itoq(16);
3653 modvalue(v1
, v2
, &sixteen
, &res
);
3654 qfree(sixteen
.v_num
);
3660 f_near(int count
, NUMBER
**vals
)
3664 val
= conf
->epsilon
;
3667 return itoq((long) qnear(vals
[0], vals
[1], val
));
3672 f_cfsim(int count
, NUMBER
**vals
)
3676 R
= (count
> 1) ? qtoi(vals
[1]) : conf
->cfsim
;
3677 return qcfsim(vals
[0], R
);
3682 f_cfappr(int count
, NUMBER
**vals
)
3687 R
= (count
> 2) ? qtoi(vals
[2]) : conf
->cfappr
;
3688 q
= (count
> 1) ? vals
[1] : conf
->epsilon
;
3690 return qcfappr(vals
[0], q
, R
);
3699 /* initialize VALUEs */
3700 res
.v_subtype
= V_NOSUBTYPE
;
3701 tmp
.v_subtype
= V_NOSUBTYPE
;
3704 tmp
.v_num
= qlink(&_qone_
);
3705 apprvalue(val
, &tmp
, &tmp
, &res
);
3713 VALUE tmp1
, tmp2
, res
;
3715 /* initialize VALUEs */
3716 res
.v_subtype
= V_NOSUBTYPE
;
3717 tmp1
.v_subtype
= V_NOSUBTYPE
;
3718 tmp2
.v_subtype
= V_NOSUBTYPE
;
3720 tmp1
.v_type
= V_NUM
;
3721 tmp1
.v_num
= qlink(&_qone_
);
3722 tmp2
.v_type
= V_NUM
;
3723 tmp2
.v_num
= qlink(&_qzero_
);
3724 apprvalue(val
, &tmp1
, &tmp2
, &res
);
3730 f_sqrt(int count
, VALUE
**vals
)
3732 VALUE tmp1
, tmp2
, result
;
3734 /* initialize VALUEs */
3735 result
.v_subtype
= V_NOSUBTYPE
;
3736 tmp1
.v_subtype
= V_NOSUBTYPE
;
3737 tmp2
.v_subtype
= V_NOSUBTYPE
;
3742 tmp2
.v_type
= V_NULL
;
3746 tmp1
.v_type
= V_NULL
;
3747 sqrtvalue(vals
[0], &tmp1
, &tmp2
, &result
);
3753 f_root(int count
, VALUE
**vals
)
3755 VALUE
*vp
, err
, result
;
3757 /* initialize VALUEs */
3758 err
.v_subtype
= V_NOSUBTYPE
;
3759 result
.v_subtype
= V_NOSUBTYPE
;
3764 err
.v_num
= conf
->epsilon
;
3768 rootvalue(vals
[0], vals
[1], vp
, &result
);
3774 f_power(int count
, VALUE
**vals
)
3776 VALUE
*vp
, err
, result
;
3778 /* initialize VALUEs */
3779 err
.v_subtype
= V_NOSUBTYPE
;
3780 result
.v_subtype
= V_NOSUBTYPE
;
3785 err
.v_num
= conf
->epsilon
;
3789 powervalue(vals
[0], vals
[1], vp
, &result
);
3795 f_polar(int count
, VALUE
**vals
)
3797 VALUE
*vp
, err
, result
;
3800 /* initialize VALUEs */
3801 err
.v_subtype
= V_NOSUBTYPE
;
3802 result
.v_subtype
= V_NOSUBTYPE
;
3807 err
.v_num
= conf
->epsilon
;
3811 if ((vals
[0]->v_type
!= V_NUM
) || (vals
[1]->v_type
!= V_NUM
))
3812 return error_value(E_POLAR1
);
3813 if ((vp
->v_type
!= V_NUM
) || qisneg(vp
->v_num
) || qiszero(vp
->v_num
))
3814 return error_value(E_POLAR2
);
3815 c
= c_polar(vals
[0]->v_num
, vals
[1]->v_num
, vp
->v_num
);
3817 result
.v_type
= V_COM
;
3819 result
.v_num
= qlink(c
->real
);
3820 result
.v_type
= V_NUM
;
3828 f_ilog(VALUE
*v1
, VALUE
*v2
)
3832 if (v2
->v_type
!= V_NUM
|| qisfrac(v2
->v_num
) || qiszero(v2
->v_num
) ||
3834 return error_value(E_ILOGB
);
3836 switch(v1
->v_type
) {
3838 res
.v_num
= qilog(v1
->v_num
, v2
->v_num
->num
);
3841 res
.v_num
= c_ilog(v1
->v_com
, v2
->v_num
->num
);
3844 return error_value(E_ILOG
);
3847 if (res
.v_num
== NULL
)
3848 return error_value(E_LOGINF
);
3851 res
.v_subtype
= V_NOSUBTYPE
;
3861 switch(vp
->v_type
) {
3863 res
.v_num
= qilog(vp
->v_num
, _two_
);
3866 res
.v_num
= c_ilog(vp
->v_com
, _two_
);
3869 return error_value(E_ILOG2
);
3872 if (res
.v_num
== NULL
)
3873 return error_value(E_LOGINF
);
3876 res
.v_subtype
= V_NOSUBTYPE
;
3886 switch(vp
->v_type
) {
3888 res
.v_num
= qilog(vp
->v_num
, _ten_
);
3891 res
.v_num
= c_ilog(vp
->v_com
, _ten_
);
3894 return error_value(E_ILOG10
);
3897 if (res
.v_num
== NULL
)
3898 return error_value(E_LOGINF
);
3901 res
.v_subtype
= V_NOSUBTYPE
;
3907 f_faccnt(NUMBER
*val1
, NUMBER
*val2
)
3909 if (qisfrac(val1
) || qisfrac(val2
))
3910 math_error("Non-integral argument for fcnt");
3911 return itoq(zdivcount(val1
->num
, val2
->num
));
3916 f_matfill(int count
, VALUE
**vals
)
3918 VALUE
*v1
, *v2
, *v3
;
3921 /* initialize VALUE */
3922 result
.v_subtype
= V_NOSUBTYPE
;
3926 if (v1
->v_type
!= V_ADDR
)
3927 return error_value(E_MATFILL1
);
3929 if (v1
->v_subtype
& V_NOCOPYTO
)
3930 return error_value(E_MATFILL3
);
3931 if (v1
->v_type
!= V_MAT
)
3932 return error_value(E_MATFILL2
);
3933 if (v2
->v_type
== V_ADDR
)
3935 if (v2
->v_subtype
& V_NOASSIGNFROM
)
3936 return error_value(E_MATFILL4
);
3939 if (v3
->v_type
== V_ADDR
)
3941 if (v3
->v_subtype
& V_NOASSIGNFROM
)
3942 return error_value(E_MATFILL4
);
3946 matfill(v1
->v_mat
, v2
, v3
);
3947 result
.v_type
= V_NULL
;
3957 /* initialize VALUE */
3958 result
.v_subtype
= V_NOSUBTYPE
;
3961 if (vp
->v_type
!= V_MAT
)
3962 return error_value(E_MATSUM
);
3965 matsum(vp
->v_mat
, &result
);
3971 f_isident(VALUE
*vp
)
3975 /* initialize VALUEs */
3976 result
.v_type
= V_NUM
;
3977 result
.v_subtype
= V_NOSUBTYPE
;
3979 if (vp
->v_type
== V_MAT
) {
3980 result
.v_num
= itoq((long) matisident(vp
->v_mat
));
3982 result
.v_num
= itoq(0);
3989 f_mattrace(VALUE
*vp
)
3991 if (vp
->v_type
!= V_MAT
)
3992 return error_value(E_MATTRACE1
);
3993 return mattrace(vp
->v_mat
);
3998 f_mattrans(VALUE
*vp
)
4002 /* initialize VALUE */
4003 result
.v_subtype
= V_NOSUBTYPE
;
4005 if (vp
->v_type
!= V_MAT
)
4006 return error_value(E_MATTRANS1
);
4007 if (vp
->v_mat
->m_dim
> 2)
4008 return error_value(E_MATTRANS2
);
4009 result
.v_type
= V_MAT
;
4010 result
.v_mat
= mattrans(vp
->v_mat
);
4018 if (vp
->v_type
!= V_MAT
)
4019 return error_value(E_DET1
);
4021 return matdet(vp
->v_mat
);
4030 /* initialize VALUEs */
4031 result
.v_type
= V_NUM
;
4032 result
.v_subtype
= V_NOSUBTYPE
;
4034 switch(vp
->v_type
) {
4036 result
.v_num
= itoq(vp
->v_obj
->o_actions
->oa_count
);
4039 result
.v_num
= itoq((long) vp
->v_mat
->m_dim
);
4042 return error_value(E_MATDIM
);
4049 f_matmin(VALUE
*v1
, VALUE
*v2
)
4055 /* initialize VALUE */
4056 result
.v_subtype
= V_NOSUBTYPE
;
4058 if (v1
->v_type
!= V_MAT
)
4059 return error_value(E_MATMIN1
);
4060 if (v2
->v_type
!= V_NUM
)
4061 return error_value(E_MATMIN2
);
4063 if (qisfrac(q
) || qisneg(q
) || qiszero(q
))
4064 return error_value(E_MATMIN2
);
4066 if (i
> v1
->v_mat
->m_dim
)
4067 return error_value(E_MATMIN3
);
4068 result
.v_type
= V_NUM
;
4069 result
.v_num
= itoq(v1
->v_mat
->m_min
[i
- 1]);
4075 f_matmax(VALUE
*v1
, VALUE
*v2
)
4081 /* initialize VALUE */
4082 result
.v_subtype
= V_NOSUBTYPE
;
4084 if (v1
->v_type
!= V_MAT
)
4085 return error_value(E_MATMAX1
);
4086 if (v2
->v_type
!= V_NUM
)
4087 return error_value(E_MATMAX2
);
4089 if (qisfrac(q
) || qisneg(q
) || qiszero(q
))
4090 return error_value(E_MATMAX2
);
4092 if (i
> v1
->v_mat
->m_dim
)
4093 return error_value(E_MATMAX3
);
4094 result
.v_type
= V_NUM
;
4095 result
.v_num
= itoq(v1
->v_mat
->m_max
[i
- 1]);
4101 f_cp(VALUE
*v1
, VALUE
*v2
)
4106 /* initialize VALUE */
4107 result
.v_subtype
= V_NOSUBTYPE
;
4109 if ((v1
->v_type
!= V_MAT
) || (v2
->v_type
!= V_MAT
))
4110 return error_value(E_CP1
);
4113 if ((m1
->m_dim
!= 1) || (m2
->m_dim
!= 1))
4114 return error_value(E_CP2
);
4115 if ((m1
->m_size
!= 3) || (m2
->m_size
!= 3))
4116 return error_value(E_CP3
);
4117 result
.v_type
= V_MAT
;
4118 result
.v_mat
= matcross(m1
, m2
);
4124 f_dp(VALUE
*v1
, VALUE
*v2
)
4128 if ((v1
->v_type
!= V_MAT
) || (v2
->v_type
!= V_MAT
))
4129 return error_value(E_DP1
);
4132 if ((m1
->m_dim
!= 1) || (m2
->m_dim
!= 1))
4133 return error_value(E_DP2
);
4134 if (m1
->m_size
!= m2
->m_size
)
4135 return error_value(E_DP3
);
4136 return matdot(m1
, m2
);
4147 /* initialize VALUE */
4148 result
.v_subtype
= V_NOSUBTYPE
;
4150 if (vp
->v_type
!= V_STR
)
4151 return error_value(E_STRLEN
);
4152 c
= vp
->v_str
->s_str
;
4155 result
.v_type
= V_NUM
;
4156 result
.v_num
= itoq(len
);
4162 f_strcmp(VALUE
*v1
, VALUE
*v2
)
4167 /* initialize VALUE */
4168 result
.v_subtype
= V_NOSUBTYPE
;
4170 if (v1
->v_type
!= V_STR
|| v2
->v_type
!= V_STR
)
4171 return error_value(E_STRCMP
);
4173 flag
= stringrel(v1
->v_str
, v2
->v_str
);
4175 result
.v_type
= V_NUM
;
4176 result
.v_num
= itoq((long) flag
);
4182 f_strncmp(VALUE
*v1
, VALUE
*v2
, VALUE
*v3
)
4188 /* initialize VALUE */
4189 result
.v_subtype
= V_NOSUBTYPE
;
4191 if (v1
->v_type
!= V_STR
|| v2
->v_type
!= V_STR
||
4192 v3
->v_type
!= V_NUM
|| qisneg(v3
->v_num
) ||
4193 qisfrac(v3
->v_num
) || zge31b(v3
->v_num
->num
))
4194 return error_value(E_STRNCMP
);
4195 n1
= v1
->v_str
->s_len
;
4196 n2
= v2
->v_str
->s_len
;
4197 n
= qtoi(v3
->v_num
);
4199 v1
->v_str
->s_len
= n
;
4201 v2
->v_str
->s_len
= n
;
4203 flag
= stringrel(v1
->v_str
, v2
->v_str
);
4205 v1
->v_str
->s_len
= n1
;
4206 v2
->v_str
->s_len
= n2
;
4208 result
.v_type
= V_NUM
;
4209 result
.v_num
= itoq((long) flag
);
4215 f_strcat(int count
, VALUE
**vals
)
4223 /* initialize VALUE */
4224 result
.v_subtype
= V_NOSUBTYPE
;
4227 result
.v_type
= V_STR
;
4229 for (i
= 0; i
< count
; i
++, vp
++) {
4230 if ((*vp
)->v_type
!= V_STR
)
4231 return error_value(E_STRCAT
);
4232 c
= (*vp
)->v_str
->s_str
;
4237 result
.v_str
= slink(&_nullstring_
);
4240 c
= (char *) malloc(len
+ 1) ;
4242 math_error("No memory for strcat");
4245 result
.v_str
= stralloc();
4246 result
.v_str
->s_str
= c
;
4247 result
.v_str
->s_len
= len
;
4248 for (vp
= vals
; count
-- > 0; vp
++) {
4249 c1
= (*vp
)->v_str
->s_str
;
4259 f_strcpy(VALUE
*v1
, VALUE
*v2
)
4263 /* initialize VALUE */
4264 result
.v_subtype
= V_NOSUBTYPE
;
4266 if (v1
->v_type
!= V_STR
|| v2
->v_type
!= V_STR
)
4267 return error_value(E_STRCPY
);
4268 result
.v_str
= stringcpy(v1
->v_str
, v2
->v_str
);
4269 result
.v_type
= V_STR
;
4275 f_strncpy(VALUE
*v1
, VALUE
*v2
, VALUE
*v3
)
4280 /* initialize VALUE */
4281 result
.v_subtype
= V_NOSUBTYPE
;
4283 if (v1
->v_type
!= V_STR
|| v2
->v_type
!= V_STR
||
4284 v3
->v_type
!= V_NUM
|| qisfrac(v3
->v_num
) || qisneg(v3
->v_num
))
4285 return error_value(E_STRNCPY
);
4286 if (zge31b(v3
->v_num
->num
))
4287 num
= v2
->v_str
->s_len
;
4289 num
= qtoi(v3
->v_num
);
4290 result
.v_str
= stringncpy(v1
->v_str
, v2
->v_str
, num
);
4291 result
.v_type
= V_STR
;
4297 f_substr(VALUE
*v1
, VALUE
*v2
, VALUE
*v3
)
4305 /* initialize VALUE */
4306 result
.v_subtype
= V_NOSUBTYPE
;
4308 if (v1
->v_type
!= V_STR
)
4309 return error_value(E_SUBSTR1
);
4310 if ((v2
->v_type
!= V_NUM
) || (v3
->v_type
!= V_NUM
))
4311 return error_value(E_SUBSTR2
);
4314 if (qisfrac(q1
) || qisneg(q1
) || qisfrac(q2
) || qisneg(q2
))
4315 return error_value(E_SUBSTR2
);
4320 result
.v_type
= V_STR
;
4321 if (start
>= v1
->v_str
->s_len
|| len
== 0) {
4322 result
.v_str
= slink(&_nullstring_
);
4325 if (len
> v1
->v_str
->s_len
- start
)
4326 len
= v1
->v_str
->s_len
- start
;
4327 cp
= v1
->v_str
->s_str
+ start
;
4328 ccp
= (char *) malloc(len
+ 1);
4330 math_error("No memory for substr");
4333 result
.v_str
= stralloc();
4334 result
.v_str
->s_len
= len
;
4335 result
.v_str
->s_str
= ccp
;
4348 /* initialize VALUE */
4349 result
.v_subtype
= V_NOSUBTYPE
;
4351 switch(vp
->v_type
) {
4353 if (qisfrac(vp
->v_num
))
4354 return error_value(E_CHAR
);
4355 ch
= (char) vp
->v_num
->num
.v
[0];
4356 if (qisneg(vp
->v_num
))
4363 ch
= *vp
->v_str
->s_str
;
4366 return error_value(E_CHAR
);
4368 result
.v_type
= V_STR
;
4369 result
.v_str
= charstring(ch
);
4380 /* initialize VALUE */
4381 result
.v_subtype
= V_NOSUBTYPE
;
4383 switch(vp
->v_type
) {
4385 c
= (OCTET
*)vp
->v_str
->s_str
;
4391 return error_value(E_ORD
);
4394 result
.v_type
= V_NUM
;
4395 result
.v_num
= itoq((long) (*c
& 0xff));
4401 f_protect(int count
, VALUE
**vals
)
4404 VALUE
*v1
, *v2
, *v3
;
4409 /* initialize VALUE */
4410 result
.v_type
= V_NULL
;
4411 result
.v_subtype
= V_NOSUBTYPE
;
4414 have_nblock
= (v1
->v_type
== V_NBLOCK
);
4416 if (v1
->v_type
!= V_ADDR
)
4417 return error_value(E_PROTECT1
);
4421 result
.v_type
= V_NUM
;
4423 result
.v_num
= itoq(v1
->v_nblock
->subtype
);
4425 result
.v_num
= itoq(v1
->v_subtype
);
4429 if (v2
->v_type
== V_ADDR
)
4431 if (v2
->v_type
!= V_NUM
||qisfrac(v2
->v_num
)||zge16b(v2
->v_num
->num
))
4432 return error_value(E_PROTECT2
);
4433 i
= qtoi(v2
->v_num
);
4437 if (v3
->v_type
== V_ADDR
)
4439 if (v3
->v_type
!= V_NUM
|| qisfrac(v3
->v_num
) ||
4440 qisneg(v3
->v_num
) || zge31b(v3
->v_num
->num
))
4441 return error_value(E_PROTECT3
);
4442 depth
= qtoi(v3
->v_num
);
4444 protecttodepth(v1
, i
, depth
);
4454 /* initialize VALUE */
4455 result
.v_subtype
= V_NOSUBTYPE
;
4458 * return information about the number of elements
4460 * This is not the sizeof, see f_sizeof() for that information.
4461 * This is not the memsize, see f_memsize() for that information.
4463 * The size of a file is treated in a special way ... we do
4464 * not use the number of elements, but rather the length
4465 * of the file as would be reported by fsize().
4467 if (vp
->v_type
== V_FILE
) {
4470 result
.v_type
= V_NUM
;
4471 result
.v_num
= itoq(elm_count(vp
));
4482 /* initialize VALUE */
4483 result
.v_type
= V_NUM
;
4484 result
.v_subtype
= V_NOSUBTYPE
;
4487 * return information about memory footprint
4489 * This is not the number of elements, see f_size() for that info.
4490 * This is not the memsize, see f_memsize() for that information.
4492 result
.v_num
= itoq(lsizeof(vp
));
4498 f_memsize(VALUE
*vp
)
4502 /* initialize VALUE */
4503 result
.v_type
= V_NUM
;
4504 result
.v_subtype
= V_NOSUBTYPE
;
4507 * return information about memory footprint
4509 * This is not the number of elements, see f_size() for that info.
4510 * This is not the sizeof, see f_sizeof() for that information.
4512 result
.v_num
= itoq(memsize(vp
));
4518 f_search(int count
, VALUE
**vals
)
4520 VALUE
*v1
, *v2
, *v3
, *v4
;
4521 NUMBER
*start
, *end
;
4529 long l_start
= 0, l_end
= 0;
4532 /* initialize VALUEs */
4533 result
.v_subtype
= V_NOSUBTYPE
;
4534 vsize
.v_subtype
= V_NOSUBTYPE
;
4538 if ((v1
->v_type
== V_FILE
|| v1
->v_type
== V_STR
) &&
4539 v2
->v_type
!= V_STR
)
4540 return error_value(E_SEARCH2
);
4544 if (v3
->v_type
!= V_NUM
&& v3
->v_type
!= V_NULL
)
4545 return error_value(E_SEARCH3
);
4546 if (v3
->v_type
== V_NUM
) {
4549 return error_value(E_SEARCH3
);
4554 if (v4
->v_type
!= V_NUM
&& v4
->v_type
!= V_NULL
)
4555 return error_value(E_SEARCH4
);
4556 if (v4
->v_type
== V_NUM
) {
4559 return error_value(E_SEARCH4
);
4562 result
.v_type
= V_NULL
;
4564 if (vsize
.v_type
!= V_NUM
)
4565 return error_value(E_SEARCH5
);
4568 if (qisneg(start
)) {
4569 start
= qqadd(size
, start
);
4570 if (qisneg(start
)) {
4572 start
= qlink(&_qzero_
);
4575 start
= qlink(start
);
4580 end
= qqadd(size
, end
);
4582 if (qrel(end
, size
) > 0)
4588 if (v1
->v_type
== V_FILE
) {
4589 if (count
== 2|| (count
== 4 &&
4590 (start
== NULL
|| end
== NULL
))) {
4591 i
= ftellid(v1
->v_file
, &pos
);
4598 return error_value(E_SEARCH5
);
4600 if (count
== 2 || (count
== 4 && end
!= NULL
)) {
4609 start
= qlink(&_qzero_
);
4614 len
= v2
->v_str
->s_len
;
4616 zsub(end
->num
, zlen
, &tmp
);
4618 i
= fsearch(v1
->v_file
, v2
->v_str
->s_str
,
4619 start
->num
, tmp
, &indx
);
4622 result
.v_type
= V_NUM
;
4623 result
.v_num
= start
;
4630 return error_value(errno
);
4632 return error_value(E_SEARCH6
);
4634 result
.v_type
= V_NUM
;
4635 result
.v_num
= qalloc();
4636 result
.v_num
->num
= indx
;
4641 start
= qlink(&_qzero_
);
4644 if (qrel(start
, end
) >= 0) {
4651 l_start
= ztolong(start
->num
);
4652 l_end
= ztolong(end
->num
);
4653 switch (v1
->v_type
) {
4655 i
= matsearch(v1
->v_mat
, v2
, l_start
, l_end
, &indx
);
4658 i
= listsearch(v1
->v_list
, v2
, l_start
, l_end
, &indx
);
4661 i
= assocsearch(v1
->v_assoc
, v2
, l_start
, l_end
, &indx
);
4664 i
= stringsearch(v1
->v_str
, v2
->v_str
, l_start
, l_end
,
4670 return error_value(E_SEARCH1
);
4675 result
.v_type
= V_NUM
;
4676 result
.v_num
= qalloc();
4677 result
.v_num
->num
= indx
;
4684 f_rsearch(int count
, VALUE
**vals
)
4686 VALUE
*v1
, *v2
, *v3
, *v4
;
4687 NUMBER
*start
, *end
;
4695 long l_start
= 0, l_end
= 0;
4698 /* initialize VALUEs */
4699 vsize
.v_subtype
= V_NOSUBTYPE
;
4700 result
.v_subtype
= V_NOSUBTYPE
;
4704 if ((v1
->v_type
== V_FILE
|| v1
->v_type
== V_STR
) &&
4705 v2
->v_type
!= V_STR
)
4706 return error_value(E_RSEARCH2
);
4710 if (v3
->v_type
!= V_NUM
&& v3
->v_type
!= V_NULL
)
4711 return error_value(E_RSEARCH3
);
4712 if (v3
->v_type
== V_NUM
) {
4715 return error_value(E_RSEARCH3
);
4720 if (v4
->v_type
!= V_NUM
&& v4
->v_type
!= V_NULL
)
4721 return error_value(E_RSEARCH4
);
4722 if (v4
->v_type
== V_NUM
) {
4725 return error_value(E_RSEARCH3
);
4728 result
.v_type
= V_NULL
;
4730 if (vsize
.v_type
!= V_NUM
)
4731 return error_value(E_RSEARCH5
);
4734 if (qisneg(start
)) {
4735 start
= qqadd(size
, start
);
4736 if (qisneg(start
)) {
4738 start
= qlink(&_qzero_
);
4742 start
= qlink(start
);
4746 end
= qqadd(size
, end
);
4748 if (qrel(end
, size
) > 0)
4754 if (v1
->v_type
== V_FILE
) {
4755 if (count
== 2 || (count
== 4 &&
4756 (start
== NULL
|| end
== NULL
))) {
4757 i
= ftellid(v1
->v_file
, &pos
);
4764 return error_value(E_RSEARCH5
);
4766 if (count
== 2 || (count
== 4 && end
!= NULL
)) {
4774 qlen
= utoq(v2
->v_str
->s_len
);
4775 qtmp
= qsub(size
, qlen
);
4782 qtmp
= qsub(end
, qlen
);
4789 start
= qlink(&_qzero_
);
4790 if (qrel(end
, size
) > 0) {
4796 if (qrel(start
, end
) > 0) {
4801 i
= frsearch(v1
->v_file
, v2
->v_str
->s_str
,
4802 end
->num
,start
->num
, &indx
);
4806 return error_value(errno
);
4808 return error_value(E_RSEARCH6
);
4810 result
.v_type
= V_NUM
;
4811 result
.v_num
= qalloc();
4812 result
.v_num
->num
= indx
;
4823 start
= qlink(&_qzero_
);
4826 start
= qlink(&_qzero_
);
4832 if (qrel(start
, end
) >= 0) {
4837 l_start
= ztolong(start
->num
);
4838 l_end
= ztolong(end
->num
);
4839 switch (v1
->v_type
) {
4841 i
= matrsearch(v1
->v_mat
, v2
, l_start
, l_end
, &indx
);
4844 i
= listrsearch(v1
->v_list
, v2
, l_start
, l_end
, &indx
);
4847 i
= assocrsearch(v1
->v_assoc
, v2
, l_start
,
4851 i
= stringrsearch(v1
->v_str
, v2
->v_str
, l_start
,
4857 return error_value(E_RSEARCH1
);
4862 result
.v_type
= V_NUM
;
4863 result
.v_num
= qalloc();
4864 result
.v_num
->num
= indx
;
4871 f_list(int count
, VALUE
**vals
)
4875 /* initialize VALUE */
4876 result
.v_type
= V_LIST
;
4877 result
.v_subtype
= V_NOSUBTYPE
;
4879 result
.v_list
= listalloc();
4881 insertlistlast(result
.v_list
, *vals
++);
4888 f_assoc(int UNUSED count
, VALUE UNUSED
**vals
)
4892 /* initialize VALUE */
4893 result
.v_type
= V_ASSOC
;
4894 result
.v_subtype
= V_NOSUBTYPE
;
4896 result
.v_assoc
= assocalloc(0L);
4902 f_indices(VALUE
*v1
, VALUE
*v2
)
4907 if (v2
->v_type
!= V_NUM
|| zge31b(v2
->v_num
->num
))
4908 return error_value(E_INDICES2
);
4910 switch (v1
->v_type
) {
4912 lp
= associndices(v1
->v_assoc
, qtoi(v2
->v_num
));
4915 lp
= matindices(v1
->v_mat
, qtoi(v2
->v_num
));
4918 return error_value(E_INDICES1
);
4921 result
.v_type
= V_NULL
;
4922 result
.v_subtype
= V_NOSUBTYPE
;
4924 result
.v_type
= V_LIST
;
4932 f_listinsert(int count
, VALUE
**vals
)
4934 VALUE
*v1
, *v2
, *v3
;
4938 /* initialize VALUE */
4939 result
.v_subtype
= V_NOSUBTYPE
;
4942 if ((v1
->v_type
!= V_ADDR
) || (v1
->v_addr
->v_type
!= V_LIST
))
4943 return error_value(E_INSERT1
);
4944 if (v1
->v_addr
->v_subtype
& V_NOREALLOC
)
4945 return error_value(E_LIST1
);
4948 if (v2
->v_type
== V_ADDR
)
4950 if ((v2
->v_type
!= V_NUM
) || qisfrac(v2
->v_num
))
4951 return error_value(E_INSERT2
);
4952 pos
= qtoi(v2
->v_num
);
4954 while (--count
> 0) {
4956 if (v3
->v_type
== V_ADDR
)
4958 insertlistmiddle(v1
->v_addr
->v_list
, pos
++, v3
);
4960 result
.v_type
= V_NULL
;
4966 f_listpush(int count
, VALUE
**vals
)
4971 /* initialize VALUE */
4972 result
.v_subtype
= V_NOSUBTYPE
;
4975 if ((v1
->v_type
!= V_ADDR
) || (v1
->v_addr
->v_type
!= V_LIST
))
4976 return error_value(E_PUSH
);
4977 if (v1
->v_addr
->v_subtype
& V_NOREALLOC
)
4978 return error_value(E_LIST3
);
4980 while (--count
> 0) {
4982 if (v2
->v_type
== V_ADDR
)
4984 insertlistfirst(v1
->v_addr
->v_list
, v2
);
4986 result
.v_type
= V_NULL
;
4992 f_listappend(int count
, VALUE
**vals
)
4997 /* initialize VALUE */
4998 result
.v_subtype
= V_NOSUBTYPE
;
5001 if ((v1
->v_type
!= V_ADDR
) || (v1
->v_addr
->v_type
!= V_LIST
))
5002 return error_value(E_APPEND
);
5003 if (v1
->v_addr
->v_subtype
& V_NOREALLOC
)
5004 return error_value(E_LIST4
);
5006 while (--count
> 0) {
5008 if (v2
->v_type
== V_ADDR
)
5010 insertlistlast(v1
->v_addr
->v_list
, v2
);
5012 result
.v_type
= V_NULL
;
5018 f_listdelete(VALUE
*v1
, VALUE
*v2
)
5022 /* initialize VALUE */
5023 result
.v_subtype
= V_NOSUBTYPE
;
5025 if ((v1
->v_type
!= V_ADDR
) || (v1
->v_addr
->v_type
!= V_LIST
))
5026 return error_value(E_DELETE1
);
5027 if (v1
->v_addr
->v_subtype
& V_NOREALLOC
)
5028 return error_value(E_LIST2
);
5030 if (v2
->v_type
== V_ADDR
)
5032 if ((v2
->v_type
!= V_NUM
) || qisfrac(v2
->v_num
))
5033 return error_value(E_DELETE2
);
5034 removelistmiddle(v1
->v_addr
->v_list
, qtoi(v2
->v_num
), &result
);
5040 f_listpop(VALUE
*vp
)
5044 if ((vp
->v_type
!= V_ADDR
) || (vp
->v_addr
->v_type
!= V_LIST
))
5045 return error_value(E_POP
);
5047 if (vp
->v_addr
->v_subtype
& V_NOREALLOC
)
5048 return error_value(E_LIST5
);
5050 removelistfirst(vp
->v_addr
->v_list
, &result
);
5056 f_listremove(VALUE
*vp
)
5060 if ((vp
->v_type
!= V_ADDR
) || (vp
->v_addr
->v_type
!= V_LIST
))
5061 return error_value(E_REMOVE
);
5063 if (vp
->v_addr
->v_subtype
& V_NOREALLOC
)
5064 return error_value(E_LIST6
);
5066 removelistlast(vp
->v_addr
->v_list
, &result
);
5072 * Return the current user time of calc in seconds.
5077 #if defined(HAVE_GETRUSAGE)
5078 struct rusage usage
; /* system resource usage */
5079 int who
= RUSAGE_SELF
; /* obtain time for just this process */
5080 int status
; /* getrusage() return code */
5081 NUMBER
*ret
; /* CPU time to return */
5082 NUMBER
*secret
; /* whole sconds of CPU time to return */
5083 NUMBER
*usecret
; /* microseconds of CPU time to return */
5085 /* get the resource informaion for ourself */
5086 status
= getrusage(who
, &usage
);
5088 /* system call error, so return 0 */
5089 return qlink(&_qzero_
);
5093 secret
= stoq(usage
.ru_utime
.tv_sec
);
5094 usecret
= iitoq((long)usage
.ru_utime
.tv_usec
, 1000000L);
5095 ret
= qqadd(secret
, usecret
);
5099 /* return user CPU time */
5102 #else /* HAVE_GETRUSAGE */
5103 /* not a POSIX system */
5104 return qlink(&_qzero_
);
5105 #endif /* HAVE_GETRUSAGE */
5110 * Return the current kernel time of calc in seconds.
5111 * This is the kernel mode time only.
5116 #if defined(HAVE_GETRUSAGE)
5117 struct rusage usage
; /* system resource usage */
5118 int who
= RUSAGE_SELF
; /* obtain time for just this process */
5119 int status
; /* getrusage() return code */
5120 NUMBER
*ret
; /* CPU time to return */
5121 NUMBER
*secret
; /* whole sconds of CPU time to return */
5122 NUMBER
*usecret
; /* microseconds of CPU time to return */
5124 /* get the resource informaion for ourself */
5125 status
= getrusage(who
, &usage
);
5127 /* system call error, so return 0 */
5128 return qlink(&_qzero_
);
5131 /* add kernel time */
5132 secret
= stoq(usage
.ru_stime
.tv_sec
);
5133 usecret
= iitoq((long)usage
.ru_stime
.tv_usec
, 1000000L);
5134 ret
= qqadd(secret
, usecret
);
5138 /* return kernel CPU time */
5141 #else /* HAVE_GETRUSAGE */
5142 /* not a POSIX system */
5143 return qlink(&_qzero_
);
5144 #endif /* HAVE_GETRUSAGE */
5149 * Return the current user and kernel time of calc in seconds.
5154 #if defined(HAVE_GETRUSAGE)
5155 struct rusage usage
; /* system resource usage */
5156 int who
= RUSAGE_SELF
; /* obtain time for just this process */
5157 int status
; /* getrusage() return code */
5158 NUMBER
*user
; /* user CPU time to return */
5159 NUMBER
*sys
; /* kernel CPU time to return */
5160 NUMBER
*ret
; /* total CPU time to return */
5161 NUMBER
*secret
; /* whole sconds of CPU time to return */
5162 NUMBER
*usecret
; /* microseconds of CPU time to return */
5164 /* get the resource informaion for ourself */
5165 status
= getrusage(who
, &usage
);
5167 /* system call error, so return 0 */
5168 return qlink(&_qzero_
);
5171 /* add kernel time */
5172 secret
= stoq(usage
.ru_stime
.tv_sec
);
5173 usecret
= iitoq((long)usage
.ru_stime
.tv_usec
, 1000000L);
5174 sys
= qqadd(secret
, usecret
);
5179 secret
= stoq(usage
.ru_utime
.tv_sec
);
5180 usecret
= iitoq((long)usage
.ru_utime
.tv_usec
, 1000000L);
5181 user
= qqadd(secret
, usecret
);
5185 /* total time is user + kernel */
5186 ret
= qqadd(user
, sys
);
5190 /* return CPU time */
5193 #else /* HAVE_GETRUSAGE */
5194 /* not a POSIX system */
5195 return qlink(&_qzero_
);
5196 #endif /* HAVE_GETRUSAGE */
5201 * return the number of second since the Epoch (00:00:00 1 Jan 1970 UTC).
5206 return itoq((long) time(0));
5211 * time in asctime()/ctime() format
5217 time_t now
; /* the current time */
5219 /* initialize VALUE */
5220 res
.v_subtype
= V_NOSUBTYPE
;
5225 res
.v_str
= makenewstring(ctime(&now
));
5231 f_fopen(VALUE
*v1
, VALUE
*v2
)
5237 /* initialize VALUE */
5238 result
.v_subtype
= V_NOSUBTYPE
;
5240 /* check for a valid mode [rwa][b+\0][b+\0] */
5241 if (v1
->v_type
!= V_STR
|| v2
->v_type
!= V_STR
)
5242 return error_value(E_FOPEN1
);
5243 mode
= v2
->v_str
->s_str
;
5244 if ((*mode
!= 'r') && (*mode
!= 'w') && (*mode
!= 'a'))
5245 return error_value(E_FOPEN2
);
5246 if (mode
[1] != '\0') {
5247 if (mode
[1] != '+' && mode
[1] != 'b')
5248 return error_value(E_FOPEN2
);
5249 if (mode
[2] != '\0') {
5250 if ((mode
[2] != '+' && mode
[2] != 'b') ||
5252 return error_value(E_FOPEN2
);
5253 if (mode
[3] != '\0')
5254 return error_value(E_FOPEN2
);
5260 id
= openid(v1
->v_str
->s_str
, v2
->v_str
->s_str
);
5261 if (id
== FILEID_NONE
)
5262 return error_value(errno
);
5264 return error_value(-id
);
5265 result
.v_type
= V_FILE
;
5272 f_fpathopen(int count
, VALUE
**vals
)
5278 /* initialize VALUE */
5279 result
.v_subtype
= V_NOSUBTYPE
;
5281 /* check for valid strongs */
5282 if (vals
[0]->v_type
!= V_STR
|| vals
[1]->v_type
!= V_STR
) {
5283 return error_value(E_FPATHOPEN1
);
5285 if (count
== 3 && vals
[2]->v_type
!= V_STR
) {
5286 return error_value(E_FPATHOPEN1
);
5289 /* check for a valid mode [rwa][b+\0][b+\0] */
5290 mode
= vals
[1]->v_str
->s_str
;
5291 if ((*mode
!= 'r') && (*mode
!= 'w') && (*mode
!= 'a'))
5292 return error_value(E_FPATHOPEN2
);
5293 if (mode
[1] != '\0') {
5294 if (mode
[1] != '+' && mode
[1] != 'b')
5295 return error_value(E_FPATHOPEN2
);
5296 if (mode
[2] != '\0') {
5297 if ((mode
[2] != '+' && mode
[2] != 'b') ||
5299 return error_value(E_FPATHOPEN2
);
5300 if (mode
[3] != '\0')
5301 return error_value(E_FPATHOPEN2
);
5305 /* try to open along a path */
5308 id
= openpathid(vals
[0]->v_str
->s_str
,
5309 vals
[1]->v_str
->s_str
,
5312 id
= openpathid(vals
[0]->v_str
->s_str
,
5313 vals
[1]->v_str
->s_str
,
5314 vals
[2]->v_str
->s_str
);
5316 if (id
== FILEID_NONE
)
5317 return error_value(errno
);
5319 return error_value(-id
);
5320 result
.v_type
= V_FILE
;
5327 f_freopen(int count
, VALUE
**vals
)
5333 /* initialize VALUE */
5334 result
.v_subtype
= V_NOSUBTYPE
;
5336 /* check for a valid mode [rwa][b+\0][b+\0] */
5337 if (vals
[0]->v_type
!= V_FILE
)
5338 return error_value(E_FREOPEN1
);
5339 if (vals
[1]->v_type
!= V_STR
)
5340 return error_value(E_FREOPEN2
);
5341 mode
= vals
[1]->v_str
->s_str
;
5342 if ((*mode
!= 'r') && (*mode
!= 'w') && (*mode
!= 'a'))
5343 return error_value(E_FREOPEN2
);
5344 if (mode
[1] != '\0') {
5345 if (mode
[1] != '+' && mode
[1] != 'b')
5346 return error_value(E_FREOPEN2
);
5347 if (mode
[2] != '\0') {
5348 if ((mode
[2] != '+' && mode
[2] != 'b') ||
5350 return error_value(E_FOPEN2
);
5351 if (mode
[3] != '\0')
5352 return error_value(E_FREOPEN2
);
5359 id
= reopenid(vals
[0]->v_file
, mode
, NULL
);
5361 if (vals
[2]->v_type
!= V_STR
)
5362 return error_value(E_FREOPEN3
);
5363 id
= reopenid(vals
[0]->v_file
, mode
,
5364 vals
[2]->v_str
->s_str
);
5367 if (id
== FILEID_NONE
)
5368 return error_value(errno
);
5369 result
.v_type
= V_NULL
;
5375 f_errno(int count
, VALUE
**vals
)
5381 /* initialize VALUE */
5382 result
.v_type
= V_NUM
;
5383 result
.v_subtype
= V_NOSUBTYPE
;
5389 if (vp
->v_type
<= 0) {
5390 newerr
= (int) -vp
->v_type
;
5391 (void) set_errno(newerr
);
5392 result
.v_num
= itoq((long) newerr
);
5396 /* arg must be an integer */
5397 if (vp
->v_type
!= V_NUM
|| qisfrac(vp
->v_num
) ||
5398 qisneg(vp
->v_num
) || zge16b(vp
->v_num
->num
)) {
5399 math_error("errno argument out of range");
5402 newerr
= (int) ztoi(vp
->v_num
->num
);
5404 olderr
= set_errno(newerr
);
5406 result
.v_num
= itoq((long) olderr
);
5413 f_errcount(int count
, VALUE
**vals
)
5415 int newcount
, oldcount
;
5419 /* initialize VALUE */
5420 result
.v_subtype
= V_NOSUBTYPE
;
5426 /* arg must be an integer */
5427 if (vp
->v_type
!= V_NUM
|| qisfrac(vp
->v_num
) ||
5428 qisneg(vp
->v_num
) || zge31b(vp
->v_num
->num
)) {
5429 math_error("errcount argument out of range");
5432 newcount
= (int) ztoi(vp
->v_num
->num
);
5434 oldcount
= set_errcount(newcount
);
5436 result
.v_type
= V_NUM
;
5437 result
.v_num
= itoq((long) oldcount
);
5443 f_errmax(int count
, VALUE
**vals
)
5449 /* initialize VALUE */
5450 result
.v_subtype
= V_NOSUBTYPE
;
5456 if (vp
->v_type
!= V_NUM
|| qisfrac(vp
->v_num
) ||
5457 zge31b(vp
->v_num
->num
) || zltnegone(vp
->v_num
->num
)) {
5459 "Out-of-range arg for errmax ignored\n");
5461 errmax
= ztoi(vp
->v_num
->num
);
5465 result
.v_type
= V_NUM
;
5466 result
.v_num
= itoq((long) oldmax
);
5472 f_stoponerror(int count
, VALUE
**vals
)
5478 /* initialize VALUE */
5479 result
.v_subtype
= V_NOSUBTYPE
;
5481 oldval
= stoponerror
;
5485 if (vp
->v_type
!= V_NUM
|| qisfrac(vp
->v_num
) ||
5486 zge31b(vp
->v_num
->num
) || zltnegone(vp
->v_num
->num
)) {
5488 "Out-of-range arg for stoponerror ignored\n");
5490 stoponerror
= ztoi(vp
->v_num
->num
);
5494 result
.v_type
= V_NUM
;
5495 result
.v_num
= itoq((long) oldval
);
5500 f_fclose(int count
, VALUE
**vals
)
5506 /* initialize VALUE */
5507 result
.v_subtype
= V_NOSUBTYPE
;
5513 for (n
= 0; n
< count
; n
++) {
5515 if (vp
->v_type
!= V_FILE
)
5516 return error_value(E_FCLOSE1
);
5518 for (n
= 0; n
< count
; n
++) {
5520 i
= closeid(vp
->v_file
);
5522 return error_value(E_REWIND2
);
5526 return error_value(errno
);
5527 result
.v_type
= V_NULL
;
5533 f_rm(int count
, VALUE
**vals
)
5536 int force
; /* TRUE -> -f was given as 1st arg */
5540 /* initialize VALUE */
5541 result
.v_subtype
= V_NOSUBTYPE
;
5547 return error_value(E_WRPERM
);
5552 for (i
=0; i
< count
; ++i
) {
5553 if (vals
[i
]->v_type
!= V_STR
)
5554 return error_value(E_RM1
);
5555 if (vals
[i
]->v_str
->s_str
[0] == '\0')
5556 return error_value(E_RM1
);
5560 * look for a leading -f option
5562 force
= (strcmp(vals
[0]->v_str
->s_str
, "-f") == 0);
5571 for (i
=0; i
< count
; ++i
) {
5572 j
= remove(vals
[i
]->v_str
->s_str
);
5573 if (!force
&& j
< 0)
5574 return error_value(errno
);
5576 result
.v_type
= V_NULL
;
5577 result
.v_subtype
= V_NOSUBTYPE
;
5583 f_newerror(int count
, VALUE
**vals
)
5590 if (count
> 0 && vals
[0]->v_type
== V_STR
)
5591 str
= vals
[0]->v_str
->s_str
;
5592 if (str
== NULL
|| str
[0] == '\0')
5594 if (nexterrnum
== E_USERDEF
)
5595 initstr(&newerrorstr
);
5596 index
= findstr(&newerrorstr
, str
);
5598 errnum
= E_USERDEF
+ index
;
5600 if (nexterrnum
== 32767)
5601 math_error("Too many new error values");
5602 errnum
= nexterrnum
++;
5603 addstr(&newerrorstr
, str
);
5605 return error_value(errnum
);
5610 f_strerror(int count
, VALUE
**vals
)
5617 /* initialize VALUE */
5618 result
.v_subtype
= V_NOSUBTYPE
;
5623 if (vp
->v_type
< 0) {
5624 i
= (long) -vp
->v_type
;
5626 if (vp
->v_type
!= V_NUM
|| qisfrac(vp
->v_num
))
5627 return error_value(E_STRERROR1
);
5628 i
= qtoi(vp
->v_num
);
5629 if (i
< 0 || i
> 32767)
5630 return error_value(E_STRERROR2
);
5636 /* setup return type */
5637 result
.v_type
= V_STR
;
5639 /* change the meaning of error 0 */
5643 /* firewall - return generic error string if it is not assigned */
5644 if (i
>= nexterrnum
|| (i
> E__HIGHEST
&& i
< E_USERDEF
)
5645 || (i
< E__BASE
&& strerror(i
) == NULL
)) {
5646 cp
= (char *) malloc(sizeof("Error 1234567890")+1);
5648 math_error("Out of memory for strerror");
5651 sprintf(cp
, "Unknown error %ld", i
);
5652 result
.v_str
= makestring(cp
);
5660 /* user-described error */
5661 } else if (i
>= E_USERDEF
) {
5662 cp
= namestr(&newerrorstr
, i
- E_USERDEF
);
5664 /* calc-described error */
5666 cp
= (char *)error_table
[i
- E__BASE
];
5669 /* return result as a V_STR */
5670 result
.v_str
= makenewstring(cp
);
5681 /* initialize VALUE */
5682 result
.v_subtype
= V_NOSUBTYPE
;
5684 if (vp
->v_type
!= V_FILE
)
5685 return error_value(E_FERROR1
);
5686 i
= errorid(vp
->v_file
);
5688 return error_value(E_FERROR2
);
5689 result
.v_type
= V_NUM
;
5690 result
.v_num
= itoq((long) i
);
5701 /* initialize VALUE */
5702 result
.v_subtype
= V_NOSUBTYPE
;
5704 if (vp
->v_type
!= V_FILE
)
5705 return error_value(E_FEOF1
);
5706 i
= eofid(vp
->v_file
);
5708 return error_value(E_FEOF2
);
5709 result
.v_type
= V_NUM
;
5710 result
.v_num
= itoq((long) i
);
5716 f_fflush(int count
, VALUE
**vals
)
5721 /* initialize VALUE */
5722 result
.v_subtype
= V_NOSUBTYPE
;
5727 #if !defined(_WIN32)
5729 #endif /* Windoz free systems */
5731 for (n
= 0; n
< count
; n
++) {
5732 if (vals
[n
]->v_type
!= V_FILE
)
5733 return error_value(E_FFLUSH
);
5735 for (n
= 0; n
< count
; n
++) {
5736 i
|= flushid(vals
[n
]->v_file
);
5740 return error_value(errno
);
5741 result
.v_type
= V_NULL
;
5747 f_error(int count
, VALUE
**vals
)
5755 if (vp
->v_type
<= 0) {
5756 r
= (long) -vp
->v_type
;
5758 if (vp
->v_type
!= V_NUM
|| qisfrac(vp
->v_num
)) {
5761 r
= qtoi(vp
->v_num
);
5762 if (r
< 0 || r
>= 32768)
5770 return error_value(r
);
5775 f_iserror(VALUE
*vp
)
5779 /* initialize VALUE */
5780 res
.v_subtype
= V_NOSUBTYPE
;
5783 res
.v_num
= itoq((long)((vp
->v_type
< 0) ? - vp
->v_type
: 0));
5792 ZVALUE len
; /* file length */
5795 /* initialize VALUE */
5796 result
.v_subtype
= V_NOSUBTYPE
;
5798 if (vp
->v_type
!= V_FILE
)
5799 return error_value(E_FSIZE1
);
5800 i
= getsize(vp
->v_file
, &len
);
5802 return error_value(errno
);
5804 return error_value(E_FSIZE2
);
5805 result
.v_type
= V_NUM
;
5806 result
.v_num
= qalloc();
5807 result
.v_num
->num
= len
;
5813 f_fseek(int count
, VALUE
**vals
)
5819 /* initialize VALUE */
5820 result
.v_subtype
= V_NOSUBTYPE
;
5824 if (vals
[0]->v_type
!= V_FILE
)
5825 return error_value(E_FSEEK1
);
5826 if (vals
[1]->v_type
!= V_NUM
|| qisfrac(vals
[1]->v_num
))
5827 return error_value(E_FSEEK2
);
5831 if (vals
[2]->v_type
!= V_NUM
|| qisfrac(vals
[2]->v_num
) ||
5832 qisneg(vals
[2]->v_num
))
5833 return error_value(E_FSEEK2
);
5834 if (vals
[2]->v_num
->num
.len
> 1)
5835 return error_value (E_FSEEK2
);
5836 whence
= (int)(unsigned int)(vals
[2]->v_num
->num
.v
[0]);
5838 return error_value (E_FSEEK2
);
5841 i
= fseekid(vals
[0]->v_file
, vals
[1]->v_num
->num
, whence
);
5842 result
.v_type
= V_NULL
;
5844 return error_value(errno
);
5846 return error_value(E_FSEEK3
);
5855 ZVALUE pos
; /* current file position */
5858 /* initialize VALUE */
5859 result
.v_subtype
= V_NOSUBTYPE
;
5862 if (vp
->v_type
!= V_FILE
)
5863 return error_value(E_FTELL1
);
5864 i
= ftellid(vp
->v_file
, &pos
);
5866 return error_value(E_FTELL2
);
5868 result
.v_type
= V_NUM
;
5869 result
.v_num
= qalloc();
5870 result
.v_num
->num
= pos
;
5876 f_rewind(int count
, VALUE
**vals
)
5881 /* initialize VALUE */
5882 result
.v_subtype
= V_NOSUBTYPE
;
5888 for (n
= 0; n
< count
; n
++) {
5889 if (vals
[n
]->v_type
!= V_FILE
)
5890 return error_value(E_REWIND1
);
5892 for (n
= 0; n
< count
; n
++) {
5893 if (rewindid(vals
[n
]->v_file
) != 0) {
5894 return error_value(E_REWIND2
);
5898 result
.v_type
= V_NULL
;
5904 f_fprintf(int count
, VALUE
**vals
)
5909 /* initialize VALUE */
5910 result
.v_subtype
= V_NOSUBTYPE
;
5912 if (vals
[0]->v_type
!= V_FILE
)
5913 return error_value(E_FPRINTF1
);
5914 if (vals
[1]->v_type
!= V_STR
)
5915 return error_value(E_FPRINTF2
);
5916 i
= idprintf(vals
[0]->v_file
, vals
[1]->v_str
->s_str
,
5917 count
- 2, vals
+ 2);
5919 return error_value(E_FPRINTF3
);
5920 result
.v_type
= V_NULL
;
5926 strscan(char *s
, int count
, VALUE
**vals
)
5934 /* initialize VALUEs */
5935 val
.v_subtype
= V_NOSUBTYPE
;
5936 result
.v_subtype
= V_NOSUBTYPE
;
5939 while (*s
!= '\0') {
5941 while ((ch
= *++s
)) {
5942 if (!isspace((int)ch
))
5945 if (ch
== '\0' || count
-- == 0)
5948 while ((ch
= *++s
)) {
5949 if (isspace((int)ch
))
5955 val
.v_str
= makenewstring(s0
);
5956 result
= f_eval(&val
);
5958 if (var
->v_type
== V_ADDR
) {
5970 filescan(FILEID id
, int count
, VALUE
**vals
)
5979 /* initialize VALUEs */
5981 val
.v_subtype
= V_NOSUBTYPE
;
5982 result
.v_subtype
= V_NOSUBTYPE
;
5984 while (count
-- > 0) {
5986 i
= readid(id
, 6, &str
);
5994 result
= f_eval(&val
);
5996 if (var
->v_type
== V_ADDR
) {
6007 f_scan(int count
, VALUE
**vals
)
6013 /* initialize VALUEs */
6014 result
.v_subtype
= V_NOSUBTYPE
;
6018 result
.v_type
= V_NULL
;
6022 i
= strscan(cp
, count
, vals
);
6023 result
.v_type
= V_NUM
;
6024 result
.v_num
= itoq((long) i
);
6030 f_strscan(int count
, VALUE
**vals
)
6036 /* initialize VALUE */
6037 result
.v_subtype
= V_NOSUBTYPE
;
6040 if (vp
->v_type
== V_ADDR
)
6042 if (vp
->v_type
!= V_STR
)
6043 return error_value(E_STRSCAN
);
6045 i
= strscan(vp
->v_str
->s_str
, count
- 1, vals
+ 1);
6047 result
.v_type
= V_NUM
;
6048 result
.v_num
= itoq((long) i
);
6054 f_fscan(int count
, VALUE
**vals
)
6060 /* initialize VALUE */
6061 result
.v_subtype
= V_NOSUBTYPE
;
6065 if (vp
->v_type
== V_ADDR
)
6067 if (vp
->v_type
!= V_FILE
)
6068 return error_value(E_FSCAN1
);
6070 i
= filescan(vp
->v_file
, count
- 1, vals
+ 1);
6073 return error_value(errno
);
6075 return error_value(E_FSCAN2
);
6077 result
.v_type
= V_NUM
;
6078 result
.v_num
= itoq((long) i
);
6084 f_scanf(int count
, VALUE
**vals
)
6090 /* initialize VALUE */
6091 result
.v_subtype
= V_NOSUBTYPE
;
6094 if (vp
->v_type
== V_ADDR
)
6096 if (vp
->v_type
!= V_STR
)
6097 return error_value(E_SCANF1
);
6098 for (i
= 1; i
< count
; i
++) {
6099 if (vals
[i
]->v_type
!= V_ADDR
)
6100 return error_value(E_SCANF2
);
6102 i
= fscanfid(FILEID_STDIN
, vp
->v_str
->s_str
, count
- 1, vals
+ 1);
6104 return error_value(E_SCANF3
);
6105 result
.v_type
= V_NUM
;
6106 result
.v_num
= itoq((long) i
);
6112 f_strscanf(int count
, VALUE
**vals
)
6118 /* initialize VALUE */
6119 result
.v_subtype
= V_NOSUBTYPE
;
6123 if (vp
->v_type
== V_ADDR
)
6125 if (vp
->v_type
!= V_STR
)
6126 return error_value(E_STRSCANF1
);
6128 if (vq
->v_type
== V_ADDR
)
6130 if (vq
->v_type
!= V_STR
)
6131 return error_value(E_STRSCANF2
);
6132 for (i
= 2; i
< count
; i
++) {
6133 if (vals
[i
]->v_type
!= V_ADDR
)
6134 return error_value(E_STRSCANF3
);
6136 i
= scanfstr(vp
->v_str
->s_str
, vq
->v_str
->s_str
,
6137 count
- 2, vals
+ 2);
6139 return error_value(errno
);
6141 return error_value(E_STRSCANF4
);
6142 result
.v_type
= V_NUM
;
6143 result
.v_num
= itoq((long) i
);
6149 f_fscanf(int count
, VALUE
**vals
)
6155 /* initialize VALUE */
6156 result
.v_subtype
= V_NOSUBTYPE
;
6159 if (vp
->v_type
== V_ADDR
)
6161 if (vp
->v_type
!= V_FILE
)
6162 return error_value(E_FSCANF1
);
6164 if (sp
->v_type
== V_ADDR
)
6166 if (sp
->v_type
!= V_STR
)
6167 return error_value(E_FSCANF2
);
6168 for (i
= 0; i
< count
- 2; i
++) {
6169 if (vals
[i
]->v_type
!= V_ADDR
)
6170 return error_value(E_FSCANF3
);
6172 i
= fscanfid(vp
->v_file
, sp
->v_str
->s_str
, count
- 2, vals
);
6174 result
.v_type
= V_NULL
;
6178 return error_value(E_FSCANF4
);
6179 result
.v_type
= V_NUM
;
6180 result
.v_num
= itoq((long) i
);
6186 f_fputc(VALUE
*v1
, VALUE
*v2
)
6193 /* initialize VALUE */
6194 result
.v_subtype
= V_NOSUBTYPE
;
6196 if (v1
->v_type
!= V_FILE
)
6197 return error_value(E_FPUTC1
);
6198 switch (v2
->v_type
) {
6200 ch
= v2
->v_str
->s_str
[0];
6205 return error_value(E_FPUTC2
);
6207 ch
= qisneg(q
) ? (int)(-q
->num
.v
[0] & 0xff) :
6208 (int)(q
->num
.v
[0] & 0xff);
6214 return error_value(E_FPUTC2
);
6216 i
= idfputc(v1
->v_file
, ch
);
6218 return error_value(E_FPUTC3
);
6219 result
.v_type
= V_NULL
;
6225 f_fputs(int count
, VALUE
**vals
)
6230 /* initialize VALUE */
6231 result
.v_subtype
= V_NOSUBTYPE
;
6233 if (vals
[0]->v_type
!= V_FILE
)
6234 return error_value(E_FPUTS1
);
6235 for (i
= 1; i
< count
; i
++) {
6236 if (vals
[i
]->v_type
!= V_STR
)
6237 return error_value(E_FPUTS2
);
6239 for (i
= 1; i
< count
; i
++) {
6240 err
= idfputs(vals
[0]->v_file
, vals
[i
]->v_str
);
6242 return error_value(E_FPUTS3
);
6244 result
.v_type
= V_NULL
;
6250 f_fputstr(int count
, VALUE
**vals
)
6255 /* initialize VALUE */
6256 result
.v_subtype
= V_NOSUBTYPE
;
6258 if (vals
[0]->v_type
!= V_FILE
)
6259 return error_value(E_FPUTSTR1
);
6260 for (i
= 1; i
< count
; i
++) {
6261 if (vals
[i
]->v_type
!= V_STR
)
6262 return error_value(E_FPUTSTR2
);
6264 for (i
= 1; i
< count
; i
++) {
6265 err
= idfputstr(vals
[0]->v_file
,
6266 vals
[i
]->v_str
->s_str
);
6268 return error_value(E_FPUTSTR3
);
6270 result
.v_type
= V_NULL
;
6276 f_printf(int count
, VALUE
**vals
)
6281 /* initialize VALUE */
6282 result
.v_subtype
= V_NOSUBTYPE
;
6284 if (vals
[0]->v_type
!= V_STR
)
6285 return error_value(E_PRINTF1
);
6286 i
= idprintf(FILEID_STDOUT
, vals
[0]->v_str
->s_str
,
6287 count
- 1, vals
+ 1);
6289 return error_value(E_PRINTF2
);
6290 result
.v_type
= V_NULL
;
6296 f_strprintf(int count
, VALUE
**vals
)
6302 /* initialize VALUE */
6303 result
.v_subtype
= V_NOSUBTYPE
;
6305 if (vals
[0]->v_type
!= V_STR
)
6306 return error_value(E_STRPRINTF1
);
6308 i
= idprintf(FILEID_STDOUT
, vals
[0]->v_str
->s_str
,
6309 count
- 1, vals
+ 1);
6311 free(math_getdivertedio());
6312 return error_value(E_STRPRINTF2
);
6314 cp
= math_getdivertedio();
6315 result
.v_type
= V_STR
;
6316 result
.v_str
= makenewstring(cp
);
6328 /* initialize VALUE */
6329 result
.v_subtype
= V_NOSUBTYPE
;
6331 if (vp
->v_type
!= V_FILE
)
6332 return error_value(E_FGETC1
);
6333 ch
= getcharid(vp
->v_file
);
6335 return error_value(E_FGETC2
);
6336 result
.v_type
= V_NULL
;
6338 result
.v_type
= V_STR
;
6339 result
.v_str
= charstring(ch
);
6346 f_ungetc(VALUE
*v1
, VALUE
*v2
)
6353 /* initialize VALUE */
6354 result
.v_subtype
= V_NOSUBTYPE
;
6357 if (v1
->v_type
!= V_FILE
)
6358 return error_value(E_UNGETC1
);
6359 switch (v2
->v_type
) {
6361 ch
= v2
->v_str
->s_str
[0];
6366 return error_value(E_UNGETC2
);
6367 ch
= qisneg(q
) ? (int)(-q
->num
.v
[0] & 0xff) :
6368 (int)(q
->num
.v
[0] & 0xff);
6371 return error_value(E_UNGETC2
);
6373 i
= idungetc(v1
->v_file
, ch
);
6375 return error_value(errno
);
6377 return error_value(E_UNGETC3
);
6378 result
.v_type
= V_NULL
;
6384 f_fgetline(VALUE
*vp
)
6390 /* initialize VALUE */
6391 result
.v_subtype
= V_NOSUBTYPE
;
6393 if (vp
->v_type
!= V_FILE
)
6394 return error_value(E_FGETLINE1
);
6395 i
= readid(vp
->v_file
, 9, &str
);
6397 return error_value(E_FGETLINE2
);
6398 result
.v_type
= V_NULL
;
6400 result
.v_type
= V_STR
;
6414 /* initialize VALUE */
6415 result
.v_subtype
= V_NOSUBTYPE
;
6417 if (vp
->v_type
!= V_FILE
)
6418 return error_value(E_FGETS1
);
6419 i
= readid(vp
->v_file
, 1, &str
);
6421 return error_value(E_FGETS2
);
6422 result
.v_type
= V_NULL
;
6424 result
.v_type
= V_STR
;
6432 f_fgetstr(VALUE
*vp
)
6438 /* initialize VALUE */
6439 result
.v_subtype
= V_NOSUBTYPE
;
6441 if (vp
->v_type
!= V_FILE
)
6442 return error_value(E_FGETSTR1
);
6443 i
= readid(vp
->v_file
, 10, &str
);
6445 return error_value(E_FGETSTR2
);
6446 result
.v_type
= V_NULL
;
6448 result
.v_type
= V_STR
;
6456 f_fgetfield(VALUE
*vp
)
6462 /* initialize VALUE */
6463 result
.v_subtype
= V_NOSUBTYPE
;
6465 if (vp
->v_type
!= V_FILE
)
6466 return error_value(E_FGETFIELD1
);
6467 i
= readid(vp
->v_file
, 14, &str
);
6469 return error_value(E_FGETFIELD2
);
6470 result
.v_type
= V_NULL
;
6472 result
.v_type
= V_STR
;
6479 f_fgetfile(VALUE
*vp
)
6485 /* initialize VALUE */
6486 result
.v_subtype
= V_NOSUBTYPE
;
6488 if (vp
->v_type
!= V_FILE
)
6489 return error_value(E_FGETFILE1
);
6490 i
= readid(vp
->v_file
, 0, &str
);
6492 return error_value(E_FGETFILE2
);
6494 return error_value(E_FGETFILE3
);
6495 result
.v_type
= V_NULL
;
6497 result
.v_type
= V_STR
;
6505 f_files(int count
, VALUE
**vals
)
6509 /* initialize VALUE */
6510 result
.v_subtype
= V_NOSUBTYPE
;
6513 result
.v_type
= V_NUM
;
6514 result
.v_num
= itoq((long) MAXFILES
);
6517 if ((vals
[0]->v_type
!= V_NUM
) || qisfrac(vals
[0]->v_num
))
6518 return error_value(E_FILES
);
6519 result
.v_type
= V_NULL
;
6520 result
.v_file
= indexid(qtoi(vals
[0]->v_num
));
6521 if (result
.v_file
!= FILEID_NONE
)
6522 result
.v_type
= V_FILE
;
6528 f_reverse(VALUE
*val
)
6532 res
.v_type
= val
->v_type
;
6533 res
.v_subtype
= val
->v_subtype
;
6534 switch(val
->v_type
) {
6536 res
.v_mat
= matcopy(val
->v_mat
);
6537 matreverse(res
.v_mat
);
6540 res
.v_list
= listcopy(val
->v_list
);
6541 listreverse(res
.v_list
);
6544 res
.v_str
= stringneg(val
->v_str
);
6545 if (res
.v_str
== NULL
)
6546 return error_value(E_STRNEG
);
6549 math_error("Bad argument type for reverse");
6561 res
.v_type
= val
->v_type
;
6562 res
.v_subtype
= val
->v_subtype
;
6563 switch (val
->v_type
) {
6565 res
.v_mat
= matcopy(val
->v_mat
);
6569 res
.v_list
= listcopy(val
->v_list
);
6570 listsort(res
.v_list
);
6573 math_error("Bad argument type for sort");
6581 f_join(int count
, VALUE
**vals
)
6587 /* initialize VALUE */
6588 res
.v_subtype
= V_NOSUBTYPE
;
6591 while (count
-- > 0) {
6592 if (vals
[0]->v_type
!= V_LIST
) {
6594 printf("Non-list argument for join\n");
6595 res
.v_type
= V_NULL
;
6598 for (ep
= vals
[0]->v_list
->l_first
; ep
; ep
= ep
->e_next
)
6599 insertlistlast(lp
, &ep
->e_value
);
6602 res
.v_type
= V_LIST
;
6609 f_head(VALUE
*v1
, VALUE
*v2
)
6614 /* initialize VALUE */
6615 res
.v_subtype
= V_NOSUBTYPE
;
6617 if (v2
->v_type
!= V_NUM
|| qisfrac(v2
->v_num
) ||
6618 zge31b(v2
->v_num
->num
))
6619 return error_value(E_HEAD2
);
6620 n
= qtoi(v2
->v_num
);
6622 res
.v_type
= v1
->v_type
;
6623 switch (v1
->v_type
) {
6626 res
.v_list
= listalloc();
6628 res
.v_list
= listsegment(v1
->v_list
,0,n
-1);
6630 res
.v_list
= listsegment(v1
->v_list
,-n
-1,0);
6634 res
.v_str
= slink(&_nullstring_
);
6636 res
.v_str
= stringsegment(v1
->v_str
,0,n
-1);
6638 res
.v_str
= stringsegment(v1
->v_str
,-n
-1,0);
6639 if (res
.v_str
== NULL
)
6640 return error_value(E_STRHEAD
);
6643 return error_value(E_HEAD1
);
6649 f_tail(VALUE
*v1
, VALUE
*v2
)
6654 /* initialize VALUE */
6655 res
.v_subtype
= V_NOSUBTYPE
;
6657 if (v2
->v_type
!= V_NUM
|| qisfrac(v2
->v_num
) ||
6658 zge31b(v2
->v_num
->num
))
6659 return error_value(E_TAIL1
);
6660 n
= qtoi(v2
->v_num
);
6661 res
.v_type
= v1
->v_type
;
6662 switch (v1
->v_type
) {
6665 res
.v_list
= listalloc();
6667 res
.v_list
= listsegment(v1
->v_list
,
6668 v1
->v_list
->l_count
- n
,
6669 v1
->v_list
->l_count
- 1);
6671 res
.v_list
= listsegment(v1
->v_list
,
6672 v1
->v_list
->l_count
- 1,
6673 v1
->v_list
->l_count
+ n
);
6678 res
.v_str
= slink(&_nullstring_
);
6680 res
.v_str
= stringsegment(v1
->v_str
,
6681 v1
->v_str
->s_len
- n
,
6682 v1
->v_str
->s_len
- 1);
6684 res
.v_str
= stringsegment(v1
->v_str
,
6685 v1
->v_str
->s_len
- 1,
6686 v1
->v_str
->s_len
+ n
);
6688 if (res
.v_str
== V_NULL
)
6689 return error_value(E_STRTAIL
);
6692 return error_value(E_TAIL1
);
6698 f_segment(int count
, VALUE
**vals
)
6704 /* initialize VALUE */
6705 result
.v_subtype
= V_NOSUBTYPE
;
6709 if (vp
->v_type
!= V_NUM
|| qisfrac(vp
->v_num
) || zge31b(vp
->v_num
->num
))
6710 return error_value(E_SEG2
);
6711 n1
= qtoi(vp
->v_num
);
6715 if (vp
->v_type
!= V_NUM
|| qisfrac(vp
->v_num
) ||
6716 zge31b(vp
->v_num
->num
))
6717 return error_value(E_SEG3
);
6718 n2
= qtoi(vp
->v_num
);
6721 result
.v_type
= vp
->v_type
;
6722 switch (vp
->v_type
) {
6724 result
.v_list
= listsegment(vp
->v_list
, n1
, n2
);
6727 result
.v_str
= stringsegment(vp
->v_str
, n1
, n2
);
6728 if (result
.v_str
== NULL
)
6729 return error_value(E_STRSEG
);
6732 return error_value(E_SEG1
);
6738 f_modify(VALUE
*v1
, VALUE
*v2
)
6745 unsigned short subtype
;
6747 if (v1
->v_type
!= V_ADDR
)
6748 return error_value(E_MODIFY1
);
6750 if (v2
->v_type
== V_ADDR
)
6752 if (v2
->v_type
!= V_STR
)
6753 return error_value(E_MODIFY2
);
6754 if (v1
->v_subtype
& V_NONEWVALUE
)
6755 return error_value(E_MODIFY3
);
6756 fp
= findfunc(adduserfunc(v2
->v_str
->s_str
));
6758 return error_value(E_MODIFY4
);
6759 switch (v1
->v_type
) {
6761 for (ep
= v1
->v_list
->l_first
; ep
; ep
= ep
->e_next
) {
6762 subtype
= ep
->e_value
.v_subtype
;
6763 *++stack
= ep
->e_value
;
6765 stack
->v_subtype
|= subtype
;
6766 ep
->e_value
= *stack
--;
6770 vp
= v1
->v_mat
->m_table
;
6771 s
= v1
->v_mat
->m_size
;
6773 subtype
= vp
->v_subtype
;
6776 stack
->v_subtype
|= subtype
;
6781 vp
= v1
->v_obj
->o_table
;
6782 s
= v1
->v_obj
->o_actions
->oa_count
;
6784 subtype
= vp
->v_subtype
;
6787 stack
->v_subtype
|= subtype
;
6792 return error_value(E_MODIFY5
);
6794 res
.v_type
= V_NULL
;
6795 res
.v_subtype
= V_NOSUBTYPE
;
6801 f_forall(VALUE
*v1
, VALUE
*v2
)
6809 /* initialize VALUE */
6810 res
.v_type
= V_NULL
;
6811 res
.v_subtype
= V_NOSUBTYPE
;
6813 if (v2
->v_type
!= V_STR
) {
6814 math_error("Non-string second argument for forall");
6817 fp
= findfunc(adduserfunc(v2
->v_str
->s_str
));
6819 math_error("Undefined function for forall");
6822 switch (v1
->v_type
) {
6824 for (ep
= v1
->v_list
->l_first
; ep
; ep
= ep
->e_next
) {
6825 copyvalue(&ep
->e_value
, ++stack
);
6831 vp
= v1
->v_mat
->m_table
;
6832 s
= v1
->v_mat
->m_size
;
6834 copyvalue(vp
++, ++stack
);
6840 math_error("Non list or matrix first argument for forall");
6848 f_select(VALUE
*v1
, VALUE
*v2
)
6855 /* initialize VALUE */
6856 res
.v_type
= V_LIST
;
6857 res
.v_subtype
= V_NOSUBTYPE
;
6859 if (v1
->v_type
!= V_LIST
) {
6860 math_error("Non-list first argument for select");
6863 if (v2
->v_type
!= V_STR
) {
6864 math_error("Non-string second argument for select");
6867 fp
= findfunc(adduserfunc(v2
->v_str
->s_str
));
6869 math_error("Undefined function for select");
6873 for (ep
= v1
->v_list
->l_first
; ep
; ep
= ep
->e_next
) {
6874 copyvalue(&ep
->e_value
, ++stack
);
6876 if (testvalue(stack
))
6877 insertlistlast(lp
, &ep
->e_value
);
6886 f_count(VALUE
*v1
, VALUE
*v2
)
6895 /* initialize VALUE */
6897 res
.v_subtype
= V_NOSUBTYPE
;
6899 if (v2
->v_type
!= V_STR
) {
6900 math_error("Non-string second argument for select");
6903 fp
= findfunc(adduserfunc(v2
->v_str
->s_str
));
6905 math_error("Undefined function for select");
6908 switch (v1
->v_type
) {
6910 for (ep
= v1
->v_list
->l_first
; ep
; ep
= ep
->e_next
) {
6911 copyvalue(&ep
->e_value
, ++stack
);
6913 if (testvalue(stack
))
6919 s
= v1
->v_mat
->m_size
;
6920 vp
= v1
->v_mat
->m_table
;
6922 copyvalue(vp
++, ++stack
);
6924 if (testvalue(stack
))
6930 math_error("Bad argument type for count");
6933 res
.v_num
= itoq(n
);
6939 f_makelist(VALUE
*v1
)
6945 /* initialize VALUE */
6946 res
.v_type
= V_NULL
;
6947 res
.v_subtype
= V_NOSUBTYPE
;
6949 if (v1
->v_type
!= V_NUM
|| qisfrac(v1
->v_num
) || qisneg(v1
->v_num
)) {
6950 math_error("Bad argument for makelist");
6953 if (zge31b(v1
->v_num
->num
)) {
6954 math_error("makelist count >= 2^31");
6957 n
= qtoi(v1
->v_num
);
6960 insertlistlast(lp
, &res
);
6961 res
.v_type
= V_LIST
;
6968 f_randperm(VALUE
*val
)
6972 /* initialize VALUE */
6973 res
.v_subtype
= V_NOSUBTYPE
;
6975 res
.v_type
= val
->v_type
;
6976 switch (val
->v_type
) {
6978 res
.v_mat
= matcopy(val
->v_mat
);
6979 matrandperm(res
.v_mat
);
6982 res
.v_list
= listcopy(val
->v_list
);
6983 listrandperm(res
.v_list
);
6986 math_error("Bad argument type for randperm");
6998 size_t cmdbuf_len
; /* length of cmdbuf string */
7000 /* initialize VALUE */
7001 result
.v_type
= V_STR
;
7002 result
.v_subtype
= V_NOSUBTYPE
;
7004 cmdbuf_len
= strlen(cmdbuf
);
7005 newcp
= (char *)malloc(cmdbuf_len
+1);
7006 strncpy(newcp
, cmdbuf
, cmdbuf_len
+1);
7007 result
.v_str
= makestring(newcp
);
7018 /* initialize VALUE */
7019 result
.v_subtype
= V_NOSUBTYPE
;
7021 if (v1
->v_type
!= V_STR
) {
7022 math_error("Non-string argument for getenv");
7025 result
.v_type
= V_STR
;
7026 str
= getenv(v1
->v_str
->s_str
);
7028 result
.v_type
= V_NULL
;
7030 result
.v_str
= makenewstring(str
);
7040 /* initialize VALUE */
7041 result
.v_subtype
= V_NOSUBTYPE
;
7043 result
.v_type
= V_NUM
;
7044 if (vp
->v_type
== V_FILE
&& isattyid(vp
->v_file
) == 1) {
7045 result
.v_num
= itoq(1);
7047 result
.v_num
= itoq(0);
7058 if (!calc_tty(FILEID_STDIN
))
7059 return error_value(E_TTY
);
7060 res
.v_type
= V_NULL
;
7061 res
.v_subtype
= V_NOSUBTYPE
;
7071 /* initialize VALUE */
7072 result
.v_type
= V_NUM
;
7073 result
.v_subtype
= V_NOSUBTYPE
;
7075 result
.v_num
= itoq((long) inputlevel());
7085 /* initialize VALUE */
7086 result
.v_type
= V_NUM
;
7087 result
.v_subtype
= V_NOSUBTYPE
;
7089 result
.v_num
= itoq(calclevel());
7099 /* initialize VALUE */
7100 result
.v_type
= V_STR
;
7101 result
.v_subtype
= V_NOSUBTYPE
;
7103 result
.v_str
= makenewstring(calcpath
);
7109 f_access(int count
, VALUE
**vals
)
7118 /* initialize VALUE */
7119 result
.v_type
= V_NULL
;
7120 result
.v_subtype
= V_NOSUBTYPE
;
7123 if (vals
[0]->v_type
!= V_STR
)
7124 return error_value(E_ACCESS1
);
7125 fname
= vals
[0]->v_str
->s_str
;
7128 switch (vals
[1]->v_type
) {
7131 if (qisfrac(q
) || qisneg(q
))
7132 return error_value(E_ACCESS2
);
7133 m
= (int)(q
->num
.v
[0] & 7);
7136 s
= vals
[1]->v_str
->s_str
;
7137 len
= (long)strlen(s
);
7140 case 'r': m
|= 4; break;
7141 case 'w': m
|= 2; break;
7142 case 'x': m
|= 1; break;
7143 default: return error_value(E_ACCESS2
);
7150 return error_value(E_ACCESS2
);
7153 i
= access(fname
, m
);
7155 return error_value(errno
);
7161 f_putenv(int count
, VALUE
**vals
)
7166 /* initialize VALUE */
7167 result
.v_type
= V_NUM
;
7168 result
.v_subtype
= V_NOSUBTYPE
;
7175 if (vals
[0]->v_type
!= V_STR
|| vals
[1]->v_type
!= V_STR
) {
7176 math_error("Non-string argument for putenv");
7180 /* convert putenv("foo","bar") into putenv("foo=bar") */
7181 putenv_str
= (char *)malloc(vals
[0]->v_str
->s_len
+ 1 +
7182 vals
[1]->v_str
->s_len
+ 1);
7183 if (putenv_str
== NULL
) {
7184 math_error("Cannot allocate string in putenv");
7187 sprintf(putenv_str
, "%s=%s", vals
[0]->v_str
->s_str
,
7188 vals
[1]->v_str
->s_str
);
7193 if (vals
[0]->v_type
!= V_STR
) {
7194 math_error("Non-string argument for putenv");
7198 /* putenv(arg) must be of the form "foo=bar" */
7199 if ((char *)strchr(vals
[0]->v_str
->s_str
, '=') == NULL
) {
7200 math_error("putenv single arg string missing =");
7205 * make a copy of the arg because subsequent changes
7206 * would change the environment.
7208 putenv_str
= (char *)malloc(vals
[0]->v_str
->s_len
+ 1);
7209 if (putenv_str
== NULL
) {
7210 math_error("Cannot allocate string in putenv");
7213 strncpy(putenv_str
, vals
[0]->v_str
->s_str
,
7214 vals
[0]->v_str
->s_len
+ 1);
7217 /* return putenv result */
7218 result
.v_num
= itoq((long) malloced_putenv(putenv_str
));
7224 f_strpos(VALUE
*haystack
, VALUE
*needle
)
7230 /* initialize VALUE */
7231 result
.v_type
= V_NUM
;
7232 result
.v_subtype
= V_NOSUBTYPE
;
7234 if (haystack
->v_type
!= V_STR
|| needle
->v_type
!= V_STR
) {
7235 math_error("Non-string argument for index");
7238 cpointer
= strstr(haystack
->v_str
->s_str
,
7239 needle
->v_str
->s_str
);
7240 if (cpointer
== NULL
)
7243 cindex
= cpointer
- haystack
->v_str
->s_str
+ 1;
7244 result
.v_num
= itoq((long) cindex
);
7254 /* initialize VALUE */
7255 result
.v_type
= V_NUM
;
7256 result
.v_subtype
= V_NOSUBTYPE
;
7258 if (vp
->v_type
!= V_STR
) {
7259 math_error("Non-string argument for system");
7263 math_error("execution disallowed by -m");
7266 if (conf
->calc_debug
& CALCDBG_SYSTEM
) {
7267 printf("%s\n", vp
->v_str
->s_str
);
7270 /* if the execute length is 0 then just return 0 */
7271 if (vp
->v_str
->s_len
== 0) {
7272 result
.v_num
= itoq((long)0);
7274 result
.v_num
= itoq((long)system(vp
->v_str
->s_str
));
7276 #else /* Windoz free systems */
7277 result
.v_num
= itoq((long)system(vp
->v_str
->s_str
));
7278 #endif /* Windoz free systems */
7284 f_sleep(int count
, VALUE
**vals
)
7290 res
.v_type
= V_NULL
;
7291 #if !defined(_WIN32)
7293 if (vals
[0]->v_type
!= V_NUM
|| qisneg(vals
[0]->v_num
))
7294 return error_value(E_SLEEP
);
7295 if (qisint(vals
[0]->v_num
)) {
7296 if (zge31b(vals
[0]->v_num
->num
))
7297 return error_value(E_SLEEP
);
7298 time
= ztoi(vals
[0]->v_num
->num
);
7302 q1
= qscale(vals
[0]->v_num
, 20);
7305 if (zge31b(q2
->num
)) {
7307 return error_value(E_SLEEP
);
7309 time
= ztoi(q2
->num
);
7311 /* BSD 4.3 usleep has void return */
7320 res
.v_num
= itoq(time
);
7322 #endif /* Windoz free systems */
7328 * set the default output base/mode
7331 f_base(int count
, NUMBER
**vals
)
7333 long base
; /* output base/mode */
7334 long oldbase
=0; /* output base/mode */
7336 /* deal with just a query */
7338 return base_value(conf
->outmode
, conf
->outmode
);
7341 /* deal with the specal modes first */
7342 if (qisfrac(vals
[0])) {
7343 return base_value(math_setmode(MODE_FRAC
), conf
->outmode
);
7345 if (vals
[0]->num
.len
> 64/BASEB
) {
7346 return base_value(math_setmode(MODE_EXP
), conf
->outmode
);
7349 /* set the base, if possible */
7350 base
= qtoi(vals
[0]);
7353 oldbase
= math_setmode(MODE_INT
);
7356 oldbase
= math_setmode(MODE_BINARY
);
7359 oldbase
= math_setmode(MODE_OCTAL
);
7362 oldbase
= math_setmode(MODE_REAL
);
7365 oldbase
= math_setmode(MODE_HEX
);
7368 math_error("Unsupported base");
7373 /* return the old base */
7374 return base_value(oldbase
, conf
->outmode
);
7379 * set the default secondary output base/mode
7382 f_base2(int count
, NUMBER
**vals
)
7384 long base
; /* output base/mode */
7385 long oldbase
=0; /* output base/mode */
7387 /* deal with just a query */
7389 return base_value(conf
->outmode2
, conf
->outmode2
);
7392 /* deal with the specal modes first */
7393 if (qisfrac(vals
[0])) {
7394 return base_value(math_setmode2(MODE_FRAC
), conf
->outmode2
);
7396 if (vals
[0]->num
.len
> 64/BASEB
) {
7397 return base_value(math_setmode2(MODE_EXP
), conf
->outmode2
);
7400 /* set the base, if possible */
7401 base
= qtoi(vals
[0]);
7404 oldbase
= math_setmode2(MODE2_OFF
);
7407 oldbase
= math_setmode2(MODE_INT
);
7410 oldbase
= math_setmode2(MODE_BINARY
);
7413 oldbase
= math_setmode2(MODE_OCTAL
);
7416 oldbase
= math_setmode2(MODE_REAL
);
7419 oldbase
= math_setmode2(MODE_HEX
);
7422 math_error("Unsupported base");
7427 /* return the old base */
7428 return base_value(oldbase
, conf
->outmode2
);
7433 * return a numerical 'value' of the mode/base
7436 base_value(long mode
, int defval
)
7440 /* return the old base */
7449 itoz(3, &result
->den
);
7459 ztenpow(20, &result
->num
);
7480 itoz(3, &result
->den
);
7490 ztenpow(20, &result
->num
);
7513 f_custom(int count
, VALUE
**vals
)
7517 /* initialize VALUE */
7518 result
.v_type
= V_NULL
;
7519 result
.v_subtype
= V_NOSUBTYPE
;
7522 * disable custom functions unless -C was given
7524 if (!allow_custom
) {
7527 "%sCalc must be run with a -C argument to "
7528 "use custom function\n",
7530 "%sCalc was built with custom functions disabled\n",
7532 (conf
->tab_ok
? "\t" : ""));
7533 return error_value(E_CUSTOM_ERROR
);
7537 * perform the custom operation
7540 /* perform the usage function function */
7544 if (vals
[0]->v_type
!= V_STR
) {
7545 math_error("custom: 1st arg not a string name");
7549 /* perform the custom function */
7550 result
= custom(vals
[0]->v_str
->s_str
, count
-1, vals
+1);
7554 * return the custom result
7561 f_blk(int count
, VALUE
**vals
)
7563 int len
; /* number of octets to malloc */
7564 int chunk
; /* block chunk size */
7570 /* initialize VALUE */
7571 result
.v_type
= V_BLOCK
;
7572 result
.v_subtype
= V_NOSUBTYPE
;
7578 if (type
== V_STR
|| type
== V_NBLOCK
|| type
== V_BLOCK
) {
7584 len
= -1; /* signal to use old or zero len */
7585 chunk
= -1; /* signal to use old or default chunksize */
7586 if (count
> 0 && vals
[0]->v_type
!= V_NULL
) {
7588 if (vals
[0]->v_type
!= V_NUM
|| qisfrac(vals
[0]->v_num
))
7589 return error_value(E_BLK1
);
7590 if (qisneg(vals
[0]->v_num
) || zge31b(vals
[0]->v_num
->num
))
7591 return error_value(E_BLK2
);
7592 len
= qtoi(vals
[0]->v_num
);
7594 if (count
> 1 && vals
[1]->v_type
!= V_NULL
) {
7596 if (vals
[1]->v_type
!= V_NUM
|| qisfrac(vals
[1]->v_num
))
7597 return error_value(E_BLK3
);
7598 if (qisneg(vals
[1]->v_num
) || zge31b(vals
[1]->v_num
->num
))
7599 return error_value(E_BLK4
);
7600 chunk
= qtoi(vals
[1]->v_num
);
7603 if (type
== V_STR
) {
7604 result
.v_type
= V_NBLOCK
;
7605 id
= findnblockid(vp
->v_str
->s_str
);
7607 /* create new named block */
7608 result
.v_nblock
= createnblock(vp
->v_str
->s_str
,
7612 /* reallocate nblock */
7613 result
.v_nblock
= reallocnblock(id
, len
, chunk
);
7617 if (type
== V_NBLOCK
) {
7618 /* reallocate nblock */
7619 result
.v_type
= V_NBLOCK
;
7620 id
= vp
->v_nblock
->id
;
7621 result
.v_nblock
= reallocnblock(id
, len
, chunk
);
7624 if (type
== V_BLOCK
) {
7625 /* reallocate block */
7626 result
.v_type
= V_BLOCK
;
7627 result
.v_block
= copyrealloc(vp
->v_block
, len
, chunk
);
7631 /* allocate block */
7632 result
.v_block
= blkalloc(len
, chunk
);
7638 f_blkfree(VALUE
*vp
)
7643 /* initialize VALUE */
7644 result
.v_type
= V_NULL
;
7645 result
.v_subtype
= V_NOSUBTYPE
;
7648 switch (vp
->v_type
) {
7650 id
= vp
->v_nblock
->id
;
7653 id
= findnblockid(vp
->v_str
->s_str
);
7655 return error_value(E_BLKFREE1
);
7658 if (qisfrac(vp
->v_num
) || qisneg(vp
->v_num
))
7659 return error_value(E_BLKFREE2
);
7660 if (zge31b(vp
->v_num
->num
))
7661 return error_value(E_BLKFREE3
);
7662 id
= qtoi(vp
->v_num
);
7665 return error_value(E_BLKFREE4
);
7667 id
= removenblock(id
);
7669 return error_value(id
);
7675 f_blocks(int count
, VALUE
**vals
)
7681 /* initialize VALUE */
7682 result
.v_subtype
= V_NOSUBTYPE
;
7685 result
.v_type
= V_NUM
;
7686 result
.v_num
= itoq((long) countnblocks());
7689 if (vals
[0]->v_type
!= V_NUM
|| qisfrac(vals
[0]->v_num
))
7690 return error_value(E_BLOCKS1
);
7691 id
= (int) qtoi(vals
[0]->v_num
);
7693 nblk
= findnblock(id
);
7696 return error_value(E_BLOCKS2
);
7698 result
.v_type
= V_NBLOCK
;
7699 result
.v_nblock
= nblk
;
7706 f_free(int count
, VALUE
**vals
)
7711 /* initialize VALUE */
7712 result
.v_subtype
= V_NOSUBTYPE
;
7714 result
.v_type
= V_NULL
;
7715 while (count
-- > 0) {
7717 if (val
->v_type
== V_ADDR
)
7718 freevalue(val
->v_addr
);
7729 /* initialize VALUE */
7730 result
.v_type
= V_NULL
;
7731 result
.v_subtype
= V_NOSUBTYPE
;
7743 /* initialize VALUE */
7744 result
.v_type
= V_NULL
;
7745 result
.v_subtype
= V_NOSUBTYPE
;
7757 /* initialize VALUE */
7758 result
.v_type
= V_NULL
;
7759 result
.v_subtype
= V_NOSUBTYPE
;
7767 * f_copy - copy consecutive items between values
7769 * copy(src, dst [, ssi [, num [, dsi]]])
7771 * Copy 'num' consecutive items from 'src' with index 'ssi' to
7772 * 'dest', starting at position with index 'dsi'.
7775 f_copy(int count
, VALUE
**vals
)
7777 long ssi
= 0; /* source start index */
7778 long num
= -1; /* number of items to copy (-1 ==> all) */
7779 long dsi
= -1; /* destination start index, -1 ==> default */
7780 int errtype
; /* error type if unable to perform copy */
7781 VALUE result
; /* null if successful */
7783 /* initialize VALUE */
7784 result
.v_type
= V_NULL
;
7785 result
.v_subtype
= V_NOSUBTYPE
;
7793 if (vals
[4]->v_type
!= V_NULL
) {
7794 if (vals
[4]->v_type
!= V_NUM
||
7795 qisfrac(vals
[4]->v_num
) ||
7796 qisneg(vals
[4]->v_num
)) {
7797 return error_value(E_COPY6
);
7799 if (zge31b(vals
[4]->v_num
->num
)) {
7800 return error_value(E_COPY7
);
7802 dsi
= qtoi(vals
[4]->v_num
);
7808 if (vals
[3]->v_type
!= V_NULL
) {
7809 if (vals
[3]->v_type
!= V_NUM
||
7810 qisfrac(vals
[3]->v_num
) ||
7811 qisneg(vals
[3]->v_num
)) {
7812 return error_value(E_COPY1
);
7814 if (zge31b(vals
[3]->v_num
->num
)) {
7815 return error_value(E_COPY2
);
7817 num
= qtoi(vals
[3]->v_num
);
7823 if (vals
[2]->v_type
!= V_NULL
) {
7824 if (vals
[2]->v_type
!= V_NUM
||
7825 qisfrac(vals
[2]->v_num
) ||
7826 qisneg(vals
[2]->v_num
)) {
7827 return error_value(E_COPY4
);
7829 if (zge31b(vals
[2]->v_num
->num
)) {
7830 return error_value(E_COPY5
);
7832 ssi
= qtoi(vals
[2]->v_num
);
7840 errtype
= copystod(vals
[0], ssi
, num
, vals
[1], dsi
);
7842 return error_value(errtype
);
7848 * f_blkcpy - copy consecutive items between values
7850 * copy(dst, src [, num [, dsi [, ssi]]])
7852 * Copy 'num' consecutive items from 'src' with index 'ssi' to
7853 * 'dest', starting at position with index 'dsi'.
7856 f_blkcpy(int count
, VALUE
**vals
)
7858 VALUE
*args
[5]; /* args to re-order */
7859 VALUE null_value
; /* dummy argument */
7861 /* initialize VALUE */
7862 null_value
.v_subtype
= V_NOSUBTYPE
;
7865 * parse args into f_copy order
7879 null_value
.v_type
= V_NULL
;
7880 args
[2] = &null_value
;
7885 null_value
.v_type
= V_NULL
;
7886 args
[2] = &null_value
;
7893 return f_copy(count
, args
);
7898 f_sha1(int count
, VALUE
**vals
)
7901 HASH
*state
; /* pointer to hash state to use */
7902 int i
; /* vals[i] to hash */
7904 /* initialize VALUE */
7905 result
.v_subtype
= V_NOSUBTYPE
;
7912 /* return an initial hash state */
7913 result
.v_type
= V_HASH
;
7914 result
.v_hash
= hash_init(SHA1_HASH_TYPE
, NULL
);
7916 } else if (count
== 1 && vals
[0]->v_type
== V_HASH
&&
7917 vals
[0]->v_hash
->hashtype
== SHA1_HASH_TYPE
) {
7919 /* if just a hash value, finalize it */
7920 state
= hash_copy(vals
[0]->v_hash
);
7921 result
.v_type
= V_NUM
;
7922 result
.v_num
= qalloc();
7923 result
.v_num
->num
= hash_final(state
);
7929 * If the first value is a hash, use that as
7930 * the initial hash state
7932 if (vals
[0]->v_type
== V_HASH
&&
7933 vals
[0]->v_hash
->hashtype
== SHA1_HASH_TYPE
) {
7934 state
= hash_copy(vals
[0]->v_hash
);
7938 * otherwise use the default initial state
7941 state
= hash_init(SHA1_HASH_TYPE
, NULL
);
7946 * hash the remaining values
7949 state
= hash_value(SHA1_HASH_TYPE
, vals
[i
], state
);
7950 } while (++i
< count
);
7953 * return the current hash state
7955 result
.v_type
= V_HASH
;
7956 result
.v_hash
= state
;
7959 /* return the result */
7965 f_argv(int count
, VALUE
**vals
)
7967 int arg
; /* the argv_value string index */
7970 /* initialize VALUE */
7971 result
.v_subtype
= V_NOSUBTYPE
;
7978 /* return the argc count */
7979 result
.v_type
= V_NUM
;
7980 result
.v_num
= itoq((long) argc_value
);
7985 if (vals
[0]->v_type
!= V_NUM
|| qisfrac(vals
[0]->v_num
) ||
7986 qisneg(vals
[0]->v_num
) || zge31b(vals
[0]->v_num
->num
)) {
7988 math_error("argv argument must be a integer [0,2^31)");
7992 /* return the n-th argv string */
7993 arg
= qtoi(vals
[0]->v_num
);
7994 if (arg
< argc_value
&& argv_value
[arg
] != NULL
) {
7995 result
.v_type
= V_STR
;
7996 result
.v_str
= makestring(strdup(argv_value
[arg
]));
7998 result
.v_type
= V_NULL
;
8002 /* return the result */
8012 /* return the calc verstion string */
8013 result
.v_type
= V_STR
;
8014 result
.v_subtype
= V_NOSUBTYPE
;
8015 result
.v_str
= makestring(strdup(version()));
8021 #endif /* !FUNCLIST */
8025 * builtins - List of primitive built-in functions
8027 * NOTE: This table is also used by the help/Makefile builtin rule to
8028 * form the builtin help file. This rule will cause a sed script
8029 * to strip this table down into a just the information needed
8030 * to print builtin function list: b_name, b_minargs, b_maxargs
8031 * and b_desc. All other struct elements will be converted to 0.
8032 * The sed script expects to find entries of the form:
8034 * {"...", number, number, stuff, stuff, stuff, stuff,
8037 * please keep this table in that form.
8039 * For nice output, when the description of function (b_desc)
8040 * gets too long (extends into col 79) you should chop the
8041 * line and add "\n\t\t\t", that's newline and 3 tabs.
8042 * For example the description:
8044 * ... very long description that goes beyond col 79
8046 * should be written as:
8048 * "... very long description that\n\t\t\tgoes beyond col 79"},
8051 * b_name name of built-in function
8052 * b_minargs minimum number of arguments
8053 * b_maxargs maximum number of arguments
8054 * b_flags special handling flags
8055 * b_opcode opcode which makes the call quick
8056 * b_numfunc routine to calculate numeric function
8057 * b_valfunc routine to calculate general values
8058 * b_desc description of function
8060 STATIC CONST
struct builtin builtins
[] = {
8061 {"abs", 1, 2, 0, OP_ABS
, 0, 0,
8062 "absolute value within accuracy b"},
8063 {"access", 1, 2, 0, OP_NOP
, 0, f_access
,
8064 "determine accessibility of file a for mode b"},
8065 {"acos", 1, 2, 0, OP_NOP
, 0, f_acos
,
8066 "arccosine of a within accuracy b"},
8067 {"acosh", 1, 2, 0, OP_NOP
, 0, f_acosh
,
8068 "inverse hyperbolic cosine of a within accuracy b"},
8069 {"acot", 1, 2, 0, OP_NOP
, 0, f_acot
,
8070 "arccotangent of a within accuracy b"},
8071 {"acoth", 1, 2, 0, OP_NOP
, 0, f_acoth
,
8072 "inverse hyperbolic cotangent of a within accuracy b"},
8073 {"acsc", 1, 2, 0, OP_NOP
, 0, f_acsc
,
8074 "arccosecant of a within accuracy b"},
8075 {"acsch", 1, 2, 0, OP_NOP
, 0, f_acsch
,
8076 "inverse csch of a within accuracy b"},
8077 {"agd", 1, 2, 0, OP_NOP
, 0, f_agd
,
8078 "inverse gudermannian function"},
8079 {"append", 1, IN
, FA
, OP_NOP
, 0, f_listappend
,
8080 "append values to end of list"},
8081 {"appr", 1, 3, 0, OP_NOP
, 0, f_appr
,
8082 "approximate a by multiple of b using rounding c"},
8083 {"arg", 1, 2, 0, OP_NOP
, 0, f_arg
,
8084 "argument (the angle) of complex number"},
8085 {"argv", 0, 1, 0, OP_NOP
, 0, f_argv
,
8086 "calc argc or argv string"},
8087 {"asec", 1, 2, 0, OP_NOP
, 0, f_asec
,
8088 "arcsecant of a within accuracy b"},
8089 {"asech", 1, 2, 0, OP_NOP
, 0, f_asech
,
8090 "inverse hyperbolic secant of a within accuracy b"},
8091 {"asin", 1, 2, 0, OP_NOP
, 0, f_asin
,
8092 "arcsine of a within accuracy b"},
8093 {"asinh", 1, 2, 0, OP_NOP
, 0, f_asinh
,
8094 "inverse hyperbolic sine of a within accuracy b"},
8095 {"assoc", 0, 0, 0, OP_NOP
, 0, f_assoc
,
8096 "create new association array"},
8097 {"atan", 1, 2, 0, OP_NOP
, 0, f_atan
,
8098 "arctangent of a within accuracy b"},
8099 {"atan2", 2, 3, FE
, OP_NOP
, qatan2
, 0,
8100 "angle to point (b,a) within accuracy c"},
8101 {"atanh", 1, 2, 0, OP_NOP
, 0, f_atanh
,
8102 "inverse hyperbolic tangent of a within accuracy b"},
8103 {"avg", 0, IN
, 0, OP_NOP
, 0, f_avg
,
8104 "arithmetic mean of values"},
8105 {"base", 0, 1, 0, OP_NOP
, f_base
, 0,
8106 "set default output base"},
8107 {"base2", 0, 1, 0, OP_NOP
, f_base2
, 0,
8108 "set default secondary output base"},
8109 {"bernoulli", 1, 1, 0, OP_NOP
, 0, f_bern
,
8110 "Bernoulli number for index a"},
8111 {"bit", 2, 2, 0, OP_BIT
, 0, 0,
8112 "whether bit b in value a is set"},
8113 {"blk", 0, 3, 0, OP_NOP
, 0, f_blk
,
8114 "block with or without name, octet number, chunksize"},
8115 {"blkcpy", 2, 5, 0, OP_NOP
, 0, f_blkcpy
,
8116 "copy value to/from a block: blkcpy(d,s,len,di,si)"},
8117 {"blkfree", 1, 1, 0, OP_NOP
, 0, f_blkfree
,
8118 "free all storage from a named block"},
8119 {"blocks", 0, 1, 0, OP_NOP
, 0, f_blocks
,
8120 "named block with specified index, or null value"},
8121 {"bround", 1, 3, 0, OP_NOP
, 0, f_bround
,
8122 "round value a to b number of binary places"},
8123 {"btrunc", 1, 2, 0, OP_NOP
, f_btrunc
, 0,
8124 "truncate a to b number of binary places"},
8125 {"calc_tty", 0, 0, 0, OP_NOP
, 0, f_calc_tty
,
8126 "set tty for interactivity"},
8127 {"calclevel", 0, 0, 0, OP_NOP
, 0, f_calclevel
,
8128 "current calculation level"},
8129 {"calcpath", 0, 0, 0, OP_NOP
, 0, f_calcpath
,
8130 "current CALCPATH search path value"},
8131 {"catalan", 1, 1, 0, OP_NOP
, 0, f_catalan
,
8132 "catalan number for index a"},
8133 {"ceil", 1, 1, 0, OP_NOP
, 0, f_ceil
,
8134 "smallest integer greater than or equal to number"},
8135 {"cfappr", 1, 3, 0, OP_NOP
, f_cfappr
, 0,
8136 "approximate a within accuracy b using\n"
8137 "\t\t\tcontinued fractions"},
8138 {"cfsim", 1, 2, 0, OP_NOP
, f_cfsim
, 0,
8139 "simplify number using continued fractions"},
8140 {"char", 1, 1, 0, OP_NOP
, 0, f_char
,
8141 "character corresponding to integer value"},
8142 {"cmdbuf", 0, 0, 0, OP_NOP
, 0, f_cmdbuf
,
8144 {"cmp", 2, 2, 0, OP_CMP
, 0, 0,
8145 "compare values returning -1, 0, or 1"},
8146 {"comb", 2, 2, 0, OP_NOP
, 0, f_comb
,
8147 "combinatorial number a!/b!(a-b)!"},
8148 {"config", 1, 2, 0, OP_SETCONFIG
, 0, 0,
8149 "set or read configuration value"},
8150 {"conj", 1, 1, 0, OP_CONJUGATE
, 0, 0,
8151 "complex conjugate of value"},
8152 {"copy", 2, 5, 0, OP_NOP
, 0, f_copy
,
8153 "copy value to/from a block: copy(s,d,len,si,di)"},
8154 {"cos", 1, 2, 0, OP_NOP
, 0, f_cos
,
8155 "cosine of value a within accuracy b"},
8156 {"cosh", 1, 2, 0, OP_NOP
, 0, f_cosh
,
8157 "hyperbolic cosine of a within accuracy b"},
8158 {"cot", 1, 2, 0, OP_NOP
, 0, f_cot
,
8159 "cotangent of a within accuracy b"},
8160 {"coth", 1, 2, 0, OP_NOP
, 0, f_coth
,
8161 "hyperbolic cotangent of a within accuracy b"},
8162 {"count", 2, 2, 0, OP_NOP
, 0, f_count
,
8163 "count listr/matrix elements satisfying some condition"},
8164 {"cp", 2, 2, 0, OP_NOP
, 0, f_cp
,
8165 "cross product of two vectors"},
8166 {"csc", 1, 2, 0, OP_NOP
, 0, f_csc
,
8167 "cosecant of a within accuracy b"},
8168 {"csch", 1, 2, 0, OP_NOP
, 0, f_csch
,
8169 "hyperbolic cosecant of a within accuracy b"},
8170 {"ctime", 0, 0, 0, OP_NOP
, 0, f_ctime
,
8171 "date and time as string"},
8172 {"custom", 0, IN
, 0, OP_NOP
, 0, f_custom
,
8173 "custom builtin function interface"},
8174 {"delete", 2, 2, FA
, OP_NOP
, 0, f_listdelete
,
8175 "delete element from list a at position b"},
8176 {"den", 1, 1, 0, OP_DENOMINATOR
, qden
, 0,
8177 "denominator of fraction"},
8178 {"det", 1, 1, 0, OP_NOP
, 0, f_det
,
8179 "determinant of matrix"},
8180 {"digit", 2, 3, 0, OP_NOP
, 0, f_digit
,
8181 "digit at specified decimal place of number"},
8182 {"digits", 1, 2, 0, OP_NOP
, 0, f_digits
,
8183 "number of digits in base b representation of a"},
8184 {"display", 0, 1, 0, OP_NOP
, 0, f_display
,
8185 "number of decimal digits for displaying numbers"},
8186 {"dp", 2, 2, 0, OP_NOP
, 0, f_dp
,
8187 "dot product of two vectors"},
8188 {"epsilon", 0, 1, 0, OP_SETEPSILON
, 0, 0,
8189 "set or read allowed error for real calculations"},
8190 {"errcount", 0, 1, 0, OP_NOP
, 0, f_errcount
,
8191 "set or read error count"},
8192 {"errmax", 0, 1, 0, OP_NOP
, 0, f_errmax
,
8193 "set or read maximum for error count"},
8194 {"errno", 0, 1, 0, OP_NOP
, 0, f_errno
,
8195 "set or read calc_errno"},
8196 {"error", 0, 1, 0, OP_NOP
, 0, f_error
,
8197 "generate error value"},
8198 {"estr", 1, 1, 0, OP_NOP
, 0, f_estr
,
8199 "exact text string representation of value"},
8200 {"euler", 1, 1, 0, OP_NOP
, 0, f_euler
,
8202 {"eval", 1, 1, 0, OP_NOP
, 0, f_eval
,
8203 "evaluate expression from string to value"},
8204 {"exp", 1, 2, 0, OP_NOP
, 0, f_exp
,
8205 "exponential of value a within accuracy b"},
8206 {"factor", 1, 3, 0, OP_NOP
, f_factor
, 0,
8207 "lowest prime factor < b of a, return c if error"},
8208 {"fcnt", 2, 2, 0, OP_NOP
, f_faccnt
, 0,
8209 "count of times one number divides another"},
8210 {"fib", 1, 1, 0, OP_NOP
, qfib
, 0,
8211 "Fibonacci number F(n)"},
8212 {"forall", 2, 2, 0, OP_NOP
, 0, f_forall
,
8213 "do function for all elements of list or matrix"},
8214 {"frem", 2, 2, 0, OP_NOP
, qfacrem
, 0,
8215 "number with all occurrences of factor removed"},
8216 {"fact", 1, 1, 0, OP_NOP
, 0, f_fact
,
8218 {"fclose", 0, IN
, 0, OP_NOP
, 0, f_fclose
,
8220 {"feof", 1, 1, 0, OP_NOP
, 0, f_feof
,
8221 "whether EOF reached for file"},
8222 {"ferror", 1, 1, 0, OP_NOP
, 0, f_ferror
,
8223 "whether error occurred for file"},
8224 {"fflush", 0, IN
, 0, OP_NOP
, 0, f_fflush
,
8225 "flush output to file(s)"},
8226 {"fgetc", 1, 1, 0, OP_NOP
, 0, f_fgetc
,
8227 "read next char from file"},
8228 {"fgetfield", 1, 1, 0, OP_NOP
, 0, f_fgetfield
,
8229 "read next white-space delimited field from file"},
8230 {"fgetfile", 1, 1, 0, OP_NOP
, 0, f_fgetfile
,
8231 "read to end of file"},
8232 {"fgetline", 1, 1, 0, OP_NOP
, 0, f_fgetline
,
8233 "read next line from file, newline removed"},
8234 {"fgets", 1, 1, 0, OP_NOP
, 0, f_fgets
,
8235 "read next line from file, newline is kept"},
8236 {"fgetstr", 1, 1, 0, OP_NOP
, 0, f_fgetstr
,
8237 "read next null-terminated string from file, null\n"
8238 "\t\t\tcharacter is kept"},
8239 {"files", 0, 1, 0, OP_NOP
, 0, f_files
,
8240 "return opened file or max number of opened files"},
8241 {"floor", 1, 1, 0, OP_NOP
, 0, f_floor
,
8242 "greatest integer less than or equal to number"},
8243 {"fopen", 2, 2, 0, OP_NOP
, 0, f_fopen
,
8244 "open file name a in mode b"},
8245 {"fpathopen", 2, 3, 0, OP_NOP
, 0, f_fpathopen
,
8246 "open file name a in mode b, search for a along\n"
8247 "\t\t\tCALCPATH or path c"},
8248 {"fprintf", 2, IN
, 0, OP_NOP
, 0, f_fprintf
,
8249 "print formatted output to opened file"},
8250 {"fputc", 2, 2, 0, OP_NOP
, 0, f_fputc
,
8251 "write a character to a file"},
8252 {"fputs", 2, IN
, 0, OP_NOP
, 0, f_fputs
,
8253 "write one or more strings to a file"},
8254 {"fputstr", 2, IN
, 0, OP_NOP
, 0, f_fputstr
,
8255 "write one or more null-terminated strings to a file"},
8256 {"free", 0, IN
, FA
, OP_NOP
, 0, f_free
,
8257 "free listed or all global variables"},
8258 {"freebernoulli", 0, 0, 0, OP_NOP
, 0, f_freebern
,
8259 "free stored Bernoulli numbers"},
8260 {"freeeuler", 0, 0, 0, OP_NOP
, 0, f_freeeuler
,
8261 "free stored Euler numbers"},
8262 {"freeglobals", 0, 0, 0, OP_NOP
, 0, f_freeglobals
,
8263 "free all global and visible static variables"},
8264 {"freeredc", 0, 0, 0, OP_NOP
, 0, f_freeredc
,
8265 "free redc data cache"},
8266 {"freestatics", 0, 0, 0, OP_NOP
, 0, f_freestatics
,
8267 "free all unscoped static variables"},
8268 {"freopen", 2, 3, 0, OP_NOP
, 0, f_freopen
,
8269 "reopen a file stream to a named file"},
8270 {"fscan", 2, IN
, FA
, OP_NOP
, 0, f_fscan
,
8271 "scan a file for assignments to one or\n"
8272 "\t\t\tmore variables"},
8273 {"fscanf", 2, IN
, FA
, OP_NOP
, 0, f_fscanf
,
8274 "formatted scan of a file for assignment to one\n"
8275 "\t\t\tor more variables"},
8276 {"fseek", 2, 3, 0, OP_NOP
, 0, f_fseek
,
8277 "seek to position b (offset from c) in file a"},
8278 {"fsize", 1, 1, 0, OP_NOP
, 0, f_fsize
,
8279 "return the size of the file"},
8280 {"ftell", 1, 1, 0, OP_NOP
, 0, f_ftell
,
8281 "return the file position"},
8282 {"frac", 1, 1, 0, OP_FRAC
, qfrac
, 0,
8283 "fractional part of value"},
8284 {"gcd", 1, IN
, 0, OP_NOP
, f_gcd
, 0,
8285 "greatest common divisor"},
8286 {"gcdrem", 2, 2, 0, OP_NOP
, qgcdrem
, 0,
8287 "a divided repeatedly by gcd with b"},
8288 {"gd", 1, 2, 0, OP_NOP
, 0, f_gd
,
8289 "gudermannian function"},
8290 {"getenv", 1, 1, 0, OP_NOP
, 0, f_getenv
,
8291 "value of environment variable (or NULL)"},
8292 {"hash", 1, IN
, 0, OP_NOP
, 0, f_hash
,
8293 "return non-negative hash value for one or\n"
8294 "\t\t\tmore values"},
8295 {"head", 2, 2, 0, OP_NOP
, 0, f_head
,
8296 "return list of specified number at head of a list"},
8297 {"highbit", 1, 1, 0, OP_HIGHBIT
, 0, 0,
8298 "high bit number in base 2 representation"},
8299 {"hmean", 0, IN
, 0, OP_NOP
, 0, f_hmean
,
8300 "harmonic mean of values"},
8301 {"hnrmod", 4, 4, 0, OP_NOP
, f_hnrmod
, 0,
8302 "v mod h*2^n+r, h>0, n>0, r = -1, 0 or 1"},
8303 {"hypot", 2, 3, FE
, OP_NOP
, qhypot
, 0,
8304 "hypotenuse of right triangle within accuracy c"},
8305 {"ilog", 2, 2, 0, OP_NOP
, 0, f_ilog
,
8306 "integral log of a to integral base b"},
8307 {"ilog10", 1, 1, 0, OP_NOP
, 0, f_ilog10
,
8308 "integral log of a number base 10"},
8309 {"ilog2", 1, 1, 0, OP_NOP
, 0, f_ilog2
,
8310 "integral log of a number base 2"},
8311 {"im", 1, 1, 0, OP_IM
, 0, 0,
8312 "imaginary part of complex number"},
8313 {"indices", 2, 2, 0, OP_NOP
, 0, f_indices
,
8314 "indices of a specified assoc or mat value"},
8315 {"inputlevel", 0, 0, 0, OP_NOP
, 0, f_inputlevel
,
8316 "current input depth"},
8317 {"insert", 2, IN
, FA
, OP_NOP
, 0, f_listinsert
,
8318 "insert values c ... into list a at position b"},
8319 {"int", 1, 1, 0, OP_INT
, qint
, 0,
8320 "integer part of value"},
8321 {"inverse", 1, 1, 0, OP_INVERT
, 0, 0,
8322 "multiplicative inverse of value"},
8323 {"iroot", 2, 2, 0, OP_NOP
, qiroot
, 0,
8324 "integer b'th root of a"},
8325 {"isassoc", 1, 1, 0, OP_ISASSOC
, 0, 0,
8326 "whether a value is an association"},
8327 {"isatty", 1, 1, 0, OP_NOP
, 0, f_isatty
,
8328 "whether a file is a tty"},
8329 {"isblk", 1, 1, 0, OP_ISBLK
, 0, 0,
8330 "whether a value is a block"},
8331 {"isconfig", 1, 1, 0, OP_ISCONFIG
, 0, 0,
8332 "whether a value is a config state"},
8333 {"isdefined", 1, 1, 0, OP_ISDEFINED
, 0, 0,
8334 "whether a string names a function"},
8335 {"iserror", 1, 1, 0, OP_NOP
, 0, f_iserror
,
8336 "where a value is an error"},
8337 {"iseven", 1, 1, 0, OP_ISEVEN
, 0, 0,
8338 "whether a value is an even integer"},
8339 {"isfile", 1, 1, 0, OP_ISFILE
, 0, 0,
8340 "whether a value is a file"},
8341 {"ishash", 1, 1, 0, OP_ISHASH
, 0, 0,
8342 "whether a value is a hash state"},
8343 {"isident", 1, 1, 0, OP_NOP
, 0, f_isident
,
8344 "returns 1 if identity matrix"},
8345 {"isint", 1, 1, 0, OP_ISINT
, 0, 0,
8346 "whether a value is an integer"},
8347 {"islist", 1, 1, 0, OP_ISLIST
, 0, 0,
8348 "whether a value is a list"},
8349 {"ismat", 1, 1, 0, OP_ISMAT
, 0, 0,
8350 "whether a value is a matrix"},
8351 {"ismult", 2, 2, 0, OP_NOP
, f_ismult
, 0,
8352 "whether a is a multiple of b"},
8353 {"isnull", 1, 1, 0, OP_ISNULL
, 0, 0,
8354 "whether a value is the null value"},
8355 {"isnum", 1, 1, 0, OP_ISNUM
, 0, 0,
8356 "whether a value is a number"},
8357 {"isobj", 1, 1, 0, OP_ISOBJ
, 0, 0,
8358 "whether a value is an object"},
8359 {"isobjtype", 1, 1, 0, OP_ISOBJTYPE
, 0,0,
8360 "whether a string names an object type"},
8361 {"isodd", 1, 1, 0, OP_ISODD
, 0, 0,
8362 "whether a value is an odd integer"},
8363 {"isoctet", 1, 1, 0, OP_ISOCTET
, 0, 0,
8364 "whether a value is an octet"},
8365 {"isprime", 1, 2, 0, OP_NOP
, f_isprime
, 0,
8366 "whether a is a small prime, return b if error"},
8367 {"isptr", 1, 1, 0, OP_ISPTR
, 0, 0,
8368 "whether a value is a pointer"},
8369 {"isqrt", 1, 1, 0, OP_NOP
, qisqrt
, 0,
8370 "integer part of square root"},
8371 {"isrand", 1, 1, 0, OP_ISRAND
, 0, 0,
8372 "whether a value is a additive 55 state"},
8373 {"israndom", 1, 1, 0, OP_ISRANDOM
, 0, 0,
8374 "whether a value is a Blum state"},
8375 {"isreal", 1, 1, 0, OP_ISREAL
, 0, 0,
8376 "whether a value is a real number"},
8377 {"isrel", 2, 2, 0, OP_NOP
, f_isrel
, 0,
8378 "whether two numbers are relatively prime"},
8379 {"isstr", 1, 1, 0, OP_ISSTR
, 0, 0,
8380 "whether a value is a string"},
8381 {"issimple", 1, 1, 0, OP_ISSIMPLE
, 0, 0,
8382 "whether value is a simple type"},
8383 {"issq", 1, 1, 0, OP_NOP
, f_issquare
, 0,
8384 "whether or not number is a square"},
8385 {"istype", 2, 2, 0, OP_ISTYPE
, 0, 0,
8386 "whether the type of a is same as the type of b"},
8387 {"jacobi", 2, 2, 0, OP_NOP
, qjacobi
, 0,
8388 "-1 => a is not quadratic residue mod b\n"
8389 "\t\t\t1 => b is composite, or a is quad residue of b"},
8390 {"join", 1, IN
, 0, OP_NOP
, 0, f_join
,
8391 "join one or more lists into one list"},
8392 {"lcm", 1, IN
, 0, OP_NOP
, f_lcm
, 0,
8393 "least common multiple"},
8394 {"lcmfact", 1, 1, 0, OP_NOP
, qlcmfact
, 0,
8395 "lcm of all integers up till number"},
8396 {"lfactor", 2, 2, 0, OP_NOP
, qlowfactor
, 0,
8397 "lowest prime factor of a in first b primes"},
8398 {"links", 1, 1, 0, OP_LINKS
, 0, 0,
8399 "links to number or string value"},
8400 {"list", 0, IN
, 0, OP_NOP
, 0, f_list
,
8401 "create list of specified values"},
8402 {"ln", 1, 2, 0, OP_NOP
, 0, f_ln
,
8403 "natural logarithm of value a within accuracy b"},
8404 {"log", 1, 2, 0, OP_NOP
, 0, f_log
,
8405 "base 10 logarithm of value a within accuracy b"},
8406 {"lowbit", 1, 1, 0, OP_LOWBIT
, 0, 0,
8407 "low bit number in base 2 representation"},
8408 {"ltol", 1, 2, FE
, OP_NOP
, f_legtoleg
, 0,
8409 "leg-to-leg of unit right triangle (sqrt(1 - a^2))"},
8410 {"makelist", 1, 1, 0, OP_NOP
, 0, f_makelist
,
8411 "create a list with a null elements"},
8412 {"matdim", 1, 1, 0, OP_NOP
, 0, f_matdim
,
8413 "number of dimensions of matrix"},
8414 {"matfill", 2, 3, FA
, OP_NOP
, 0, f_matfill
,
8415 "fill matrix with value b (value c on diagonal)"},
8416 {"matmax", 2, 2, 0, OP_NOP
, 0, f_matmax
,
8417 "maximum index of matrix a dim b"},
8418 {"matmin", 2, 2, 0, OP_NOP
, 0, f_matmin
,
8419 "minimum index of matrix a dim b"},
8420 {"matsum", 1, 1, 0, OP_NOP
, 0, f_matsum
,
8421 "sum the numeric values in a matrix"},
8422 {"mattrace", 1, 1, 0, OP_NOP
, 0, f_mattrace
,
8423 "return the trace of a square matrix"},
8424 {"mattrans", 1, 1, 0, OP_NOP
, 0, f_mattrans
,
8425 "transpose of matrix"},
8426 {"max", 0, IN
, 0, OP_NOP
, 0, f_max
,
8428 {"memsize", 1, 1, 0, OP_NOP
, 0, f_memsize
,
8429 "number of octets used by the value, including overhead"},
8430 {"meq", 3, 3, 0, OP_NOP
, f_meq
, 0,
8431 "whether a and b are equal modulo c"},
8432 {"min", 0, IN
, 0, OP_NOP
, 0, f_min
,
8434 {"minv", 2, 2, 0, OP_NOP
, qminv
, 0,
8435 "inverse of a modulo b"},
8436 {"mmin", 2, 2, 0, OP_NOP
, 0, f_mmin
,
8437 "a mod b value with smallest abs value"},
8438 {"mne", 3, 3, 0, OP_NOP
, f_mne
, 0,
8439 "whether a and b are not equal modulo c"},
8440 {"mod", 2, 3, 0, OP_NOP
, 0, f_mod
,
8441 "residue of a modulo b, rounding type c"},
8442 {"modify", 2, 2, FA
, OP_NOP
, 0, f_modify
,
8443 "modify elements of a list or matrix"},
8444 {"name", 1, 1, 0, OP_NOP
, 0, f_name
,
8445 "name assigned to block or file"},
8446 {"near", 2, 3, 0, OP_NOP
, f_near
, 0,
8447 "sign of (abs(a-b) - c)"},
8448 {"newerror", 0, 1, 0, OP_NOP
, 0, f_newerror
,
8449 "create new error type with message a"},
8450 {"nextcand", 1, 5, 0, OP_NOP
, f_nextcand
, 0,
8451 "smallest value == d mod e > a, ptest(a,b,c) true"},
8452 {"nextprime", 1, 2, 0, OP_NOP
, f_nprime
, 0,
8453 "return next small prime, return b if err"},
8454 {"norm", 1, 1, 0, OP_NORM
, 0, 0,
8455 "norm of a value (square of absolute value)"},
8456 {"null", 0, IN
, 0, OP_NOP
, 0, f_null
,
8458 {"num", 1, 1, 0, OP_NUMERATOR
, qnum
, 0,
8459 "numerator of fraction"},
8460 {"ord", 1, 1, 0, OP_NOP
, 0, f_ord
,
8461 "integer corresponding to character value"},
8462 {"param", 1, 1, 0, OP_ARGVALUE
, 0, 0,
8463 "value of parameter n (or parameter count if n\n"
8465 {"perm", 2, 2, 0, OP_NOP
, qperm
, 0,
8466 "permutation number a!/(a-b)!"},
8467 {"prevcand", 1, 5, 0, OP_NOP
, f_prevcand
, 0,
8468 "largest value == d mod e < a, ptest(a,b,c) true"},
8469 {"prevprime", 1, 2, 0, OP_NOP
, f_pprime
, 0,
8470 "return previous small prime, return b if err"},
8471 {"pfact", 1, 1, 0, OP_NOP
, qpfact
, 0,
8472 "product of primes up till number"},
8473 {"pi", 0, 1, FE
, OP_NOP
, qpi
, 0,
8474 "value of pi accurate to within epsilon"},
8475 {"pix", 1, 2, 0, OP_NOP
, f_pix
, 0,
8476 "number of primes <= a < 2^32, return b if error"},
8477 {"places", 1, 2, 0, OP_NOP
, 0, f_places
,
8478 "places after \"decimal\" point (-1 if infinite)"},
8479 {"pmod", 3, 3, 0, OP_NOP
, qpowermod
,0,
8480 "mod of a power (a ^ b (mod c))"},
8481 {"polar", 2, 3, 0, OP_NOP
, 0, f_polar
,
8482 "complex value of polar coordinate (a * exp(b*1i))"},
8483 {"poly", 1, IN
, 0, OP_NOP
, 0, f_poly
,
8484 "evaluates a polynomial given its coefficients\n"
8485 "\t\t\tor coefficient-list"},
8486 {"pop", 1, 1, FA
, OP_NOP
, 0, f_listpop
,
8487 "pop value from front of list"},
8488 {"popcnt", 1, 2, 0, OP_NOP
, f_popcnt
, 0,
8489 "number of bits in a that match b (or 1)"},
8490 {"power", 2, 3, 0, OP_NOP
, 0, f_power
,
8491 "value a raised to the power b within accuracy c"},
8492 {"protect", 1, 3, FA
, OP_NOP
, 0, f_protect
,
8493 "read or set protection level for variable"},
8494 {"ptest", 1, 3, 0, OP_NOP
, f_primetest
, 0,
8495 "probabilistic primality test"},
8496 {"printf", 1, IN
, 0, OP_NOP
, 0, f_printf
,
8497 "print formatted output to stdout"},
8498 {"prompt", 1, 1, 0, OP_NOP
, 0, f_prompt
,
8499 "prompt for input line using value a"},
8500 {"push", 1, IN
, FA
, OP_NOP
, 0, f_listpush
,
8501 "push values onto front of list"},
8502 {"putenv", 1, 2, 0, OP_NOP
, 0, f_putenv
,
8503 "define an environment variable"},
8504 {"quo", 2, 3, 0, OP_NOP
, 0, f_quo
,
8505 "integer quotient of a by b, rounding type c"},
8506 {"quomod", 4, 5, FA
, OP_NOP
, 0, f_quomod
,
8507 "set c and d to quotient and remainder of a\n"
8508 "\t\t\tdivided by b"},
8509 {"rand", 0, 2, 0, OP_NOP
, f_rand
, 0,
8510 "additive 55 random number [0,2^64), [0,a), or [a,b)"},
8511 {"randbit", 0, 1, 0, OP_NOP
, f_randbit
, 0,
8512 "additive 55 random number [0,2^a)"},
8513 {"random", 0, 2, 0, OP_NOP
, f_random
, 0,
8514 "Blum-Blum-Shub random number [0,2^64), [0,a), or [a,b)"},
8515 {"randombit", 0, 1, 0, OP_NOP
, f_randombit
, 0,
8516 "Blum-Blum-Sub random number [0,2^a)"},
8517 {"randperm", 1, 1, 0, OP_NOP
, 0, f_randperm
,
8518 "random permutation of a list or matrix"},
8519 {"rcin", 2, 2, 0, OP_NOP
, qredcin
, 0,
8520 "convert normal number a to REDC number mod b"},
8521 {"rcmul", 3, 3, 0, OP_NOP
, qredcmul
, 0,
8522 "multiply REDC numbers a and b mod c"},
8523 {"rcout", 2, 2, 0, OP_NOP
, qredcout
, 0,
8524 "convert REDC number a mod b to normal number"},
8525 {"rcpow", 3, 3, 0, OP_NOP
, qredcpower
, 0,
8526 "raise REDC number a to power b mod c"},
8527 {"rcsq", 2, 2, 0, OP_NOP
, qredcsquare
, 0,
8528 "square REDC number a mod b"},
8529 {"re", 1, 1, 0, OP_RE
, 0, 0,
8530 "real part of complex number"},
8531 {"remove", 1, 1, FA
, OP_NOP
, 0, f_listremove
,
8532 "remove value from end of list"},
8533 {"reverse", 1, 1, 0, OP_NOP
, 0, f_reverse
,
8534 "reverse a copy of a matrix or list"},
8535 {"rewind", 0, IN
, 0, OP_NOP
, 0, f_rewind
,
8537 {"rm", 1, IN
, 0, OP_NOP
, 0, f_rm
,
8538 "remove file(s), -f turns off no-such-file errors"},
8539 {"root", 2, 3, 0, OP_NOP
, 0, f_root
,
8540 "value a taken to the b'th root within accuracy c"},
8541 {"round", 1, 3, 0, OP_NOP
, 0, f_round
,
8542 "round value a to b number of decimal places"},
8543 {"rsearch", 2, 4, 0, OP_NOP
, 0, f_rsearch
,
8544 "reverse search matrix or list for value b\n"
8545 "\t\t\tstarting at index c"},
8546 {"runtime", 0, 0, 0, OP_NOP
, f_runtime
, 0,
8547 "user and kernel mode cpu time in seconds"},
8548 {"saveval", 1, 1, 0, OP_SAVEVAL
, 0, 0,
8549 "set flag for saving values"},
8550 {"scale", 2, 2, 0, OP_SCALE
, 0, 0,
8551 "scale value up or down by a power of two"},
8552 {"scan", 1, IN
, FA
, OP_NOP
, 0, f_scan
,
8553 "scan standard input for assignment to one\n"
8554 "\t\t\tor more variables"},
8555 {"scanf", 2, IN
, FA
, OP_NOP
, 0, f_scanf
,
8556 "formatted scan of standard input for assignment\n"
8557 "\t\t\tto variables"},
8558 {"search", 2, 4, 0, OP_NOP
, 0, f_search
,
8559 "search matrix or list for value b starting\n"
8560 "\t\t\tat index c"},
8561 {"sec", 1, 2, 0, OP_NOP
, 0, f_sec
,
8562 "sec of a within accuracy b"},
8563 {"sech", 1, 2, 0, OP_NOP
, 0, f_sech
,
8564 "hyperbolic secant of a within accuracy b"},
8565 {"seed", 0, 0, 0, OP_NOP
, f_seed
, 0,
8566 "return a 64 bit seed for a psuedo-random generator"},
8567 {"segment", 2, 3, 0, OP_NOP
, 0, f_segment
,
8568 "specified segment of specified list"},
8569 {"select", 2, 2, 0, OP_NOP
, 0, f_select
,
8570 "form sublist of selected elements from list"},
8571 {"setbit", 2, 3, 0, OP_NOP
, 0, f_setbit
,
8572 "set specified bit in string"},
8573 {"sgn", 1, 1, 0, OP_SGN
, qsign
, 0,
8574 "sign of value (-1, 0, 1)"},
8575 {"sha1", 0, IN
, 0, OP_NOP
, 0, f_sha1
,
8576 "Secure Hash Algorithm (SHS-1 FIPS Pub 180-1)"},
8577 {"sin", 1, 2, 0, OP_NOP
, 0, f_sin
,
8578 "sine of value a within accuracy b"},
8579 {"sinh", 1, 2, 0, OP_NOP
, 0, f_sinh
,
8580 "hyperbolic sine of a within accuracy b"},
8581 {"size", 1, 1, 0, OP_NOP
, 0, f_size
,
8582 "total number of elements in value"},
8583 {"sizeof", 1, 1, 0, OP_NOP
, 0, f_sizeof
,
8584 "number of octets used to hold the value"},
8585 {"sleep", 0, 1, 0, OP_NOP
, 0, f_sleep
,
8586 "suspend operation for a seconds"},
8587 {"sort", 1, 1, 0, OP_NOP
, 0, f_sort
,
8588 "sort a copy of a matrix or list"},
8589 {"sqrt", 1, 3, 0, OP_NOP
, 0, f_sqrt
,
8590 "square root of value a within accuracy b"},
8591 {"srand", 0, 1, 0, OP_NOP
, 0, f_srand
,
8592 "seed the rand() function"},
8593 {"srandom", 0, 4, 0, OP_NOP
, 0, f_srandom
,
8594 "seed the random() function"},
8595 {"ssq", 1, IN
, 0, OP_NOP
, 0, f_ssq
,
8596 "sum of squares of values"},
8597 {"stoponerror", 0, 1, 0, OP_NOP
, 0, f_stoponerror
,
8598 "assign value to stoponerror flag"},
8599 {"str", 1, 1, 0, OP_NOP
, 0, f_str
,
8600 "simple value converted to string"},
8601 {"strcat", 1,IN
, 0, OP_NOP
, 0, f_strcat
,
8602 "concatenate strings together"},
8603 {"strcmp", 2, 2, 0, OP_NOP
, 0, f_strcmp
,
8604 "compare two strings"},
8605 {"strcpy", 2, 2, 0, OP_NOP
, 0, f_strcpy
,
8606 "copy string to string"},
8607 {"strerror", 0, 1, 0, OP_NOP
, 0, f_strerror
,
8608 "string describing error type"},
8609 {"strlen", 1, 1, 0, OP_NOP
, 0, f_strlen
,
8610 "length of string"},
8611 {"strncmp", 3, 3, 0, OP_NOP
, 0, f_strncmp
,
8612 "compare strings a, b to c characters"},
8613 {"strncpy", 3, 3, 0, OP_NOP
, 0, f_strncpy
,
8614 "copy up to c characters from string to string"},
8615 {"strpos", 2, 2, 0, OP_NOP
, 0, f_strpos
,
8616 "index of first occurrence of b in a"},
8617 {"strprintf", 1, IN
, 0, OP_NOP
, 0, f_strprintf
,
8618 "return formatted output as a string"},
8619 {"strscan", 2, IN
, FA
, OP_NOP
, 0, f_strscan
,
8620 "scan a string for assignments to one or more variables"},
8621 {"strscanf", 2, IN
, FA
, OP_NOP
, 0, f_strscanf
,
8622 "formatted scan of string for assignments to variables"},
8623 {"substr", 3, 3, 0, OP_NOP
, 0, f_substr
,
8624 "substring of a from position b for c chars"},
8625 {"sum", 0, IN
, 0, OP_NOP
, 0, f_sum
,
8626 "sum of list or object sums and/or other terms"},
8627 {"swap", 2, 2, 0, OP_SWAP
, 0, 0,
8628 "swap values of variables a and b (can be dangerous)"},
8629 {"system", 1, 1, 0, OP_NOP
, 0, f_system
,
8630 "call Unix command"},
8631 {"systime", 0, 0, 0, OP_NOP
, f_systime
, 0,
8632 "kernel mode cpu time in seconds"},
8633 {"tail", 2, 2, 0, OP_NOP
, 0, f_tail
,
8634 "retain list of specified number at tail of list"},
8635 {"tan", 1, 2, 0, OP_NOP
, 0, f_tan
,
8636 "tangent of a within accuracy b"},
8637 {"tanh", 1, 2, 0, OP_NOP
, 0, f_tanh
,
8638 "hyperbolic tangent of a within accuracy b"},
8639 {"test", 1, 1, 0, OP_TEST
, 0, 0,
8640 "test that value is nonzero"},
8641 {"time", 0, 0, 0, OP_NOP
, f_time
, 0,
8642 "number of seconds since 00:00:00 1 Jan 1970 UTC"},
8643 {"trunc", 1, 2, 0, OP_NOP
, f_trunc
, 0,
8644 "truncate a to b number of decimal places"},
8645 {"ungetc", 2, 2, 0, OP_NOP
, 0, f_ungetc
,
8646 "unget char read from file"},
8647 {"usertime", 0, 0, 0, OP_NOP
, f_usertime
, 0,
8648 "user mode cpu time in seconds"},
8649 {"version", 0, 0, 0, OP_NOP
, 0, f_version
,
8650 "calc version string"},
8651 {"xor", 1, IN
, 0, OP_NOP
, 0, f_xor
,
8655 {NULL
, 0, 0, 0, 0, 0, 0,
8661 * Show the list of primitive built-in functions
8663 * When FUNCLIST is defined, we are being compiled by rules from the help
8664 * sub-directory to form a program that will produce the main part of the
8665 * buiiltin help file.
8667 * See the builtin rule in the help/Makefile for details.
8669 #if defined(FUNCLIST)
8672 main(int argc
, char *argv
[])
8674 CONST
struct builtin
*bp
; /* current function */
8676 printf("\nName\tArgs\tDescription\n\n");
8677 for (bp
= builtins
; bp
->b_name
; bp
++) {
8678 printf("%-9s ", bp
->b_name
);
8679 if (bp
->b_maxargs
== IN
)
8680 printf("%d+ ", bp
->b_minargs
);
8681 else if (bp
->b_minargs
== bp
->b_maxargs
)
8682 printf("%-6d", bp
->b_minargs
);
8684 printf("%d-%-4d", bp
->b_minargs
, bp
->b_maxargs
);
8685 printf("%s\n", bp
->b_desc
);
8688 return 0; /* exit(0); */
8690 #else /* FUNCLIST */
8694 CONST
struct builtin
*bp
; /* current function */
8697 printf("\nName\tArgs\tDescription\n\n");
8698 for (bp
= builtins
, i
= 0; bp
->b_name
; bp
++, i
++) {
8699 printf("%-14s ", bp
->b_name
);
8700 if (bp
->b_maxargs
== IN
)
8701 printf("%d+ ", bp
->b_minargs
);
8702 else if (bp
->b_minargs
== bp
->b_maxargs
)
8703 printf("%-6d", bp
->b_minargs
);
8705 printf("%d-%-4d", bp
->b_minargs
, bp
->b_maxargs
);
8706 printf("%s\n", bp
->b_desc
);
8709 if (getchar() == 27)
8715 #endif /* FUNCLIST */
8718 #if !defined(FUNCLIST)
8721 * Call a built-in function.
8722 * Arguments to the function are on the stack, but are not removed here.
8723 * Functions are either purely numeric, or else can take any value type.
8726 * index index on where to scan in builtin table
8727 * argcount number of args
8728 * stck arguments on the stack
8731 builtinfunc(long index
, int argcount
, VALUE
*stck
)
8733 VALUE
*sp
; /* pointer to stack entries */
8734 VALUE
**vpp
; /* pointer to current value address */
8735 CONST
struct builtin
*bp
; /* builtin function to be called */
8736 NUMBER
*numargs
[IN
]; /* numeric arguments for function */
8737 VALUE
*valargs
[IN
]; /* addresses of actual arguments */
8738 VALUE result
; /* general result of function */
8741 if ((unsigned long)index
>=
8742 (sizeof(builtins
) / sizeof(builtins
[0])) - 1) {
8743 math_error("Bad built-in function index");
8746 bp
= &builtins
[index
];
8747 if (argcount
< bp
->b_minargs
) {
8748 math_error("Too few arguments for builtin function \"%s\"",
8752 if ((argcount
> bp
->b_maxargs
) || (argcount
> IN
)) {
8753 math_error("Too many arguments for builtin function \"%s\"",
8758 * If an address was passed, then point at the real variable,
8759 * otherwise point at the stack value itself (unless the function
8762 sp
= stck
- argcount
+ 1;
8764 for (i
= argcount
; i
> 0; i
--) {
8765 if ((sp
->v_type
!= V_ADDR
) || (bp
->b_flags
& FA
))
8773 * Handle general values if the function accepts them.
8775 if (bp
->b_valfunc
) {
8777 if ((bp
->b_minargs
== 1) && (bp
->b_maxargs
== 1))
8778 result
= (*bp
->b_valfunc
)(vpp
[0]);
8779 else if ((bp
->b_minargs
== 2) && (bp
->b_maxargs
== 2))
8780 result
= (*bp
->b_valfunc
)(vpp
[0], vpp
[1]);
8781 else if ((bp
->b_minargs
== 3) && (bp
->b_maxargs
== 3))
8782 result
= (*bp
->b_valfunc
)(vpp
[0], vpp
[1], vpp
[2]);
8783 else if ((bp
->b_minargs
== 4) && (bp
->b_maxargs
== 4))
8784 result
= (*bp
->b_valfunc
)(vpp
[0],vpp
[1],vpp
[2],vpp
[3]);
8786 result
= (*bp
->b_valfunc
)(argcount
, vpp
);
8790 * Function must be purely numeric, so handle that.
8793 for (i
= 0; i
< argcount
; i
++) {
8794 if ((*vpp
)->v_type
!= V_NUM
) {
8795 math_error("Non-real argument for builtin function %s",
8799 numargs
[i
] = (*vpp
)->v_num
;
8802 result
.v_type
= V_NUM
;
8803 result
.v_subtype
= V_NOSUBTYPE
;
8804 if (!(bp
->b_flags
& FE
) && (bp
->b_minargs
!= bp
->b_maxargs
)) {
8805 result
.v_num
= (*bp
->b_numfunc
)(argcount
, numargs
);
8808 if ((bp
->b_flags
& FE
) && (argcount
< bp
->b_maxargs
))
8809 numargs
[argcount
++] = conf
->epsilon
;
8813 result
.v_num
= (*bp
->b_numfunc
)();
8816 result
.v_num
= (*bp
->b_numfunc
)(numargs
[0]);
8819 result
.v_num
= (*bp
->b_numfunc
)(numargs
[0], numargs
[1]);
8822 result
.v_num
= (*bp
->b_numfunc
)(numargs
[0],
8823 numargs
[1], numargs
[2]);
8826 result
.v_num
= (*bp
->b_numfunc
)(numargs
[0], numargs
[1],
8827 numargs
[2], numargs
[3]);
8830 math_error("Bad builtin function call");
8838 * Return the index of a built-in function given its name.
8839 * Returns minus one if the name is not known.
8842 getbuiltinfunc(char *name
)
8844 CONST
struct builtin
*bp
;
8846 for (bp
= builtins
; bp
->b_name
; bp
++) {
8847 if ((*name
== *bp
->b_name
) && (strcmp(name
, bp
->b_name
) == 0))
8848 return (bp
- builtins
);
8855 * Given the index of a built-in function, return its name.
8858 builtinname(long index
)
8860 if ((unsigned long)index
>=
8861 (sizeof(builtins
) / sizeof(builtins
[0])) - 1)
8863 return builtins
[index
].b_name
;
8868 * Given the index of a built-in function, and the number of arguments seen,
8869 * determine if the number of arguments are legal. This routine is called
8870 * during parsing time.
8873 builtincheck(long index
, int count
)
8875 CONST
struct builtin
*bp
;
8877 if ((unsigned long)index
>=
8878 (sizeof(builtins
) / sizeof(builtins
[0])) - 1) {
8879 math_error("Unknown built in index");
8882 bp
= &builtins
[index
];
8883 if (count
< bp
->b_minargs
)
8885 "Too few arguments for builtin function \"%s\"",
8887 if (count
> bp
->b_maxargs
)
8889 "Too many arguments for builtin function \"%s\"",
8895 * Return the opcode for a built-in function that can be used to avoid
8896 * the function call at all.
8899 builtinopcode(long index
)
8901 if ((unsigned long)index
>=
8902 (sizeof(builtins
) / sizeof(builtins
[0])) - 1)
8904 return builtins
[index
].b_opcode
;
8908 * Show the error-values created by newerror(str).
8915 if (nexterrnum
== E_USERDEF
)
8916 printf("No new error-values created\n");
8917 for (i
= E_USERDEF
; i
< nexterrnum
; i
++)
8918 printf("%d: %s\n", i
,
8919 namestr(&newerrorstr
, i
- E_USERDEF
));
8924 * malloced_putenv - Keep track of malloced environment variable storage
8927 * str a malloced string which will be given to putenv
8930 * putenv() return value
8932 * NOTE: The caller MUST pass a string that the caller has previously malloced.
8935 malloced_putenv(char *str
)
8937 char *value
; /* location of the value part of the str argument */
8938 char *old_val
; /* previously stored (or inherited) env value */
8939 int found_cnt
; /* number of active env_pool entries found */
8940 struct env_pool
*new; /* new e_pool */
8947 math_error("malloced_putenv given a NULL pointer!!");
8950 if (str
[0] == '=') {
8951 math_error("malloced_putenv = is first character in string!!");
8956 * determine the place where getenv would return
8958 value
= strchr(str
, '=');
8959 if (value
== NULL
) {
8960 math_error("malloced_putenv = not found in string!!");
8966 * lookup for an existing environment value
8969 old_val
= getenv(str
);
8973 * If we have the value in our environment, look for a
8974 * previously malloced string and free it
8976 if (old_val
!= NULL
&& env_pool_cnt
> 0) {
8977 for (i
=0, found_cnt
=0;
8978 i
< env_pool_max
&& found_cnt
< env_pool_cnt
;
8981 /* skip an unused entry */
8982 if (e_pool
[i
].getenv
== NULL
) {
8987 /* look for the 1st match */
8988 if (e_pool
[i
].getenv
== value
) {
8990 /* found match, free the storage */
8991 if (e_pool
[i
].putenv
!= NULL
) {
8992 free(e_pool
[i
].putenv
);
8994 e_pool
[i
].getenv
= NULL
;
9002 * ensure that we have room in the e_pool
9004 if (env_pool_max
== 0) {
9006 /* allocate an initial pool (with one extra guard value) */
9007 new = (struct env_pool
*)malloc((ENV_POOL_CHUNK
+1) *
9008 sizeof(struct env_pool
));
9010 math_error("malloced_putenv malloc failed");
9014 env_pool_max
= ENV_POOL_CHUNK
;
9015 for (i
=0; i
<= ENV_POOL_CHUNK
; ++i
) {
9016 e_pool
[i
].getenv
= NULL
;
9019 } else if (env_pool_cnt
>= env_pool_max
) {
9021 /* expand the current pool (with one extra guard value) */
9022 new = (struct env_pool
*)realloc(e_pool
,
9023 (env_pool_max
+ENV_POOL_CHUNK
+1) *
9024 sizeof(struct env_pool
));
9026 math_error("malloced_putenv realloc failed");
9030 for (i
=env_pool_max
; i
<= env_pool_max
+ ENV_POOL_CHUNK
; ++i
) {
9031 e_pool
[i
].getenv
= NULL
;
9033 env_pool_max
+= ENV_POOL_CHUNK
;
9037 * store our data into the first e_pool entry
9039 for (i
=0; i
< env_pool_max
; ++i
) {
9041 /* skip used entries */
9042 if (e_pool
[i
].getenv
!= NULL
) {
9046 /* store in this free entry and stop looping */
9047 e_pool
[i
].getenv
= value
;
9048 e_pool
[i
].putenv
= str
;
9052 if (i
>= env_pool_max
) {
9053 math_error("malloced_putenv missed unused entry!!");
9058 * finally, do the putenv action
9064 #endif /* FUNCLIST */