4.4BSD/usr/src/contrib/calc-1.26.4/config.c

/*
 * 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 */