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/
35 #include "have_times.h"
36 #if defined(HAVE_TIME_H)
40 #if defined(HAVE_TIMES_H)
44 #if defined(HAVE_SYS_TIME_H)
48 #if defined(HAVE_SYS_TIMES_H)
49 #include <sys/times.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
70 # define CALC_HZ ((long)(CLK_TCK))
72 # define CALC_HZ (0L) /* no defined clock tick rate */
77 * Table of configuration types that can be set or read.
79 NAMETYPE configs
[] = {
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
},
90 {"pow2", CONFIG_POW2
},
91 {"redc2", CONFIG_REDC2
},
92 {"tilde", CONFIG_TILDE
},
94 {"quomod", CONFIG_QUOMOD
},
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
},
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 */
176 NULL
, /* basename of our name */
178 TRUE
, /* running under windows */
180 FALSE
, /* congrats, you are not using windows */
182 #if defined(__CYGWIN__)
183 TRUE
, /* compiled under cygwin */
185 FALSE
, /* not compiled with cygwin */
188 TRUE
, /* compiled with -DCUSTOM */
190 FALSE
, /* compiled without -DCUSTOM */
192 &allow_custom
, /* *TRUE=> custom functions are enabled */
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 */
236 NULL
, /* basename of our name */
238 TRUE
, /* running under windows */
240 FALSE
, /* congrats, you are not using windows */
242 #if defined(__CYGWIN__)
243 TRUE
, /* compiled under cygwin */
245 FALSE
, /* not compiled with cygwin */
248 TRUE
, /* compiled with -DCUSTOM */
250 FALSE
, /* compiled without -DCUSTOM */
252 &allow_custom
, /* *TRUE=> custom functions are enabled */
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
},
267 {"integer", MODE_INT
},
270 {"float", MODE_REAL
},
271 {"default", MODE_INITIAL
}, /* MODE_REAL */
272 {"scientific", MODE_EXP
},
275 {"hexadecimal", MODE_HEX
},
277 {"octal", MODE_OCTAL
},
279 {"binary", MODE_BINARY
},
280 {"bin", MODE_BINARY
},
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
},
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
},
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
},
344 * Possible binary config state values
346 #define TRUE_STRING "true"
347 #define FALSE_STRING "false"
348 STATIC NAMETYPE truth
[] = {
356 {FALSE_STRING
, FALSE
},
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.
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)
397 * lookup_long - given a name and a NAMETYPE, return the int
400 * set the NAMESET array of name/int pairs
404 * numeric value of the name or -1 if not found
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)
420 * lookup_name - given numeric value and a NAMETYPE, return the name
423 * set the NAMESET array of name/int pairs
424 * val numeric value to lookup
427 * name of the value found of NULL
430 lookup_name(NAMETYPE
*set
, long val
)
432 NAMETYPE
*cp
; /* current config pointer */
434 for (cp
= set
; cp
->name
; cp
++) {
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
450 getlen(VALUE
*vp
, LEN
*lp
)
452 if (vp
->v_type
!= V_NUM
|| !qisint(vp
->v_num
))
454 if (zge31b(vp
->v_num
->num
))
456 *lp
= ztoi(vp
->v_num
->num
);
464 * Set the specified configuration type to the specified value.
465 * An error is generated if the type number or value is illegal.
468 setconfig(int type
, VALUE
*vp
)
471 CONFIG
*newconf
; /* new configuration to set */
478 newconf
= NULL
; /* firewall */
479 if (vp
->v_type
== V_STR
) {
480 if (strcmp(vp
->v_str
->s_str
, "oldstd") == 0) {
482 } else if (strcmp(vp
->v_str
->s_str
, "newstd") == 0) {
485 math_error("CONFIG alias not oldstd or newstd");
488 } else if (vp
->v_type
!= V_CONFIG
) {
489 math_error("non-CONFIG for all");
492 newconf
= vp
->v_config
;
495 /* free the current configuration */
498 /* set the new configuration */
499 conf
= config_copy(newconf
);
503 if (vp
->v_type
!= V_NUM
) {
504 math_error("Non-numeric for trace");
509 if (qisfrac(q
) || !zistiny(q
->num
) ||
510 ((unsigned long) temp
> TRACE_MAX
)) {
511 math_error("Bad trace value");
514 conf
->traceflags
= (FLAG
)temp
;
518 if (getlen(vp
, &len
)) {
519 math_error("Bad value for display");
526 if (vp
->v_type
!= V_STR
) {
527 math_error("Non-string for mode");
530 temp
= lookup_long(modes
, vp
->v_str
->s_str
);
532 math_error("Unknown mode \"%s\"", vp
->v_str
->s_str
);
535 math_setmode((int) temp
);
539 if (vp
->v_type
!= V_STR
) {
540 math_error("Non-string for mode");
543 temp
= lookup_long(modes
, vp
->v_str
->s_str
);
545 math_error("Unknown mode \"%s\"", vp
->v_str
->s_str
);
548 math_setmode2((int) temp
);
552 if (vp
->v_type
!= V_NUM
) {
553 math_error("Non-numeric for epsilon");
556 setepsilon(vp
->v_num
);
559 case CONFIG_MAXPRINT
:
560 if (getlen(vp
, &len
)) {
561 math_error("Bad value for maxprint");
564 conf
->maxprint
= len
;
568 if (getlen(vp
, &len
) || len
< 0 || len
== 1) {
569 math_error("Bad value for mul2");
578 if (getlen(vp
, &len
) || len
< 0 || len
== 1) {
579 math_error("Bad value for sq2");
588 if (getlen(vp
, &len
) || len
< 0 || len
== 1) {
589 math_error("Bad value for pow2");
598 if (getlen(vp
, &len
) || len
< 0 || len
== 1) {
599 math_error("Bad value for redc2");
608 if (vp
->v_type
== 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
);
614 math_error("Illegal truth value for tilde");
617 conf
->tilde_ok
= (int)temp
;
622 if (vp
->v_type
== 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
);
628 math_error("Illegal truth value for tab");
631 conf
->tab_ok
= (int)temp
;
636 if (getlen(vp
, &len
)) {
637 math_error("Illegal value for quomod");
644 if (getlen(vp
, &len
)) {
645 math_error("Illegal value for quo");
652 if (getlen(vp
, &len
)) {
653 math_error("Illegal value for mod");
660 if (getlen(vp
, &len
)) {
661 math_error("Illegal value for sqrt");
668 if (getlen(vp
, &len
)) {
669 math_error("Illegal value for appr");
676 if (getlen(vp
, &len
)) {
677 math_error("Illegal value for cfappr");
684 if (getlen(vp
, &len
)) {
685 math_error("Illegal value for cfsim");
691 case CONFIG_OUTROUND
:
692 if (getlen(vp
, &len
)) {
693 math_error("Illegal value for outround");
696 conf
->outround
= len
;
700 if (getlen(vp
, &len
)) {
701 math_error("Illegal value for round");
707 case CONFIG_LEADZERO
:
708 if (vp
->v_type
== 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
);
714 math_error("Illegal truth value for leadzero");
718 conf
->leadzero
= (int)temp
;
722 case CONFIG_FULLZERO
:
723 if (vp
->v_type
== 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
);
729 math_error("Illegal truth value for fullzero");
733 conf
->fullzero
= (int)temp
;
738 if (vp
->v_type
!= V_NUM
) {
739 math_error("Non-numeric for maxscancount");
744 if (qisfrac(q
) || qisneg(q
) || !zistiny(q
->num
))
747 math_error("Maxscan value is out of range");
750 conf
->maxscancount
= temp
;
754 if (vp
->v_type
!= V_STR
) {
755 math_error("Non-string for prompt");
758 p
= (char *)malloc(vp
->v_str
->s_len
+ 1);
760 math_error("Cannot duplicate new prompt");
763 strncpy(p
, vp
->v_str
->s_str
, vp
->v_str
->s_len
+ 1);
769 if (vp
->v_type
!= V_STR
) {
770 math_error("Non-string for more prompt");
773 p
= (char *)malloc(vp
->v_str
->s_len
+ 1);
775 math_error("Cannot duplicate new more prompt");
778 strncpy(p
, vp
->v_str
->s_str
, vp
->v_str
->s_len
+ 1);
783 case CONFIG_BLKMAXPRINT
:
784 if (vp
->v_type
!= V_NUM
) {
785 math_error("Non-numeric for blkmaxprint");
790 if (qisfrac(q
) || qisneg(q
) || !zistiny(q
->num
))
793 math_error("Blkmaxprint value is out of range");
796 conf
->blkmaxprint
= temp
;
799 case CONFIG_BLKVERBOSE
:
800 if (vp
->v_type
== 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
);
806 math_error("Illegal truth value for blkverbose");
809 conf
->blkverbose
= (int)temp
;
814 if (vp
->v_type
!= V_STR
) {
815 math_error("Non-string for blkbase");
818 temp
= lookup_long(blk_base
, vp
->v_str
->s_str
);
820 math_error("Unknown mode \"%s\" for blkbase",
824 conf
->blkbase
= temp
;
828 if (vp
->v_type
!= V_STR
) {
829 math_error("Non-string for blkfmt");
832 temp
= lookup_long(blk_fmt
, vp
->v_str
->s_str
);
834 math_error("Unknown mode \"%s\" for blkfmt",
841 case CONFIG_CALC_DEBUG
:
842 if (vp
->v_type
!= V_NUM
) {
843 math_error("Non numeric for calc_debug");
848 if (qisfrac(q
) || !zistiny(q
->num
)) {
849 math_error("Illegal calc_debug parameter value");
852 conf
->calc_debug
= temp
;
855 case CONFIG_RESOURCE_DEBUG
:
856 if (vp
->v_type
!= V_NUM
) {
857 math_error("Non numeric for resource_debug");
862 if (qisfrac(q
) || !zistiny(q
->num
)) {
863 math_error("Illegal resource_debug parameter value");
866 conf
->resource_debug
= temp
;
869 case CONFIG_USER_DEBUG
:
870 if (vp
->v_type
!= V_NUM
) {
871 math_error("Non numeric for user_debug");
876 if (qisfrac(q
) || !zistiny(q
->num
)) {
877 math_error("Illegal user_debug parameter value");
880 conf
->user_debug
= temp
;
883 case CONFIG_VERBOSE_QUIT
:
884 if (vp
->v_type
== 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
);
890 math_error("Illegal truth value "
894 conf
->verbose_quit
= (int)temp
;
899 if (vp
->v_type
!= V_STR
) {
900 math_error("Non-string for ctrl_d");
903 temp
= lookup_long(ctrl_d
, vp
->v_str
->s_str
);
905 math_error("Unknown mode \"%s\" for ctrl_d",
913 math_error("The program config parameter is read-only");
916 case CONFIG_BASENAME
:
917 math_error("The basename config parameter is read-only");
921 math_error("The windows config parameter is read-only");
925 math_error("The cygwin config parameter is read-only");
928 case CONFIG_COMPILE_CUSTOM
:
929 math_error("The custom config parameter is read-only");
932 case CONFIG_ALLOW_CUSTOM
:
933 math_error("The allow_custom config parameter is read-only");
937 math_error("The version config parameter is read-only");
941 math_error("The baseb config parameter is read-only");
944 case CONFIG_REDECL_WARN
:
945 if (vp
->v_type
== 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
);
951 math_error("Illegal truth value for "
955 conf
->redecl_warn
= (int)temp
;
959 case CONFIG_DUPVAR_WARN
:
960 if (vp
->v_type
== 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
);
966 math_error("Illegal truth value for "
970 conf
->dupvar_warn
= (int)temp
;
975 math_error("The clock tick rate config parameter is read-only");
979 math_error("Setting illegal config parameter");
986 * config_copy - copy the configuration from one value to another
989 * src copy this configuration
992 * pointer to the configuration copy
995 config_copy(CONFIG
*src
)
997 CONFIG
*dest
; /* the new CONFIG to return */
1002 if (src
== NULL
|| src
->epsilon
== NULL
|| src
->prompt1
== NULL
||
1003 src
->prompt2
== NULL
) {
1004 math_error("bad CONFIG value");
1009 * malloc the storage
1011 dest
= (CONFIG
*)malloc(sizeof(CONFIG
));
1013 math_error("malloc of CONFIG failed");
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
);
1031 dest
->program
= strdup(src
->program
);
1033 if (src
->base_name
== NULL
) {
1034 dest
->base_name
= strdup(base_name
);
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());
1042 dest
->version
= strdup(src
->version
);
1046 * return the new value
1053 * config_free - free a CONFIG value
1056 * cfg the CONFIG value to free
1059 config_free(CONFIG
*cfg
)
1069 * free pointer values
1071 if (cfg
->epsilon
!= NULL
) {
1072 qfree(cfg
->epsilon
);
1074 if (cfg
->prompt1
!= NULL
) {
1077 if (cfg
->prompt2
!= NULL
) {
1080 if (cfg
->program
!= NULL
) {
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
) {
1092 * free the CONFIG value itself
1100 * config_value - return a CONFIG element as a value
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
1108 * ret points to the VALUE returned
1111 config_value(CONFIG
*cfg
, int type
, VALUE
*vp
)
1119 if (cfg
== NULL
|| cfg
->epsilon
== NULL
|| cfg
->prompt1
== NULL
||
1120 cfg
->prompt2
== NULL
) {
1121 math_error("bad CONFIG value");
1126 * convert element to value
1129 vp
->v_subtype
= V_NOSUBTYPE
;
1132 vp
->v_type
= V_CONFIG
;
1133 vp
->v_config
= config_copy(conf
);
1137 i
= cfg
->traceflags
;
1140 case CONFIG_DISPLAY
:
1146 p
= lookup_name(modes
, cfg
->outmode
);
1148 math_error("invalid output mode: %d", cfg
->outmode
);
1151 vp
->v_str
= makenewstring(p
);
1156 p
= lookup_name(modes
, cfg
->outmode2
);
1158 math_error("invalid secondary output mode: %d",
1162 vp
->v_str
= makenewstring(p
);
1165 case CONFIG_EPSILON
:
1166 vp
->v_num
= qlink(cfg
->epsilon
);
1169 case CONFIG_MAXPRINT
:
1190 i
= (cfg
->tilde_ok
? 1 : 0);
1194 i
= (cfg
->tab_ok
? 1 : 0);
1225 case CONFIG_OUTROUND
:
1233 case CONFIG_LEADZERO
:
1234 i
= (cfg
->leadzero
? 1 : 0);
1237 case CONFIG_FULLZERO
:
1238 i
= (cfg
->fullzero
? 1 : 0);
1241 case CONFIG_MAXSCAN
:
1242 i
= cfg
->maxscancount
;
1247 vp
->v_str
= makenewstring(cfg
->prompt1
);
1252 vp
->v_str
= makenewstring(cfg
->prompt2
);
1255 case CONFIG_BLKMAXPRINT
:
1256 i
= cfg
->blkmaxprint
;
1259 case CONFIG_BLKVERBOSE
:
1260 i
= (cfg
->blkverbose
? 1 : 0);
1263 case CONFIG_BLKBASE
:
1265 p
= lookup_name(blk_base
, cfg
->blkbase
);
1267 math_error("invalid block base: %d", cfg
->blkbase
);
1270 vp
->v_str
= makenewstring(p
);
1275 p
= lookup_name(blk_fmt
, cfg
->blkfmt
);
1277 math_error("invalid block format: %d", cfg
->blkfmt
);
1280 vp
->v_str
= makenewstring(p
);
1283 case CONFIG_CALC_DEBUG
:
1284 i
= cfg
->calc_debug
;
1287 case CONFIG_RESOURCE_DEBUG
:
1288 i
= cfg
->resource_debug
;
1291 case CONFIG_USER_DEBUG
:
1292 i
= cfg
->user_debug
;
1295 case CONFIG_VERBOSE_QUIT
:
1296 i
= (cfg
->verbose_quit
? 1 : 0);
1301 p
= lookup_name(ctrl_d
, cfg
->ctrl_d
);
1303 math_error("invalid Control-D: %d", cfg
->ctrl_d
);
1306 vp
->v_str
= makenewstring(p
);
1309 case CONFIG_PROGRAM
:
1311 if (cfg
->base_name
== NULL
) {
1312 vp
->v_str
= makestring(strdup(program
));
1314 vp
->v_str
= makenewstring(cfg
->program
);
1318 case CONFIG_BASENAME
:
1320 if (cfg
->base_name
== NULL
) {
1321 vp
->v_str
= makestring(strdup(base_name
));
1323 vp
->v_str
= makenewstring(cfg
->base_name
);
1327 case CONFIG_WINDOWS
:
1328 i
= (cfg
->windows
? 1 : 0);
1332 i
= (cfg
->cygwin
? 1 : 0);
1335 case CONFIG_COMPILE_CUSTOM
:
1336 i
= (cfg
->compile_custom
? 1 : 0);
1339 case CONFIG_ALLOW_CUSTOM
:
1341 if (cfg
->allow_custom
== NULL
) {
1342 cfg
->allow_custom
= &allow_custom
;
1344 i
= (*(cfg
->allow_custom
) ? 1 : 0);
1347 case CONFIG_VERSION
:
1349 if (cfg
->version
== NULL
) {
1350 vp
->v_str
= makestring(strdup(version()));
1352 vp
->v_str
= makenewstring(cfg
->version
);
1360 case CONFIG_REDECL_WARN
:
1361 i
= (cfg
->redecl_warn
? 1 : 0);
1364 case CONFIG_DUPVAR_WARN
:
1365 i
= (cfg
->dupvar_warn
? 1 : 0);
1373 math_error("Getting illegal CONFIG element");
1378 * if we got this far, we have a V_NUM in i
1380 vp
->v_num
= itoq(i
);
1386 * config_cmp - compare two CONFIG states
1389 * cfg1 - 1st CONFIG to compare
1390 * cfg2 - 2nd CONFIG to compare
1393 * TRUE if configurations differ
1396 config_cmp(CONFIG
*cfg1
, CONFIG
*cfg2
)
1401 if (cfg1
== NULL
|| cfg1
->epsilon
== NULL
|| cfg1
->prompt1
== NULL
||
1402 cfg1
->prompt2
== NULL
) {
1403 math_error("CONFIG #1 value is invalid");
1406 if (cfg2
== NULL
|| cfg2
->epsilon
== NULL
|| cfg2
->prompt1
== NULL
||
1407 cfg2
->prompt2
== NULL
) {
1408 math_error("CONFIG #2 value is invalid");
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
;