#include "e.h"
#include "y.tab.h"

tbl	*keytbl[TBLSIZE];	/* key words */
tbl	*restbl[TBLSIZE];	/* reserved words */
tbl	*deftbl[TBLSIZE];	/* user-defined names */

struct keyword {
	char	*key;
	int	keyval;
} keyword[]	={
	{ "sub",	 SUB, },
	{ "sup",	 SUP, },
	{ ".EN",	 DOTEN, },
	{ ".EQ",	 DOTEQ, },
	{ "from",	 FROM, },
	{ "to",	         TO, },
	{ "sum",	 SUM, },
	{ "hat",	 HAT, },
	{ "vec",	 VEC, },
	{ "dyad",	 DYAD, },
	{ "dot",	 DOT, },
	{ "dotdot",	 DOTDOT, },
	{ "bar",	 BAR, },
	{ "lowbar",	 LOWBAR, },
	{ "highbar",	 HIGHBAR, },
	{ "tilde",	 TILDE, },
	{ "utilde",	 UTILDE, },
	{ "under",	 UNDER, },
	{ "prod",	 PROD, },
	{ "int",	 INT, },
	{ "integral",	 INT, },
	{ "union",	 UNION, },
	{ "inter",	 INTER, },
	{ "matrix",	 MATRIX, },
	{ "col",	 COL, },
	{ "lcol",	 LCOL, },
	{ "ccol",	 CCOL, },
	{ "rcol",	 RCOL, },
	{ "pile",	 COL },  /* synonyms ... */
	{ "lpile",	 LCOL, },
	{ "cpile",	 CCOL, },
	{ "rpile",	 RCOL, },
	{ "over",	 OVER, },
	{ "sqrt",	 SQRT, },
	{ "above",	 ABOVE, },
	{ "size",	 SIZE, },
	{ "font",	 FONT, },
	{ "fat",	 FAT, },
	{ "roman",	 ROMAN, },
	{ "italic",	 ITALIC, },
	{ "bold",	 BOLD, },
	{ "left",	 LEFT, },
	{ "right",	 RIGHT, },
	{ "delim",	 DELIM, },
	{ "define",	 DEFINE, },
	{ "tdefine",	 DEFINE, },
	{ "ndefine",	 NDEFINE, },
	{ "ifdef",	 IFDEF, },
	{ "gsize",	 GSIZE, },
	{ ".gsize",	 GSIZE, },
	{ "gfont",	 GFONT, },
	{ "include",	 INCLUDE, },
	{ "copy",	 INCLUDE, },
	{ "space",	 SPACE, },
	{ "up",	         UP, },
	{ "down",	 DOWN, },
	{ "fwd",	 FWD, },
	{ "back",	 BACK, },
	{ "mark",	 MARK, },
	{ "lineup",	 LINEUP, },
	{ 0, 	0 }
};

struct resword {
	char	*res;
	char	*resval;
} resword[]	={
	{ ">=",	 "\\(>=", },
	{ "<=",	 "\\(<=", },
	{ "==",	 "\\(==", },
	{ "!=",	 "\\(!=", },
	{ "+-",	 "\\(+-", },
	{ "->",	 "\\(->", },
	{ "<-",	 "\\(<-", },
	{ "inf",	 "\\(if", },
	{ "infinity",	 "\\(if", },
	{ "partial",	 "\\(pd", },
	{ "half",	 "\\f1\\(12\\fP", },
	{ "prime",	 "\\f1\\v'.5m'\\s+3\\(fm\\s-3\\v'-.5m'\\fP", },
	{ "dollar",	 "\\f1$\\fP", },
	{ "nothing",	 "", },
	{ "times",	 "\\(mu", },
	{ "del",	 "\\(gr", },
	{ "grad",	 "\\(gr", },
	{ "approx",	 "\\v'-.2m'\\z\\(ap\\v'.25m'\\(ap\\v'-.05m'", },
	{ "cdot",	 "\\v'-.3m'.\\v'.3m'", },
	{ "...",	 "\\v'-.25m'\\ .\\ .\\ .\\ \\v'.25m'", },
	{ ",...,",	 "\\f1,\\fP\\ .\\ .\\ .\\ \\f1,\\fP\\|", },
	{ "alpha",	 "α", },
	{ "ALPHA",	 "Α", },
	{ "beta",	 "β", },
	{ "BETA",	 "Β", },
	{ "gamma",	 "γ", },
	{ "GAMMA",	 "Γ", },
	{ "delta",	 "δ", },
	{ "DELTA",	 "Δ", },
	{ "epsilon",	 "ε", },
	{ "EPSILON",	 "Ε", },
	{ "omega",	 "ω", },
	{ "OMEGA",	 "Ω", },
	{ "lambda",	 "λ", },
	{ "LAMBDA",	 "Λ", },
	{ "mu",	 "μ", },
	{ "MU",	 "Μ", },
	{ "nu",	 "ν", },
	{ "NU",	 "Ν", },
	{ "theta",	 "θ", },
	{ "THETA",	 "Θ", },
	{ "phi",	 "φ", },
	{ "PHI",	 "Φ", },
	{ "pi",	 "π", },
	{ "PI",	 "Π", },
	{ "sigma",	 "σ", },
	{ "SIGMA",	 "Σ", },
	{ "xi",	 "ξ", },
	{ "XI",	 "Ξ", },
	{ "zeta",	 "ζ", },
	{ "ZETA",	 "Ζ", },
	{ "iota",	 "ι", },
	{ "IOTA",	 "Ι", },
	{ "eta",	 "η", },
	{ "ETA",	 "Η", },
	{ "kappa",	 "κ", },
	{ "KAPPA",	 "Κ", },
	{ "rho",	 "ρ", },
	{ "RHO",	 "Ρ", },
	{ "tau",	 "τ", },
	{ "TAU",	 "Τ", },
	{ "omicron",	 "ο", },
	{ "OMICRON",	 "Ο", },
	{ "upsilon",	 "υ", },
	{ "UPSILON",	 "Υ", },
	{ "psi",	 "ψ", },
	{ "PSI",	 "Ψ", },
	{ "chi",	 "χ", },
	{ "CHI",	 "Χ", },
	{ "and",	 "\\f1and\\fP", },
	{ "for",	 "\\f1for\\fP", },
	{ "if",	 "\\f1if\\fP", },
	{ "Re",	 "\\f1Re\\fP", },
	{ "Im",	 "\\f1Im\\fP", },
	{ "sin",	 "\\f1sin\\fP", },
	{ "cos",	 "\\f1cos\\fP", },
	{ "tan",	 "\\f1tan\\fP", },
	{ "arc",	 "\\f1arc\\fP", },
	{ "sinh",	 "\\f1sinh\\fP", },
	{ "coth",	 "\\f1coth\\fP", },
	{ "tanh",	 "\\f1tanh\\fP", },
	{ "cosh",	 "\\f1cosh\\fP", },
	{ "lim",	 "\\f1lim\\fP", },
	{ "log",	 "\\f1log\\fP", },
	{ "ln",	 "\\f1ln\\fP", },
	{ "max",	 "\\f1max\\fP", },
	{ "min",	 "\\f1min\\fP", },
	{ "exp",	 "\\f1exp\\fP", },
	{ "det",	 "\\f1det\\fP", },
	{ 0,	0 }
};

int hash(char *s)
{
	register unsigned int h;

	for (h = 0; *s != '\0'; )
		h += *s++;
	h %= TBLSIZE;
	return h;
}

tbl *lookup(tbl **tblp, char *name)	/* find name in tbl */
{
	register tbl *p;

	for (p = tblp[hash(name)]; p != NULL; p = p->next)
		if (strcmp(name, p->name) == 0)
			return(p);
	return(NULL);
}

void install(tbl **tblp, char *name, char *cval, int ival)	/* install name, vals in tblp */
{
	register tbl *p;
	int h;

	if ((p = lookup(tblp, name)) == NULL) {
		p = (tbl *) malloc(sizeof(tbl));
		if (p == NULL)
			ERROR "out of space in install" FATAL;
		h = hash(name);	/* bad visibility here */
		p->name = name;
		p->next = tblp[h];
		tblp[h] = p;
	}
	p->cval = cval;
	p->ival = ival;
}

void init_tbl(void)	/* initialize tables */
{
	int i;
	extern int init_tune(void);

	for (i = 0; keyword[i].key != NULL; i++)
		install(keytbl, keyword[i].key, (char *) 0, keyword[i].keyval);
	for (i = 0; resword[i].res != NULL; i++)
		install(restbl, resword[i].res, resword[i].resval, 0);
	init_tune();	/* tuning table done in tuning.c */
}