/* * Copyright (c) 1993 David I. Bell * Permission is granted to use, distribute, or modify this source, * provided that this copyright notice remains intact. * * Configuration routines. */ #include "calc.h" /* * Configuration parameter name and type. */ typedef struct { char *name; /* name of configuration string */ int type; /* type for configuration */ } CONFIG; /* * Table of configuration types that can be set or read. */ static CONFIG configs[] = { "trace", CONFIG_TRACE, "display", CONFIG_DISPLAY, "epsilon", CONFIG_EPSILON, "mode", CONFIG_MODE, "maxprint", CONFIG_MAXPRINT, "mul2", CONFIG_MUL2, "sq2", CONFIG_SQ2, "pow2", CONFIG_POW2, "redc2", CONFIG_REDC2, NULL, 0 }; /* * Possible output modes. */ static CONFIG modes[] = { "frac", MODE_FRAC, "decimal", MODE_FRAC, "dec", MODE_FRAC, "int", MODE_INT, "real", MODE_REAL, "exp", MODE_EXP, "hexadecimal", MODE_HEX, "hex", MODE_HEX, "octal", MODE_OCTAL, "oct", MODE_OCTAL, "binary", MODE_BINARY, "bin", MODE_BINARY, NULL, 0 }; /* * Given a string value which represents a configuration name, return * the configuration type for that string. Returns negative type if * the string is unknown. */ configtype(name) char *name; /* configuration name */ { CONFIG *cp; /* current config pointer */ for (cp = configs; cp->name; cp++) { if (strcmp(cp->name, name) == 0) return cp->type; } return -1; } /* * Given the name of a mode, convert it to the internal format. * Returns -1 if the string is unknown. */ static modetype(name) char *name; /* mode name */ { CONFIG *cp; /* current config pointer */ for (cp = modes; cp->name; cp++) { if (strcmp(cp->name, name) == 0) return cp->type; } return -1; } /* * Given the mode type, convert it to a string representing that mode. * Where there are multiple strings representing the same mode, the first * one in the table is used. Returns NULL if the node type is unknown. * The returned string cannot be modified. */ static char * modename(type) { CONFIG *cp; /* current config pointer */ for (cp = modes; cp->name; cp++) { if (type == cp->type) return cp->name; } return NULL; } /* * Set the specified configuration type to the specified value. * An error is generated if the type number or value is illegal. */ void setconfig(type, vp) VALUE *vp; { NUMBER *q; long temp; switch (type) { case CONFIG_TRACE: if (vp->v_type != V_NUM) error("Non-numeric for trace"); q = vp->v_num; temp = qtoi(q); if (qisfrac(q) || !istiny(q->num) || ((unsigned long) temp > TRACE_MAX)) error("Bad trace value"); traceflags = (FLAG)temp; break; case CONFIG_DISPLAY: if (vp->v_type != V_NUM) error("Non-numeric for display"); q = vp->v_num; temp = qtoi(q); if (qisfrac(q) || qisneg(q) || !istiny(q->num)) temp = -1; setdigits(temp); break; case CONFIG_MODE: if (vp->v_type != V_STR) error("Non-string for mode"); temp = modetype(vp->v_str); if (temp < 0) error("Unknown mode \"%s\"", vp->v_str); set_mode((int) temp); break; case CONFIG_EPSILON: if (vp->v_type != V_NUM) error("Non-numeric for epsilon"); setepsilon(vp->v_num); break; case CONFIG_MAXPRINT: if (vp->v_type != V_NUM) error("Non-numeric for maxprint"); q = vp->v_num; temp = qtoi(q); if (qisfrac(q) || qisneg(q) || !istiny(q->num)) temp = -1; if (temp < 0) error("Maxprint value is out of range"); maxprint = temp; break; case CONFIG_MUL2: if (vp->v_type != V_NUM) error("Non-numeric for mul2"); q = vp->v_num; temp = qtoi(q); if (qisfrac(q) || qisneg(q)) temp = -1; if (temp == 0) temp = MUL_ALG2; if (temp < 2) error("Illegal mul2 value"); _mul2_ = temp; break; case CONFIG_SQ2: if (vp->v_type != V_NUM) error("Non-numeric for sq2"); q = vp->v_num; temp = qtoi(q); if (qisfrac(q) || qisneg(q)) temp = -1; if (temp == 0) temp = SQ_ALG2; if (temp < 2) error("Illegal sq2 value"); _sq2_ = temp; break; case CONFIG_POW2: if (vp->v_type != V_NUM) error("Non-numeric for pow2"); q = vp->v_num; temp = qtoi(q); if (qisfrac(q) || qisneg(q)) temp = -1; if (temp == 0) temp = POW_ALG2; if (temp < 1) error("Illegal pow2 value"); _pow2_ = temp; break; case CONFIG_REDC2: if (vp->v_type != V_NUM) error("Non-numeric for redc2"); q = vp->v_num; temp = qtoi(q); if (qisfrac(q) || qisneg(q)) temp = -1; if (temp == 0) temp = REDC_ALG2; if (temp < 1) error("Illegal redc2 value"); _redc2_ = temp; break; default: error("Setting illegal config parameter"); } } /* * Get the current value of the specified configuration type. * An error is generated if the type number is illegal. */ void getconfig(type, vp) VALUE *vp; { switch (type) { case CONFIG_TRACE: vp->v_type = V_NUM; vp->v_num = itoq((long) traceflags); break; case CONFIG_DISPLAY: vp->v_type = V_NUM; vp->v_num = itoq(_outdigits_); break; case CONFIG_MODE: vp->v_type = V_STR; vp->v_subtype = V_STRLITERAL; vp->v_str = modename(_outmode_); break; case CONFIG_EPSILON: vp->v_type = V_NUM; vp->v_num = qlink(_epsilon_); break; case CONFIG_MAXPRINT: vp->v_type = V_NUM; vp->v_num = itoq(maxprint); break; case CONFIG_MUL2: vp->v_type = V_NUM; vp->v_num = itoq(_mul2_); break; case CONFIG_SQ2: vp->v_type = V_NUM; vp->v_num = itoq(_sq2_); break; case CONFIG_POW2: vp->v_type = V_NUM; vp->v_num = itoq(_pow2_); break; case CONFIG_REDC2: vp->v_type = V_NUM; vp->v_num = itoq(_redc2_); break; default: error("Getting illegal config parameter"); } } /* END CODE */