modified: makefile
[GalaxyCodeBases.git] / c_cpp / etc / calc / config.c
blob87b903ae6531e1e103e30bb4d0c784b9ca3a46c5
1 /*
2 * config - configuration routines
4 * Copyright (C) 1999-2007 David I. Bell and Landon Curt Noll
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.3 $
23 * @(#) $Id: config.c,v 30.3 2013/08/11 08:41:38 chongo Exp $
24 * @(#) $Source: /usr/local/src/bin/calc/RCS/config.c,v $
26 * Under source code control: 1991/07/20 00:21:56
27 * File existed as early as: 1991
29 * Share and enjoy! :-) http://www.isthe.com/chongo/tech/comp/calc/
33 #include <stdio.h>
35 #include "have_times.h"
36 #if defined(HAVE_TIME_H)
37 #include <time.h>
38 #endif
40 #if defined(HAVE_TIMES_H)
41 #include <times.h>
42 #endif
44 #if defined(HAVE_SYS_TIME_H)
45 #include <sys/time.h>
46 #endif
48 #if defined(HAVE_SYS_TIMES_H)
49 #include <sys/times.h>
50 #endif
52 #include "calc.h"
53 #include "token.h"
54 #include "zrand.h"
55 #include "block.h"
56 #include "nametype.h"
57 #include "config.h"
58 #include "str.h"
59 #include "custom.h"
61 #include "have_strdup.h"
62 #if !defined(HAVE_STRDUP)
63 # define strdup(x) calc_strdup((CONST char *)(x))
64 #endif /* HAVE_STRDUP */
67 * deal with systems that lack a defined CLK_TCK
69 #if defined(CLK_TCK)
70 # define CALC_HZ ((long)(CLK_TCK))
71 #else
72 # define CALC_HZ (0L) /* no defined clock tick rate */
73 #endif
77 * Table of configuration types that can be set or read.
79 NAMETYPE configs[] = {
80 {"all", CONFIG_ALL},
81 {"mode", CONFIG_MODE},
82 {"mode2", CONFIG_MODE2},
83 {"display", CONFIG_DISPLAY},
84 {"epsilon", CONFIG_EPSILON},
85 /*epsilonprec -- tied to epsilon not a configuration type*/
86 {"trace", CONFIG_TRACE},
87 {"maxprint", CONFIG_MAXPRINT},
88 {"mul2", CONFIG_MUL2},
89 {"sq2", CONFIG_SQ2},
90 {"pow2", CONFIG_POW2},
91 {"redc2", CONFIG_REDC2},
92 {"tilde", CONFIG_TILDE},
93 {"tab", CONFIG_TAB},
94 {"quomod", CONFIG_QUOMOD},
95 {"quo", CONFIG_QUO},
96 {"mod", CONFIG_MOD},
97 {"sqrt", CONFIG_SQRT},
98 {"appr", CONFIG_APPR},
99 {"cfappr", CONFIG_CFAPPR},
100 {"cfsim", CONFIG_CFSIM},
101 {"outround", CONFIG_OUTROUND},
102 {"round", CONFIG_ROUND},
103 {"leadzero", CONFIG_LEADZERO},
104 {"fullzero", CONFIG_FULLZERO},
105 {"maxscan", CONFIG_MAXSCAN},
106 {"maxerr", CONFIG_MAXSCAN}, /* old name for maxscan */
107 {"prompt", CONFIG_PROMPT},
108 {"more", CONFIG_MORE},
109 {"blkmaxprint", CONFIG_BLKMAXPRINT},
110 {"blkverbose", CONFIG_BLKVERBOSE},
111 {"blkbase", CONFIG_BLKBASE},
112 {"blkfmt", CONFIG_BLKFMT},
113 {"resource_debug", CONFIG_RESOURCE_DEBUG},
114 {"lib_debug", CONFIG_RESOURCE_DEBUG},
115 {"calc_debug", CONFIG_CALC_DEBUG},
116 {"user_debug", CONFIG_USER_DEBUG},
117 {"verbose_quit",CONFIG_VERBOSE_QUIT},
118 {"ctrl_d", CONFIG_CTRL_D},
119 {"ctrl-d", CONFIG_CTRL_D}, /* alias for ctrl_d */
120 {"program", CONFIG_PROGRAM},
121 {"basename", CONFIG_BASENAME},
122 {"windows", CONFIG_WINDOWS},
123 {"cygwin", CONFIG_CYGWIN},
124 {"compile_custom", CONFIG_COMPILE_CUSTOM},
125 {"allow_custom", CONFIG_ALLOW_CUSTOM},
126 {"version", CONFIG_VERSION},
127 {"baseb", CONFIG_BASEB},
128 {"redecl_warn", CONFIG_REDECL_WARN},
129 {"dupvar_warn", CONFIG_DUPVAR_WARN},
130 {"hz", CONFIG_HZ},
131 {NULL, 0}
136 * configurations
138 CONFIG oldstd = { /* backward compatible standard configuration */
139 MODE_INITIAL, /* current output mode */
140 MODE2_INITIAL, /* current secondary output mode */
141 20, /* current output digits for float or exp */
142 NULL, /* loaded in at startup - default error for real functions */
143 EPSILONPREC_DEFAULT, /* binary precision of epsilon */
144 FALSE, /* tracing flags */
145 MAXPRINT_DEFAULT, /* number of elements to print */
146 MUL_ALG2, /* size of number to use multiply alg 2 */
147 SQ_ALG2, /* size of number to use square alg 2 */
148 POW_ALG2, /* size of modulus to use REDC for powers */
149 REDC_ALG2, /* size of modulus to use REDC algorithm 2 */
150 TRUE, /* ok to print a tilde on approximations */
151 TRUE, /* ok to print tab before numeric values */
152 0, /* quomod() default rounding mode */
153 2, /* quotient // default rounding mode */
154 0, /* mod % default rounding mode */
155 24, /* sqrt() default rounding mode */
156 24, /* appr() default rounding mode */
157 0, /* cfappr() default rounding mode */
158 8, /* cfsim() default rounding mode */
159 2, /* output default rounding mode */
160 24, /* round()/bround() default rounding mode */
161 FALSE, /* ok to print leading 0 before decimal pt */
162 0, /* ok to print trailing 0's */
163 MAXSCANCOUNT, /* max scan errors before abort */
164 PROMPT1, /* normal prompt */
165 PROMPT2, /* prompt when inside multi-line input */
166 BLK_DEF_MAXPRINT, /* number of octets of a block to print */
167 FALSE, /* skip duplicate block output lines */
168 BLK_BASE_HEX, /* block octet print base */
169 BLK_FMT_HD_STYLE, /* block output format */
170 0, /* internal calc debug level */
171 3, /* calc resource file debug level */
172 0, /* user defined debug level */
173 FALSE, /* print Quit or abort executed messages */
174 CTRL_D_VIRGIN_EOF, /* ^D only exits on virgin lines */
175 NULL, /* our name */
176 NULL, /* basename of our name */
177 #if defined(_WIN32)
178 TRUE, /* running under windows */
179 #else
180 FALSE, /* congrats, you are not using windows */
181 #endif
182 #if defined(__CYGWIN__)
183 TRUE, /* compiled under cygwin */
184 #else
185 FALSE, /* not compiled with cygwin */
186 #endif
187 #if defined(CUSTOM)
188 TRUE, /* compiled with -DCUSTOM */
189 #else
190 FALSE, /* compiled without -DCUSTOM */
191 #endif
192 &allow_custom, /* *TRUE=> custom functions are enabled */
193 NULL, /* version */
194 BASEB, /* base for calculations */
195 TRUE, /* warn when redeclaring */
196 TRUE, /* warn when variable names collide */
198 CONFIG newstd = { /* new non-backward compatible configuration */
199 MODE_INITIAL, /* current output mode */
200 MODE2_INITIAL, /* current output mode */
201 20, /* current output digits for float or exp */
202 NULL, /* loaded in at startup - default error for real functions */
203 EPSILONPREC_DEFAULT, /* binary precision of epsilon */
204 FALSE, /* tracing flags */
205 MAXPRINT_DEFAULT, /* number of elements to print */
206 MUL_ALG2, /* size of number to use multiply alg 2 */
207 SQ_ALG2, /* size of number to use square alg 2 */
208 POW_ALG2, /* size of modulus to use REDC for powers */
209 REDC_ALG2, /* size of modulus to use REDC algorithm 2 */
210 TRUE, /* ok to print a tilde on approximations */
211 TRUE, /* ok to print tab before numeric values */
212 0, /* quomod() default rounding mode */
213 2, /* quotient // default rounding mode */
214 0, /* mod % default rounding mode */
215 24, /* sqrt() default rounding mode */
216 24, /* appr() default rounding mode */
217 0, /* cfappr() default rounding mode */
218 8, /* cfsim() default rounding mode */
219 24, /* output default rounding mode */
220 24, /* round()/bround() default rounding mode */
221 TRUE, /* ok to print leading 0 before decimal pt */
222 0, /* ok to print trailing 0's */
223 MAXSCANCOUNT, /* max scan errors before abort */
224 "; ", /* normal prompt */
225 ";; ", /* prompt when inside multi-line input */
226 BLK_DEF_MAXPRINT, /* number of octets of a block to print */
227 FALSE, /* skip duplicate block output lines */
228 BLK_BASE_HEX, /* block octet print base */
229 BLK_FMT_HD_STYLE, /* block output format */
230 0, /* internal calc debug level */
231 3, /* calc resource file debug level */
232 0, /* user defined debug level */
233 FALSE, /* print Quit or abort executed messages */
234 CTRL_D_VIRGIN_EOF, /* ^D only exits on virgin lines */
235 NULL, /* our name */
236 NULL, /* basename of our name */
237 #if defined(_WIN32)
238 TRUE, /* running under windows */
239 #else
240 FALSE, /* congrats, you are not using windows */
241 #endif
242 #if defined(__CYGWIN__)
243 TRUE, /* compiled under cygwin */
244 #else
245 FALSE, /* not compiled with cygwin */
246 #endif
247 #if defined(CUSTOM)
248 TRUE, /* compiled with -DCUSTOM */
249 #else
250 FALSE, /* compiled without -DCUSTOM */
251 #endif
252 &allow_custom, /* *TRUE=> custom functions are enabled */
253 NULL, /* version */
254 BASEB, /* base for calculations */
255 TRUE, /* warn when redeclaring */
256 TRUE, /* warn when variable names collide */
258 CONFIG *conf = NULL; /* loaded in at startup - current configuration */
262 * Possible output modes.
264 STATIC NAMETYPE modes[] = {
265 {"fraction", MODE_FRAC},
266 {"frac", MODE_FRAC},
267 {"integer", MODE_INT},
268 {"int", MODE_INT},
269 {"real", MODE_REAL},
270 {"float", MODE_REAL},
271 {"default", MODE_INITIAL}, /* MODE_REAL */
272 {"scientific", MODE_EXP},
273 {"sci", MODE_EXP},
274 {"exp", MODE_EXP},
275 {"hexadecimal", MODE_HEX},
276 {"hex", MODE_HEX},
277 {"octal", MODE_OCTAL},
278 {"oct", MODE_OCTAL},
279 {"binary", MODE_BINARY},
280 {"bin", MODE_BINARY},
281 {"off", MODE2_OFF},
282 {NULL, 0}
287 * Possible block base output modes
289 STATIC NAMETYPE blk_base[] = {
290 {"hexadecimal", BLK_BASE_HEX},
291 {"hex", BLK_BASE_HEX},
292 {"default", BLK_BASE_HEX},
293 {"octal", BLK_BASE_OCT},
294 {"oct", BLK_BASE_OCT},
295 {"character", BLK_BASE_CHAR},
296 {"char", BLK_BASE_CHAR},
297 {"binary", BLK_BASE_BINARY},
298 {"bin", BLK_BASE_BINARY},
299 {"raw", BLK_BASE_RAW},
300 {"none", BLK_BASE_RAW},
301 {NULL, 0}
306 * Possible block output formats
308 STATIC NAMETYPE blk_fmt[] = {
309 {"lines", BLK_FMT_LINE},
310 {"line", BLK_FMT_LINE},
311 {"strings", BLK_FMT_STRING},
312 {"string", BLK_FMT_STRING},
313 {"str", BLK_FMT_STRING},
314 {"od_style", BLK_FMT_OD_STYLE},
315 {"odstyle", BLK_FMT_OD_STYLE},
316 {"od", BLK_FMT_OD_STYLE},
317 {"hd_style", BLK_FMT_HD_STYLE},
318 {"hdstyle", BLK_FMT_HD_STYLE},
319 {"hd", BLK_FMT_HD_STYLE},
320 {"default", BLK_FMT_HD_STYLE},
321 {NULL, 0}
326 * Possible ctrl_d styles
328 STATIC NAMETYPE ctrl_d[] = {
329 {"virgin_eof", CTRL_D_VIRGIN_EOF},
330 {"virgineof", CTRL_D_VIRGIN_EOF},
331 {"virgin", CTRL_D_VIRGIN_EOF},
332 {"default", CTRL_D_VIRGIN_EOF},
333 {"never_eof", CTRL_D_NEVER_EOF},
334 {"nevereof", CTRL_D_NEVER_EOF},
335 {"never", CTRL_D_NEVER_EOF},
336 {"empty_eof", CTRL_D_EMPTY_EOF},
337 {"emptyeof", CTRL_D_EMPTY_EOF},
338 {"empty", CTRL_D_EMPTY_EOF},
339 {NULL, 0}
344 * Possible binary config state values
346 #define TRUE_STRING "true"
347 #define FALSE_STRING "false"
348 STATIC NAMETYPE truth[] = {
349 {TRUE_STRING, TRUE},
350 {"t", TRUE},
351 {"on", TRUE},
352 {"yes", TRUE},
353 {"y", TRUE},
354 {"set", TRUE},
355 {"1", TRUE},
356 {FALSE_STRING, FALSE},
357 {"f", FALSE},
358 {"off", FALSE},
359 {"no", FALSE},
360 {"n", FALSE},
361 {"unset", FALSE},
362 {"0", FALSE},
363 {NULL, 0}
368 * declare static functions
370 S_FUNC long lookup_long(NAMETYPE *set, char *name);
371 S_FUNC char *lookup_name(NAMETYPE *set, long val);
372 S_FUNC int getlen(VALUE *vp, LEN *lp);
376 * Given a string value which represents a configuration name, return
377 * the configuration type for that string. Returns negative type if
378 * the string is unknown.
380 * given:
381 * name configuration name
384 configtype(char *name)
386 NAMETYPE *cp; /* current config pointer */
388 for (cp = configs; cp->name; cp++) {
389 if (strcmp(cp->name, name) == 0)
390 return cp->type;
392 return -1;
397 * lookup_long - given a name and a NAMETYPE, return the int
399 * given:
400 * set the NAMESET array of name/int pairs
401 * name mode name
403 * returns:
404 * numeric value of the name or -1 if not found
406 S_FUNC long
407 lookup_long(NAMETYPE *set, char *name)
409 NAMETYPE *cp; /* current config pointer */
411 for (cp = set; cp->name; cp++) {
412 if (strcmp(cp->name, name) == 0)
413 return cp->type;
415 return -1;
420 * lookup_name - given numeric value and a NAMETYPE, return the name
422 * given:
423 * set the NAMESET array of name/int pairs
424 * val numeric value to lookup
426 * returns:
427 * name of the value found of NULL
429 S_FUNC char *
430 lookup_name(NAMETYPE *set, long val)
432 NAMETYPE *cp; /* current config pointer */
434 for (cp = set; cp->name; cp++) {
435 if (val == cp->type)
436 return cp->name;
438 return NULL;
443 * Check whether VALUE at vp is a LEN (32-bit signed integer) and if so,
444 * copy that integer to lp.
446 * Return: 1 ==> not an integer, 2 ==> int > 2^31, 0 ==> OK, -1 ==> error
449 S_FUNC int
450 getlen(VALUE *vp, LEN *lp)
452 if (vp->v_type != V_NUM || !qisint(vp->v_num))
453 return 1;
454 if (zge31b(vp->v_num->num))
455 return 2;
456 *lp = ztoi(vp->v_num->num);
457 if (*lp < 0)
458 return -1;
459 return 0;
464 * Set the specified configuration type to the specified value.
465 * An error is generated if the type number or value is illegal.
467 void
468 setconfig(int type, VALUE *vp)
470 NUMBER *q;
471 CONFIG *newconf; /* new configuration to set */
472 long temp;
473 LEN len = 0;
474 char *p;
476 switch (type) {
477 case CONFIG_ALL:
478 newconf = NULL; /* firewall */
479 if (vp->v_type == V_STR) {
480 if (strcmp(vp->v_str->s_str, "oldstd") == 0) {
481 newconf = &oldstd;
482 } else if (strcmp(vp->v_str->s_str, "newstd") == 0) {
483 newconf = &newstd;
484 } else {
485 math_error("CONFIG alias not oldstd or newstd");
486 /*NOTREACHED*/
488 } else if (vp->v_type != V_CONFIG) {
489 math_error("non-CONFIG for all");
490 /*NOTREACHED*/
491 } else {
492 newconf = vp->v_config;
495 /* free the current configuration */
496 config_free(conf);
498 /* set the new configuration */
499 conf = config_copy(newconf);
500 break;
502 case CONFIG_TRACE:
503 if (vp->v_type != V_NUM) {
504 math_error("Non-numeric for trace");
505 /*NOTREACHED*/
507 q = vp->v_num;
508 temp = qtoi(q);
509 if (qisfrac(q) || !zistiny(q->num) ||
510 ((unsigned long) temp > TRACE_MAX)) {
511 math_error("Bad trace value");
512 /*NOTREACHED*/
514 conf->traceflags = (FLAG)temp;
515 break;
517 case CONFIG_DISPLAY:
518 if (getlen(vp, &len)) {
519 math_error("Bad value for display");
520 /*NOTREACHED*/
522 math_setdigits(len);
523 break;
525 case CONFIG_MODE:
526 if (vp->v_type != V_STR) {
527 math_error("Non-string for mode");
528 /*NOTREACHED*/
530 temp = lookup_long(modes, vp->v_str->s_str);
531 if (temp < 0) {
532 math_error("Unknown mode \"%s\"", vp->v_str->s_str);
533 /*NOTREACHED*/
535 math_setmode((int) temp);
536 break;
538 case CONFIG_MODE2:
539 if (vp->v_type != V_STR) {
540 math_error("Non-string for mode");
541 /*NOTREACHED*/
543 temp = lookup_long(modes, vp->v_str->s_str);
544 if (temp < 0) {
545 math_error("Unknown mode \"%s\"", vp->v_str->s_str);
546 /*NOTREACHED*/
548 math_setmode2((int) temp);
549 break;
551 case CONFIG_EPSILON:
552 if (vp->v_type != V_NUM) {
553 math_error("Non-numeric for epsilon");
554 /*NOTREACHED*/
556 setepsilon(vp->v_num);
557 break;
559 case CONFIG_MAXPRINT:
560 if (getlen(vp, &len)) {
561 math_error("Bad value for maxprint");
562 /*NOTREACHED*/
564 conf->maxprint = len;
565 break;
567 case CONFIG_MUL2:
568 if (getlen(vp, &len) || len < 0 || len == 1) {
569 math_error("Bad value for mul2");
570 /*NOTREACHED*/
572 if (len == 0)
573 len = MUL_ALG2;
574 conf->mul2 = len;
575 break;
577 case CONFIG_SQ2:
578 if (getlen(vp, &len) || len < 0 || len == 1) {
579 math_error("Bad value for sq2");
580 /*NOTREACHED*/
582 if (len == 0)
583 len = SQ_ALG2;
584 conf->sq2 = len;
585 break;
587 case CONFIG_POW2:
588 if (getlen(vp, &len) || len < 0 || len == 1) {
589 math_error("Bad value for pow2");
590 /*NOTREACHED*/
592 if (len == 0)
593 len = POW_ALG2;
594 conf->pow2 = len;
595 break;
597 case CONFIG_REDC2:
598 if (getlen(vp, &len) || len < 0 || len == 1) {
599 math_error("Bad value for redc2");
600 /*NOTREACHED*/
602 if (len == 0)
603 len = REDC_ALG2;
604 conf->redc2 = len;
605 break;
607 case CONFIG_TILDE:
608 if (vp->v_type == V_NUM) {
609 q = vp->v_num;
610 conf->tilde_ok = !qiszero(q);
611 } else if (vp->v_type == V_STR) {
612 temp = lookup_long(truth, vp->v_str->s_str);
613 if (temp < 0) {
614 math_error("Illegal truth value for tilde");
615 /*NOTREACHED*/
617 conf->tilde_ok = (int)temp;
619 break;
621 case CONFIG_TAB:
622 if (vp->v_type == V_NUM) {
623 q = vp->v_num;
624 conf->tab_ok = !qiszero(q);
625 } else if (vp->v_type == V_STR) {
626 temp = lookup_long(truth, vp->v_str->s_str);
627 if (temp < 0) {
628 math_error("Illegal truth value for tab");
629 /*NOTREACHED*/
631 conf->tab_ok = (int)temp;
633 break;
635 case CONFIG_QUOMOD:
636 if (getlen(vp, &len)) {
637 math_error("Illegal value for quomod");
638 /*NOTREACHED*/
640 conf->quomod = len;
641 break;
643 case CONFIG_QUO:
644 if (getlen(vp, &len)) {
645 math_error("Illegal value for quo");
646 /*NOTREACHED*/
648 conf->quo = len;
649 break;
651 case CONFIG_MOD:
652 if (getlen(vp, &len)) {
653 math_error("Illegal value for mod");
654 /*NOTREACHED*/
656 conf->mod = len;
657 break;
659 case CONFIG_SQRT:
660 if (getlen(vp, &len)) {
661 math_error("Illegal value for sqrt");
662 /*NOTREACHED*/
664 conf->sqrt = len;
665 break;
667 case CONFIG_APPR:
668 if (getlen(vp, &len)) {
669 math_error("Illegal value for appr");
670 /*NOTREACHED*/
672 conf->appr = len;
673 break;
675 case CONFIG_CFAPPR:
676 if (getlen(vp, &len)) {
677 math_error("Illegal value for cfappr");
678 /*NOTREACHED*/
680 conf->cfappr = len;
681 break;
683 case CONFIG_CFSIM:
684 if (getlen(vp, &len)) {
685 math_error("Illegal value for cfsim");
686 /*NOTREACHED*/
688 conf->cfsim = len;
689 break;
691 case CONFIG_OUTROUND:
692 if (getlen(vp, &len)) {
693 math_error("Illegal value for outround");
694 /*NOTREACHED*/
696 conf->outround = len;
697 break;
699 case CONFIG_ROUND:
700 if (getlen(vp, &len)) {
701 math_error("Illegal value for round");
702 /*NOTREACHED*/
704 conf->round = len;
705 break;
707 case CONFIG_LEADZERO:
708 if (vp->v_type == V_NUM) {
709 q = vp->v_num;
710 conf->leadzero = !qiszero(q);
711 } else if (vp->v_type == V_STR) {
712 temp = lookup_long(truth, vp->v_str->s_str);
713 if (temp < 0) { {
714 math_error("Illegal truth value for leadzero");
715 /*NOTREACHED*/
718 conf->leadzero = (int)temp;
720 break;
722 case CONFIG_FULLZERO:
723 if (vp->v_type == V_NUM) {
724 q = vp->v_num;
725 conf->fullzero = !qiszero(q);
726 } else if (vp->v_type == V_STR) {
727 temp = lookup_long(truth, vp->v_str->s_str);
728 if (temp < 0) { {
729 math_error("Illegal truth value for fullzero");
730 /*NOTREACHED*/
733 conf->fullzero = (int)temp;
735 break;
737 case CONFIG_MAXSCAN:
738 if (vp->v_type != V_NUM) {
739 math_error("Non-numeric for maxscancount");
740 /*NOTREACHED*/
742 q = vp->v_num;
743 temp = qtoi(q);
744 if (qisfrac(q) || qisneg(q) || !zistiny(q->num))
745 temp = -1;
746 if (temp < 0) {
747 math_error("Maxscan value is out of range");
748 /*NOTREACHED*/
750 conf->maxscancount = temp;
751 break;
753 case CONFIG_PROMPT:
754 if (vp->v_type != V_STR) {
755 math_error("Non-string for prompt");
756 /*NOTREACHED*/
758 p = (char *)malloc(vp->v_str->s_len + 1);
759 if (p == NULL) {
760 math_error("Cannot duplicate new prompt");
761 /*NOTREACHED*/
763 strncpy(p, vp->v_str->s_str, vp->v_str->s_len + 1);
764 free(conf->prompt1);
765 conf->prompt1 = p;
766 break;
768 case CONFIG_MORE:
769 if (vp->v_type != V_STR) {
770 math_error("Non-string for more prompt");
771 /*NOTREACHED*/
773 p = (char *)malloc(vp->v_str->s_len + 1);
774 if (p == NULL) {
775 math_error("Cannot duplicate new more prompt");
776 /*NOTREACHED*/
778 strncpy(p, vp->v_str->s_str, vp->v_str->s_len + 1);
779 free(conf->prompt2);
780 conf->prompt2 = p;
781 break;
783 case CONFIG_BLKMAXPRINT:
784 if (vp->v_type != V_NUM) {
785 math_error("Non-numeric for blkmaxprint");
786 /*NOTREACHED*/
788 q = vp->v_num;
789 temp = qtoi(q);
790 if (qisfrac(q) || qisneg(q) || !zistiny(q->num))
791 temp = -1;
792 if (temp < 0) {
793 math_error("Blkmaxprint value is out of range");
794 /*NOTREACHED*/
796 conf->blkmaxprint = temp;
797 break;
799 case CONFIG_BLKVERBOSE:
800 if (vp->v_type == V_NUM) {
801 q = vp->v_num;
802 conf->blkverbose = !qiszero(q);
803 } else if (vp->v_type == V_STR) {
804 temp = lookup_long(truth, vp->v_str->s_str);
805 if (temp < 0) {
806 math_error("Illegal truth value for blkverbose");
807 /*NOTREACHED*/
809 conf->blkverbose = (int)temp;
811 break;
813 case CONFIG_BLKBASE:
814 if (vp->v_type != V_STR) {
815 math_error("Non-string for blkbase");
816 /*NOTREACHED*/
818 temp = lookup_long(blk_base, vp->v_str->s_str);
819 if (temp < 0) {
820 math_error("Unknown mode \"%s\" for blkbase",
821 vp->v_str->s_str);
822 /*NOTREACHED*/
824 conf->blkbase = temp;
825 break;
827 case CONFIG_BLKFMT:
828 if (vp->v_type != V_STR) {
829 math_error("Non-string for blkfmt");
830 /*NOTREACHED*/
832 temp = lookup_long(blk_fmt, vp->v_str->s_str);
833 if (temp < 0) {
834 math_error("Unknown mode \"%s\" for blkfmt",
835 vp->v_str->s_str);
836 /*NOTREACHED*/
838 conf->blkfmt = temp;
839 break;
841 case CONFIG_CALC_DEBUG:
842 if (vp->v_type != V_NUM) {
843 math_error("Non numeric for calc_debug");
844 /*NOTREACHED*/
846 q = vp->v_num;
847 temp = qtoi(q);
848 if (qisfrac(q) || !zistiny(q->num)) {
849 math_error("Illegal calc_debug parameter value");
850 /*NOTREACHED*/
852 conf->calc_debug = temp;
853 break;
855 case CONFIG_RESOURCE_DEBUG:
856 if (vp->v_type != V_NUM) {
857 math_error("Non numeric for resource_debug");
858 /*NOTREACHED*/
860 q = vp->v_num;
861 temp = qtoi(q);
862 if (qisfrac(q) || !zistiny(q->num)) {
863 math_error("Illegal resource_debug parameter value");
864 /*NOTREACHED*/
866 conf->resource_debug = temp;
867 break;
869 case CONFIG_USER_DEBUG:
870 if (vp->v_type != V_NUM) {
871 math_error("Non numeric for user_debug");
872 /*NOTREACHED*/
874 q = vp->v_num;
875 temp = qtoi(q);
876 if (qisfrac(q) || !zistiny(q->num)) {
877 math_error("Illegal user_debug parameter value");
878 /*NOTREACHED*/
880 conf->user_debug = temp;
881 break;
883 case CONFIG_VERBOSE_QUIT:
884 if (vp->v_type == V_NUM) {
885 q = vp->v_num;
886 conf->verbose_quit = !qiszero(q);
887 } else if (vp->v_type == V_STR) {
888 temp = lookup_long(truth, vp->v_str->s_str);
889 if (temp < 0) {
890 math_error("Illegal truth value "
891 "for verbose_quit");
892 /*NOTREACHED*/
894 conf->verbose_quit = (int)temp;
896 break;
898 case CONFIG_CTRL_D:
899 if (vp->v_type != V_STR) {
900 math_error("Non-string for ctrl_d");
901 /*NOTREACHED*/
903 temp = lookup_long(ctrl_d, vp->v_str->s_str);
904 if (temp < 0) {
905 math_error("Unknown mode \"%s\" for ctrl_d",
906 vp->v_str->s_str);
907 /*NOTREACHED*/
909 conf->ctrl_d = temp;
910 break;
912 case CONFIG_PROGRAM:
913 math_error("The program config parameter is read-only");
914 /*NOTREACHED*/
916 case CONFIG_BASENAME:
917 math_error("The basename config parameter is read-only");
918 /*NOTREACHED*/
920 case CONFIG_WINDOWS:
921 math_error("The windows config parameter is read-only");
922 /*NOTREACHED*/
924 case CONFIG_CYGWIN:
925 math_error("The cygwin config parameter is read-only");
926 /*NOTREACHED*/
928 case CONFIG_COMPILE_CUSTOM:
929 math_error("The custom config parameter is read-only");
930 /*NOTREACHED*/
932 case CONFIG_ALLOW_CUSTOM:
933 math_error("The allow_custom config parameter is read-only");
934 /*NOTREACHED*/
936 case CONFIG_VERSION:
937 math_error("The version config parameter is read-only");
938 /*NOTREACHED*/
940 case CONFIG_BASEB:
941 math_error("The baseb config parameter is read-only");
942 /*NOTREACHED*/
944 case CONFIG_REDECL_WARN:
945 if (vp->v_type == V_NUM) {
946 q = vp->v_num;
947 conf->redecl_warn = !qiszero(q);
948 } else if (vp->v_type == V_STR) {
949 temp = lookup_long(truth, vp->v_str->s_str);
950 if (temp < 0) {
951 math_error("Illegal truth value for "
952 "redecl_warn");
953 /*NOTREACHED*/
955 conf->redecl_warn = (int)temp;
957 break;
959 case CONFIG_DUPVAR_WARN:
960 if (vp->v_type == V_NUM) {
961 q = vp->v_num;
962 conf->dupvar_warn = !qiszero(q);
963 } else if (vp->v_type == V_STR) {
964 temp = lookup_long(truth, vp->v_str->s_str);
965 if (temp < 0) {
966 math_error("Illegal truth value for "
967 "dupvar_warn");
968 /*NOTREACHED*/
970 conf->dupvar_warn = (int)temp;
972 break;
974 case CONFIG_HZ:
975 math_error("The clock tick rate config parameter is read-only");
976 /*NOTREACHED*/
978 default:
979 math_error("Setting illegal config parameter");
980 /*NOTREACHED*/
986 * config_copy - copy the configuration from one value to another
988 * given:
989 * src copy this configuration
991 * returns:
992 * pointer to the configuration copy
994 CONFIG *
995 config_copy(CONFIG *src)
997 CONFIG *dest; /* the new CONFIG to return */
1000 * firewall
1002 if (src == NULL || src->epsilon == NULL || src->prompt1 == NULL ||
1003 src->prompt2 == NULL) {
1004 math_error("bad CONFIG value");
1005 /*NOTREACHED*/
1009 * malloc the storage
1011 dest = (CONFIG *)malloc(sizeof(CONFIG));
1012 if (dest == NULL) {
1013 math_error("malloc of CONFIG failed");
1014 /*NOTREACHED*/
1018 * copy over the values
1020 memcpy((void *)dest, (void *)src, sizeof(CONFIG));
1023 * clone the pointer values
1025 dest->epsilon = qlink(src->epsilon);
1026 dest->prompt1 = strdup(src->prompt1);
1027 dest->prompt2 = strdup(src->prompt2);
1028 if (src->program == NULL) {
1029 dest->program = strdup(program);
1030 } else {
1031 dest->program = strdup(src->program);
1033 if (src->base_name == NULL) {
1034 dest->base_name = strdup(base_name);
1035 } else {
1036 dest->base_name = strdup(src->base_name);
1038 /* NOTE: allow_custom points to a global variable, so do not clone it */
1039 if (src->version == NULL) {
1040 dest->version = strdup(version());
1041 } else {
1042 dest->version = strdup(src->version);
1046 * return the new value
1048 return dest;
1053 * config_free - free a CONFIG value
1055 * given:
1056 * cfg the CONFIG value to free
1058 void
1059 config_free(CONFIG *cfg)
1062 * firewall
1064 if (cfg == NULL) {
1065 return;
1069 * free pointer values
1071 if (cfg->epsilon != NULL) {
1072 qfree(cfg->epsilon);
1074 if (cfg->prompt1 != NULL) {
1075 free(cfg->prompt1);
1077 if (cfg->prompt2 != NULL) {
1078 free(cfg->prompt2);
1080 if (cfg->program != NULL) {
1081 free(cfg->program);
1083 if (cfg->base_name != NULL) {
1084 free(cfg->base_name);
1086 /* NOTE: allow_custom points to a global variable, so do not free it */
1087 if (cfg->version != NULL) {
1088 free(cfg->version);
1092 * free the CONFIG value itself
1094 free(cfg);
1095 return;
1100 * config_value - return a CONFIG element as a value
1102 * given:
1103 * cfg CONFIG from which an element will be returned
1104 * type the type of CONFIG element to print
1105 * ret where to return the value
1107 * returns:
1108 * ret points to the VALUE returned
1110 void
1111 config_value(CONFIG *cfg, int type, VALUE *vp)
1113 long i=0;
1114 char *p;
1117 * firewall
1119 if (cfg == NULL || cfg->epsilon == NULL || cfg->prompt1 == NULL ||
1120 cfg->prompt2 == NULL) {
1121 math_error("bad CONFIG value");
1122 /*NOTREACHED*/
1126 * convert element to value
1128 vp->v_type = V_NUM;
1129 vp->v_subtype = V_NOSUBTYPE;
1130 switch (type) {
1131 case CONFIG_ALL:
1132 vp->v_type = V_CONFIG;
1133 vp->v_config = config_copy(conf);
1134 return;
1136 case CONFIG_TRACE:
1137 i = cfg->traceflags;
1138 break;
1140 case CONFIG_DISPLAY:
1141 i = cfg->outdigits;
1142 break;
1144 case CONFIG_MODE:
1145 vp->v_type = V_STR;
1146 p = lookup_name(modes, cfg->outmode);
1147 if (p == NULL) {
1148 math_error("invalid output mode: %d", cfg->outmode);
1149 /*NOTREACHED*/
1151 vp->v_str = makenewstring(p);
1152 return;
1154 case CONFIG_MODE2:
1155 vp->v_type = V_STR;
1156 p = lookup_name(modes, cfg->outmode2);
1157 if (p == NULL) {
1158 math_error("invalid secondary output mode: %d",
1159 cfg->outmode2);
1160 /*NOTREACHED*/
1162 vp->v_str = makenewstring(p);
1163 return;
1165 case CONFIG_EPSILON:
1166 vp->v_num = qlink(cfg->epsilon);
1167 return;
1169 case CONFIG_MAXPRINT:
1170 i = cfg->maxprint;
1171 break;
1173 case CONFIG_MUL2:
1174 i = cfg->mul2;
1175 break;
1177 case CONFIG_SQ2:
1178 i = cfg->sq2;
1179 break;
1181 case CONFIG_POW2:
1182 i = cfg->pow2;
1183 break;
1185 case CONFIG_REDC2:
1186 i = cfg->redc2;
1187 break;
1189 case CONFIG_TILDE:
1190 i = (cfg->tilde_ok ? 1 : 0);
1191 break;
1193 case CONFIG_TAB:
1194 i = (cfg->tab_ok ? 1 : 0);
1195 break;
1197 case CONFIG_QUOMOD:
1198 i = cfg->quomod;
1199 break;
1201 case CONFIG_QUO:
1202 i = cfg->quo;
1203 break;
1205 case CONFIG_MOD:
1206 i = cfg->mod;
1207 break;
1209 case CONFIG_SQRT:
1210 i = cfg->sqrt;
1211 break;
1213 case CONFIG_APPR:
1214 i = cfg->appr;
1215 break;
1217 case CONFIG_CFAPPR:
1218 i = cfg->cfappr;
1219 break;
1221 case CONFIG_CFSIM:
1222 i = cfg->cfsim;
1223 break;
1225 case CONFIG_OUTROUND:
1226 i = cfg->outround;
1227 break;
1229 case CONFIG_ROUND:
1230 i = cfg->round;
1231 break;
1233 case CONFIG_LEADZERO:
1234 i = (cfg->leadzero ? 1 : 0);
1235 break;
1237 case CONFIG_FULLZERO:
1238 i = (cfg->fullzero ? 1 : 0);
1239 break;
1241 case CONFIG_MAXSCAN:
1242 i = cfg->maxscancount;
1243 break;
1245 case CONFIG_PROMPT:
1246 vp->v_type = V_STR;
1247 vp->v_str = makenewstring(cfg->prompt1);
1248 return;
1250 case CONFIG_MORE:
1251 vp->v_type = V_STR;
1252 vp->v_str = makenewstring(cfg->prompt2);
1253 return;
1255 case CONFIG_BLKMAXPRINT:
1256 i = cfg->blkmaxprint;
1257 break;
1259 case CONFIG_BLKVERBOSE:
1260 i = (cfg->blkverbose ? 1 : 0);
1261 break;
1263 case CONFIG_BLKBASE:
1264 vp->v_type = V_STR;
1265 p = lookup_name(blk_base, cfg->blkbase);
1266 if (p == NULL) {
1267 math_error("invalid block base: %d", cfg->blkbase);
1268 /*NOTREACHED*/
1270 vp->v_str = makenewstring(p);
1271 return;
1273 case CONFIG_BLKFMT:
1274 vp->v_type = V_STR;
1275 p = lookup_name(blk_fmt, cfg->blkfmt);
1276 if (p == NULL) {
1277 math_error("invalid block format: %d", cfg->blkfmt);
1278 /*NOTREACHED*/
1280 vp->v_str = makenewstring(p);
1281 return;
1283 case CONFIG_CALC_DEBUG:
1284 i = cfg->calc_debug;
1285 break;
1287 case CONFIG_RESOURCE_DEBUG:
1288 i = cfg->resource_debug;
1289 break;
1291 case CONFIG_USER_DEBUG:
1292 i = cfg->user_debug;
1293 break;
1295 case CONFIG_VERBOSE_QUIT:
1296 i = (cfg->verbose_quit ? 1 : 0);
1297 break;
1299 case CONFIG_CTRL_D:
1300 vp->v_type = V_STR;
1301 p = lookup_name(ctrl_d, cfg->ctrl_d);
1302 if (p == NULL) {
1303 math_error("invalid Control-D: %d", cfg->ctrl_d);
1304 /*NOTREACHED*/
1306 vp->v_str = makenewstring(p);
1307 return;
1309 case CONFIG_PROGRAM:
1310 vp->v_type = V_STR;
1311 if (cfg->base_name == NULL) {
1312 vp->v_str = makestring(strdup(program));
1313 } else {
1314 vp->v_str = makenewstring(cfg->program);
1316 return;
1318 case CONFIG_BASENAME:
1319 vp->v_type = V_STR;
1320 if (cfg->base_name == NULL) {
1321 vp->v_str = makestring(strdup(base_name));
1322 } else {
1323 vp->v_str = makenewstring(cfg->base_name);
1325 return;
1327 case CONFIG_WINDOWS:
1328 i = (cfg->windows ? 1 : 0);
1329 break;
1331 case CONFIG_CYGWIN:
1332 i = (cfg->cygwin ? 1 : 0);
1333 break;
1335 case CONFIG_COMPILE_CUSTOM:
1336 i = (cfg->compile_custom ? 1 : 0);
1337 break;
1339 case CONFIG_ALLOW_CUSTOM:
1340 /* firewall */
1341 if (cfg->allow_custom == NULL) {
1342 cfg->allow_custom = &allow_custom;
1344 i = (*(cfg->allow_custom) ? 1 : 0);
1345 break;
1347 case CONFIG_VERSION:
1348 vp->v_type = V_STR;
1349 if (cfg->version == NULL) {
1350 vp->v_str = makestring(strdup(version()));
1351 } else {
1352 vp->v_str = makenewstring(cfg->version);
1354 return;
1356 case CONFIG_BASEB:
1357 i = BASEB;
1358 break;
1360 case CONFIG_REDECL_WARN:
1361 i = (cfg->redecl_warn ? 1 : 0);
1362 break;
1364 case CONFIG_DUPVAR_WARN:
1365 i = (cfg->dupvar_warn ? 1 : 0);
1366 break;
1368 case CONFIG_HZ:
1369 i = CALC_HZ;
1370 break;
1372 default:
1373 math_error("Getting illegal CONFIG element");
1374 /*NOTREACHED*/
1378 * if we got this far, we have a V_NUM in i
1380 vp->v_num = itoq(i);
1381 return;
1386 * config_cmp - compare two CONFIG states
1388 * given:
1389 * cfg1 - 1st CONFIG to compare
1390 * cfg2 - 2nd CONFIG to compare
1392 * return:
1393 * TRUE if configurations differ
1395 BOOL
1396 config_cmp(CONFIG *cfg1, CONFIG *cfg2)
1399 * firewall
1401 if (cfg1 == NULL || cfg1->epsilon == NULL || cfg1->prompt1 == NULL ||
1402 cfg1->prompt2 == NULL) {
1403 math_error("CONFIG #1 value is invalid");
1404 /*NOTREACHED*/
1406 if (cfg2 == NULL || cfg2->epsilon == NULL || cfg2->prompt1 == NULL ||
1407 cfg2->prompt2 == NULL) {
1408 math_error("CONFIG #2 value is invalid");
1409 /*NOTREACHED*/
1413 * compare
1415 return cfg1->traceflags != cfg2->traceflags ||
1416 cfg1->outdigits != cfg2->outdigits ||
1417 cfg1->outmode != cfg2->outmode ||
1418 cfg1->outmode2 != cfg2->outmode2 ||
1419 qcmp(cfg1->epsilon, cfg2->epsilon) ||
1420 cfg1->epsilonprec != cfg2->epsilonprec ||
1421 cfg1->maxprint != cfg2->maxprint ||
1422 cfg1->mul2 != cfg2->mul2 ||
1423 cfg1->sq2 != cfg2->sq2 ||
1424 cfg1->pow2 != cfg2->pow2 ||
1425 cfg1->redc2 != cfg2->redc2 ||
1426 cfg1->tilde_ok != cfg2->tilde_ok ||
1427 cfg1->tab_ok != cfg2->tab_ok ||
1428 cfg1->quomod != cfg2->quomod ||
1429 cfg1->quo != cfg2->quo ||
1430 cfg1->mod != cfg2->mod ||
1431 cfg1->sqrt != cfg2->sqrt ||
1432 cfg1->appr != cfg2->appr ||
1433 cfg1->cfappr != cfg2->cfappr ||
1434 cfg1->cfsim != cfg2->cfsim ||
1435 cfg1->outround != cfg2->outround ||
1436 cfg1->round != cfg2->round ||
1437 cfg1->leadzero != cfg2->leadzero ||
1438 cfg1->fullzero != cfg2->fullzero ||
1439 cfg1->maxscancount != cfg2->maxscancount ||
1440 strcmp(cfg1->prompt1, cfg2->prompt1) != 0 ||
1441 strcmp(cfg1->prompt2, cfg2->prompt2) != 0 ||
1442 cfg1->blkmaxprint != cfg2->blkmaxprint ||
1443 cfg1->blkverbose != cfg2->blkverbose ||
1444 cfg1->blkbase != cfg2->blkbase ||
1445 cfg1->blkfmt != cfg2->blkfmt ||
1446 cfg1->calc_debug != cfg2->calc_debug ||
1447 cfg1->resource_debug != cfg2->resource_debug ||
1448 cfg1->user_debug != cfg2->user_debug ||
1449 cfg1->verbose_quit != cfg2->verbose_quit ||
1450 cfg1->ctrl_d != cfg2->ctrl_d ||
1452 (cfg1->program == NULL && cfg2->program != NULL) ||
1453 (cfg1->program != NULL && cfg2->program == NULL) ||
1454 (cfg1->program != NULL && cfg2->program != NULL &&
1455 strcmp(cfg1->program, cfg2->program) != 0) ||
1457 (cfg1->base_name == NULL && cfg2->base_name != NULL) ||
1458 (cfg1->base_name != NULL && cfg2->base_name == NULL) ||
1459 (cfg1->base_name != NULL && cfg2->base_name != NULL &&
1460 strcmp(cfg1->base_name, cfg2->base_name) != 0) ||
1462 cfg1->windows != cfg2->windows ||
1464 cfg1->cygwin != cfg2->cygwin ||
1466 cfg1->compile_custom != cfg2->compile_custom ||
1468 (cfg1->allow_custom == NULL && cfg2->allow_custom != NULL) ||
1469 (cfg1->allow_custom != NULL && cfg2->allow_custom == NULL) ||
1470 (cfg1->allow_custom != NULL && cfg2->allow_custom != NULL &&
1471 *(cfg1->allow_custom) != *(cfg2->allow_custom)) ||
1473 (cfg1->version == NULL && cfg2->version != NULL) ||
1474 (cfg1->version != NULL && cfg2->version == NULL) ||
1475 (cfg1->version != NULL && cfg2->version != NULL &&
1476 strcmp(cfg1->version, cfg2->version) != 0) ||
1478 cfg1->baseb != cfg2->baseb;