xref: /csrg-svn/old/as.vax/asexpr.c (revision 19822)
15823Srrh /*
2*19822Sdist  * Copyright (c) 1982 Regents of the University of California.
3*19822Sdist  * All rights reserved.  The Berkeley software License Agreement
4*19822Sdist  * specifies the terms and conditions for redistribution.
55823Srrh  */
6*19822Sdist 
75823Srrh #ifndef lint
8*19822Sdist static char sccsid[] = "@(#)asexpr.c	5.1 (Berkeley) 04/30/85";
9*19822Sdist #endif not lint
105823Srrh 
115823Srrh #endif not lint
12593Sbill #include <stdio.h>
13593Sbill #include "as.h"
145823Srrh #include "asscan.h"
15593Sbill #include "asexpr.h"
16593Sbill 
17593Sbill /*
18593Sbill  * Tables for combination of operands.
19593Sbill  */
20593Sbill #define	XTXRN	5<<1		/* indexes last row/column when right shifted */
21593Sbill 
22593Sbill /*
23593Sbill  *	table for +
24593Sbill  */
25593Sbill readonly char pltab[6][6] = {
26593Sbill /*		UND	ABS	TXT	DAT	BSS	EXT */
27593Sbill 
28593Sbill /*UND*/		XUNDEF,	XUNDEF,	XUNDEF,	XUNDEF,	XUNDEF,	XUNDEF,
29593Sbill /*ABS*/		XUNDEF,	XABS,	XTEXT,	XDATA,	XBSS,	XXTRN,
30593Sbill /*TXT*/		XUNDEF,	XTEXT,	ERR,	ERR,	ERR,	ERR,
31593Sbill /*DAT*/		XUNDEF,	XDATA,	ERR,	ERR,	ERR,	ERR,
32593Sbill /*BSS*/		XUNDEF,	XBSS,	ERR,	ERR,	ERR,	ERR,
33593Sbill /*EXT*/		XUNDEF,	XXTRN,	ERR,	ERR,	ERR,	ERR,
34593Sbill };
35593Sbill 
36593Sbill /*
37593Sbill  *	table for -
38593Sbill  */
39593Sbill readonly char mintab[6][6] = {
40593Sbill /*		UND	ABS	TXT	DAT	BSS	EXT */
41593Sbill 
42593Sbill /*UND*/		XUNDEF,	XUNDEF,	XUNDEF,	XUNDEF,	XUNDEF,	XUNDEF,
43593Sbill /*ABS*/		XUNDEF,	XABS,	ERR,	ERR,	ERR,	ERR,
44593Sbill /*TXT*/		XUNDEF,	XTEXT,	XABS,	ERR,	ERR,	ERR,
45593Sbill /*DAT*/		XUNDEF,	XDATA,	ERR,	XABS,	ERR,	ERR,
46593Sbill /*BSS*/		XUNDEF,	XBSS,	ERR,	ERR,	XABS,	ERR,
47593Sbill /*EXT*/		XUNDEF,	XXTRN,	ERR,	ERR,	ERR,	ERR,
48593Sbill };
49593Sbill 
50593Sbill /*
51593Sbill  *	table for other operators
52593Sbill  */
53593Sbill readonly char othtab[6][6] = {
54593Sbill /*		UND	ABS	TXT	DAT	BSS	EXT */
55593Sbill 
56593Sbill /*UND*/		XUNDEF,	XUNDEF,	XUNDEF,	XUNDEF,	XUNDEF,	XUNDEF,
57593Sbill /*ABS*/		XUNDEF,	XABS,	ERR,	ERR,	ERR,	ERR,
58593Sbill /*TXT*/		XUNDEF,	ERR,	ERR,	ERR,	ERR,	ERR,
59593Sbill /*DAT*/		XUNDEF,	ERR,	ERR,	ERR,	ERR,	ERR,
60593Sbill /*BSS*/		XUNDEF,	ERR,	ERR,	ERR,	ERR,	ERR,
61593Sbill /*EXT*/		XUNDEF,	ERR,	ERR,	ERR,	ERR,	ERR,
62593Sbill };
63593Sbill 
645823Srrh struct exp *combine(op, exp1, exp2)
655823Srrh 	reg struct exp *exp1, *exp2;
66593Sbill {
675823Srrh 	reg 	e1_type, e2_type;
685823Srrh 	reg	back_type;
695823Srrh 	char	*btype = "The assembler can only do arithmetic on 1,2, or 4 byte integers";
70593Sbill 
71593Sbill 	lastnam=0; 			/* kludge for jxxx instructions */
72593Sbill 
73630Shenry 	e1_type = exp1->e_xtype&XTYPE;
74630Shenry 	e2_type = exp2->e_xtype&XTYPE;
75593Sbill 
76630Shenry 	if (exp1->e_xtype==XXTRN+XUNDEF)
77593Sbill 		e1_type = XTXRN;
78630Shenry 	if (exp2->e_xtype==XXTRN+XUNDEF)
79593Sbill 		e2_type = XTXRN;
80593Sbill 	if (passno==1)
81630Shenry 		if (exp1->e_xloc!=exp2->e_xloc && e1_type==e2_type)
82593Sbill 			e1_type = e2_type = XTXRN;	/* error on != loc ctrs */
83593Sbill 	e1_type >>= 1;		/*dispose of the external (XXTRN) bit*/
84593Sbill 	e2_type >>= 1;
85593Sbill 
865823Srrh 	switch(exp1->e_number.num_tag){
875823Srrh 	case TYPB:
885823Srrh 	case TYPW:
895823Srrh 	case TYPL:
905823Srrh 		break;
915823Srrh 	default:
925823Srrh 		yyerror(btype);
935823Srrh 		return(exp1);
945823Srrh 	}
955823Srrh 	switch(exp2->e_number.num_tag){
965823Srrh 	case TYPB:
975823Srrh 	case TYPW:
985823Srrh 	case TYPL:
995823Srrh 		break;
1005823Srrh 	default:
1015823Srrh 		yyerror(btype);
1025823Srrh 		return(exp1);
1035823Srrh 	}
1045823Srrh 	switch (op){
105593Sbill 	case PLUS:
106630Shenry 		exp1->e_xvalue += exp2->e_xvalue;
107630Shenry 		back_type = pltab[e1_type][e2_type];
108593Sbill 		break;
109593Sbill 	case MINUS:
110630Shenry 		exp1->e_xvalue -= exp2->e_xvalue;
111630Shenry 		back_type = mintab[e1_type][e2_type];
112593Sbill 		break;
113593Sbill 	case IOR:
114630Shenry 		exp1->e_xvalue |= exp2->e_xvalue;
115593Sbill 		goto comm;
116593Sbill 	case XOR:
117630Shenry 		exp1->e_xvalue ^= exp2->e_xvalue;
118593Sbill 		goto comm;
119593Sbill 	case AND:
120630Shenry 		exp1->e_xvalue &= exp2->e_xvalue;
121593Sbill 		goto comm;
122593Sbill 	case ORNOT:
123630Shenry 		exp1->e_xvalue |= ~exp2->e_xvalue;
124593Sbill 		goto comm;
125593Sbill 	case LSH:
126630Shenry 		exp1->e_xvalue <<= exp2->e_xvalue;
127593Sbill 		goto comm;
128593Sbill 	case RSH:
129630Shenry 		exp1->e_xvalue >>= exp2->e_xvalue;
130593Sbill 		goto comm;
131593Sbill 	case TILDE:
132630Shenry 		exp1->e_xvalue |= ~ exp2->e_xvalue;
133593Sbill 		goto comm;
134593Sbill 	case MUL:
135630Shenry 		exp1->e_xvalue *= exp2->e_xvalue;
136593Sbill 		goto comm;
137593Sbill 	case DIV:
138630Shenry 		if (exp2->e_xvalue == 0)
139593Sbill 			yyerror("Divide check");
140593Sbill 		else
141630Shenry 			exp1->e_xvalue /= exp2->e_xvalue;
142593Sbill 		goto comm;
143593Sbill 	case REGOP:
144630Shenry 		if (exp2->e_xvalue == 0)
145593Sbill 			yyerror("Divide check (modulo)");
146593Sbill 		else
147630Shenry 			exp1->e_xvalue %= exp2->e_xvalue;
148593Sbill 		goto comm;
149593Sbill 
150593Sbill 	comm:
151630Shenry 		back_type = othtab[e1_type][e2_type];
152593Sbill 		break;
153593Sbill 	default:
154593Sbill 		yyerror("Internal error: unknown operator");
155593Sbill 	}
156593Sbill 
157593Sbill 	if (e2_type==(XTXRN>>1))
158630Shenry 		exp1->e_xname = exp2->e_xname;
159630Shenry 	exp1->e_xtype = back_type | (
160630Shenry 			(exp1->e_xtype|exp2->e_xtype) & (XFORW|XXTRN) );
161630Shenry 	if (back_type==ERR)
162593Sbill 		yyerror("Relocation error");
163593Sbill 	return(exp1);
164593Sbill }
165593Sbill 
166593Sbill buildtokensets()
167593Sbill {
168593Sbill #define clobber(val, set) tokensets[(val)] |= (set)
169593Sbill 
170593Sbill 	clobber(SEMI,	LINSTBEGIN);
171593Sbill 	clobber(NL,	LINSTBEGIN);
172593Sbill 	clobber(INT,	LINSTBEGIN);
173593Sbill 
174593Sbill 	clobber(NAME,	YUKKYEXPRBEG + LINSTBEGIN);
175593Sbill 	clobber(INSTn,	YUKKYEXPRBEG);
176593Sbill 	clobber(INST0,	YUKKYEXPRBEG);
177593Sbill 	clobber(REG,	YUKKYEXPRBEG);
178593Sbill 	clobber(BFINT,	YUKKYEXPRBEG);
179593Sbill 
180593Sbill 	clobber(INT,	SAFEEXPRBEG);
1815823Srrh 	clobber(BIGNUM,	SAFEEXPRBEG);
182593Sbill 
183593Sbill 	clobber(PLUS,	ADDOPS);
184593Sbill 	clobber(MINUS,	ADDOPS + EBEGOPS);
185593Sbill 
186593Sbill 	clobber(LP,	EBEGOPS);
187593Sbill 
188593Sbill 	clobber(IOR,	BOOLOPS);
189593Sbill 	clobber(XOR,	BOOLOPS);
190593Sbill 	clobber(AND,	BOOLOPS);
191593Sbill 	clobber(ORNOT,	BOOLOPS);
192593Sbill 
193593Sbill 	clobber(TILDE,	MULOPS + EBEGOPS);
194593Sbill 	clobber(LSH,	MULOPS);
195593Sbill 	clobber(RSH,	MULOPS);
196593Sbill 	clobber(MUL,	MULOPS);
197593Sbill 	clobber(DIV,	MULOPS);
198593Sbill 	clobber(REGOP,	MULOPS);	/* % */
199593Sbill 
200593Sbill }
201593Sbill 
202593Sbill /*
203593Sbill  *	We keep the current token class in this global variable, so
204593Sbill  *	the recursive descent expression analyzers can talk amongst
205593Sbill  *	themselves, and so that we may use the macros shift and shift over
206593Sbill  */
207593Sbill 
208593Sbill extern	int	yylval;		/*the value of the lexical value*/
209593Sbill extern	struct	exp	*xp;	/*the next free expression slot*/
210593Sbill 
2115823Srrh static	inttoktype	val;
2125823Srrh 
2135823Srrh /*
2145823Srrh  *	return the value the read head is sitting on
2155823Srrh  */
2165823Srrh inttoktype exprparse(inval, backexpr)
2175823Srrh 	inttoktype	inval;
218593Sbill 	struct	exp **backexpr;
219593Sbill {
2205823Srrh 	reg	struct exp *lexpr;
2215823Srrh 	inttoktype	op;
222593Sbill 
223593Sbill 	val = inval;
224593Sbill 	lexpr = boolterm();
225593Sbill 	while (INTOKSET(val, ADDOPS)){
226593Sbill 		op = val;
227593Sbill 		shift;
228593Sbill 		lexpr = combine(op, lexpr, boolterm());
229593Sbill 	}
230593Sbill 	*backexpr = lexpr;
231593Sbill 	return(val);
232593Sbill }
233593Sbill 
234593Sbill struct exp *boolterm()
235593Sbill {
2365823Srrh 	reg	struct exp *lexpr;
2375823Srrh 	inttoktype	op;
238593Sbill 
239593Sbill 	lexpr = term();
240593Sbill 	while(INTOKSET(val, BOOLOPS)){
241593Sbill 		op = val;
242593Sbill 		shift;
243593Sbill 		lexpr = combine(op, lexpr, term());
244593Sbill 	}
245593Sbill 	return(lexpr);
246593Sbill }
247593Sbill 
248593Sbill struct exp *term()
249593Sbill {
2505823Srrh 	reg	struct	exp	*lexpr;
2515823Srrh 	inttoktype	op;
252593Sbill 
253593Sbill 	lexpr = factor();
254593Sbill 	while(INTOKSET(val, MULOPS)){
255593Sbill 		op = val;
256593Sbill 		shift;
257593Sbill 		lexpr = combine(op, lexpr, factor());
258593Sbill 	}
259593Sbill 	return(lexpr);
260593Sbill }
261593Sbill 
262593Sbill struct exp *factor()
263593Sbill {
264593Sbill 	struct	exp *lexpr;
2655823Srrh 	inttoktype	op;
266593Sbill 	extern		int	droppedLP;	/*called exprparse after consuming an LP*/
267593Sbill 
268593Sbill 	if (val == LP || droppedLP){
269593Sbill 		if (droppedLP)
270593Sbill 			droppedLP = 0;
271593Sbill 		else
272593Sbill 			shift;		/*the LP*/
273593Sbill 		val = exprparse(val, &lexpr);
274593Sbill 		if (val != RP)
275593Sbill 			yyerror("right parenthesis expected");
276593Sbill 		else
277593Sbill 			shift;
278593Sbill 	} else
279593Sbill 	if (INTOKSET(val, YUKKYEXPRBEG)){
280593Sbill 		lexpr = yukkyexpr(val, yylval);
281593Sbill 		shift;
282593Sbill 	}
283593Sbill 	else if (INTOKSET(val, SAFEEXPRBEG)){
284593Sbill 		lexpr = (struct exp *)yylval;
285593Sbill 		shift;
286593Sbill 	}
287593Sbill 	else if ( (val == TILDE) || (val == MINUS) ){
288593Sbill 		op = val;
289593Sbill 		shift;
290593Sbill 		lexpr = xp++;
291630Shenry 		lexpr->e_xtype = XABS;
2925823Srrh 		lexpr->e_number = Znumber;
2935823Srrh 		lexpr->e_number.num_tag = TYPL;
294593Sbill 		lexpr = combine(op, lexpr, factor());
2955823Srrh 	} else {
296593Sbill 		yyerror("Bad expression syntax");
297593Sbill 		lexpr = xp++;
298630Shenry 		lexpr->e_xtype = XABS;
2995823Srrh 		lexpr->e_number = Znumber;
3005823Srrh 		lexpr->e_number.num_tag = TYPL;
301593Sbill 	}
302593Sbill 	return(lexpr);
303593Sbill }
304593Sbill 
305593Sbill struct exp *yukkyexpr(val, np)
306593Sbill 	int	val;
3075823Srrh 	reg	np;
308593Sbill {
3095823Srrh 	reg	struct exp *locxp;
3105823Srrh 	extern	int	exprisname;	/*last factor is a name*/
3115823Srrh 		int	off = 0;
312593Sbill 
313593Sbill 	exprisname = 0;
314593Sbill 	locxp = xp++;
3155823Srrh 	locxp->e_number = Znumber;
3165823Srrh 	locxp->e_number.num_tag = TYPL;
3175823Srrh 
3185823Srrh 	switch(val){
3195823Srrh 	case BFINT:
3205823Srrh 		yylval = ((struct exp *)np)->e_xvalue;
3215823Srrh 		if (yylval < 0) {
3225823Srrh 			yylval = -yylval;
3235823Srrh 			yylval--;
3245823Srrh 			off = -1;
3255823Srrh 			if (lgensym[yylval] == 1)
3265823Srrh 				yyerror("Reference to undefined local label %db", yylval);
3275823Srrh 		} else {
3285823Srrh 			yylval--;
3295823Srrh 			genref[yylval] = 1;
330593Sbill 		}
3315823Srrh 		(void)sprintf(yytext, "L%d\001%d", yylval, lgensym[yylval] + off);
3325823Srrh 		yylval = np = (int)*lookup(passno == 1);
3335823Srrh 		lastnam = (struct symtab *)np;
3345823Srrh 		/* FALLTHROUGH */
3355823Srrh 	case NAME:
336593Sbill 		exprisname++;
337630Shenry 		locxp->e_xtype = ((struct symtab *)np)->s_type;
338630Shenry 		if (( ((struct symtab *)np)->s_type&XTYPE)==XUNDEF) { /*forward*/
339630Shenry 			locxp->e_xname = (struct symtab *)np;
340630Shenry 			locxp->e_xvalue = 0;
341593Sbill 			if (passno==1)
342630Shenry 				((struct symtab *)np)->s_type |= XFORW;
343593Sbill 		} else {	/*otherwise, just get the value*/
344630Shenry 			locxp->e_xvalue = ((struct symtab *)np)->s_value;
345630Shenry 			locxp->e_xname = NULL;
346593Sbill 		}
3475823Srrh 		break;
3485823Srrh 	default:
3495823Srrh 		yyerror("Internal Error in yukkyexpr");
3505823Srrh 		/* FALLTHROUGH */
3515823Srrh 
3525823Srrh 	case INSTn:
3535823Srrh 	case INST0:
3545823Srrh 	case REG:
355630Shenry 		locxp->e_xtype = XABS;
356630Shenry 		locxp->e_xvalue = ( (int)np) & 0xFF;
357630Shenry 		locxp->e_xloc = 0;
358630Shenry 		locxp->e_xname = NULL;
3595823Srrh 		break;
360593Sbill 	}
361593Sbill 
362593Sbill 	return(locxp);
363593Sbill }
364593Sbill 
36512944Srrh /*
36612944Srrh  *	Print definitions for token kinds
36712944Srrh  */
36812944Srrh static char pdirect[]	= "directive";
36912944Srrh static char pinstr[]	= "instruction";
37012944Srrh static char phunk[]	= "lexeme";
37112944Srrh static char psmall[]	= "small symbol";
37212944Srrh static char pcntrl[]	= "control token";
373593Sbill 
37412944Srrh #define	DIRECT	pdirect
37512944Srrh #define	INSTR	pinstr
37612944Srrh #define	HUNK	phunk
37712944Srrh #define	SMALL	psmall
37812944Srrh #define	CNTRL	pcntrl
37912944Srrh 
380593Sbill struct Tok_Desc{
381593Sbill 	int		tok_which;
38212944Srrh 	char		*tok_kind;
383593Sbill 	char		*tok_name;
384593Sbill };
38512944Srrh struct Tok_Desc *tok_name[LASTTOKEN - FIRSTTOKEN + 1];
38612944Srrh 
38712944Srrh struct Tok_Desc tok_desc[] = {
38812944Srrh 	FIRSTTOKEN,	DIRECT,	"first token",
38912944Srrh 
39012944Srrh 	IBYTE,		DIRECT,	".byte",
39112944Srrh 	IWORD,		DIRECT,	".word",
39212944Srrh 	IINT,		DIRECT,	".int",
39312944Srrh 	ILONG,		DIRECT,	".long",
39412944Srrh 	IQUAD,		DIRECT,	".quad",
39512944Srrh 	IOCTA,		DIRECT,	".octa",
39612944Srrh 	IFFLOAT,	DIRECT,	".ffloat",
39712944Srrh 	IDFLOAT,	DIRECT,	".dfloat",
39812944Srrh 	IGFLOAT,	DIRECT,	".gfloat",
39912944Srrh 	IHFLOAT,	DIRECT,	".hfloat",
40012944Srrh 	IASCII,		DIRECT,	".ascii",
40112944Srrh 	IASCIZ,		DIRECT,	".asciz",
40212944Srrh 	IFILL,		DIRECT,	".fill",
40312944Srrh 	ISPACE,		DIRECT,	".space",
40412944Srrh 
40512944Srrh 	IDATA,		DIRECT,	".data",
40612944Srrh 	ITEXT,		DIRECT,	".text",
40712944Srrh 	IGLOBAL,	DIRECT,	".global",
40812944Srrh 	IALIGN,		DIRECT,	".align",
40912944Srrh 
41012944Srrh 	ISET,		DIRECT,	".set",
41112944Srrh 	ICOMM,		DIRECT,	".comm",
41212944Srrh 	ILCOMM,		DIRECT,	".lcomm",
41312944Srrh 	IORG,		DIRECT,	".org",
41412944Srrh 	ILSYM,		DIRECT,	".lsym",
41512944Srrh 
41612944Srrh 	ISTAB,		DIRECT,	".stab",
41712944Srrh 	ISTABSTR,	DIRECT,	".stabstr",
41812944Srrh 	ISTABNONE,	DIRECT,	".stabnone",
41912944Srrh 	ISTABDOT,	DIRECT,	".stabdot",
42012944Srrh 
42112944Srrh 	IFILE,		DIRECT,	".file",
42212944Srrh 	ILINENO,	DIRECT,	".lineno",
42312944Srrh 	IABORT,		DIRECT,	".abort",
42412944Srrh 
42512944Srrh 	IJXXX,		INSTR,	"jump pseudo",
42612944Srrh 	INST0,		INSTR,	"0 argument inst",
42712944Srrh 	INSTn,		INSTR,	"n argument inst",
42812944Srrh 
42912944Srrh 	PARSEEOF,	CNTRL,	"parse end of file",
43012944Srrh 	ILINESKIP,	CNTRL,	"skip lines",
43112944Srrh 	VOID,		CNTRL,	"void",
43212944Srrh 	SKIP,		CNTRL,	"skip",
43312944Srrh 	NL,		CNTRL,	"new line",
43412944Srrh 	SCANEOF,	CNTRL,	"scanner end of file",
43512944Srrh 	BADCHAR,	CNTRL,	"bad character",
43612944Srrh 	SH,		CNTRL,	"comment, #",
43712944Srrh 
43812944Srrh 	INT,		HUNK,	"int",
43912944Srrh 	BFINT,		HUNK,	"local label",
44012944Srrh 	BIGNUM,		HUNK,	"big number",
44112944Srrh 	NAME,		HUNK,	"name",
44212944Srrh 	STRING,		HUNK,	"string",
44312944Srrh 	REG,		HUNK,	"register specifier",
44412944Srrh 
44512944Srrh 	SIZESPEC,	SMALL,	"size specifier, [BWLbwl]",
44612944Srrh 	SIZEQUOTE,	SMALL,	"sizequote, [^']",
44712944Srrh 	LITOP,		SMALL,	"litop",
44812944Srrh 
44912944Srrh 	MP,		SMALL,	"minus parenthesis, -(",
45012944Srrh 	REGOP,		SMALL,	"register operator, %",
45112944Srrh 
45212944Srrh 	SP,		SMALL,	"space",
45312944Srrh 	ALPH,		SMALL,	"alphabetic character, [A-Za-z_]",
45412944Srrh 	DIG,		SMALL,	"digit character, [A-Fa-f0-9]",
45512944Srrh 
45612944Srrh 	SQ,		SMALL,	"single quote, '",
45712944Srrh 	DQ,		SMALL,	"double quote, \"",
45812944Srrh 
45912944Srrh 	LSH,		SMALL,	"arithmetic left shift, <",
46012944Srrh 	RSH,		SMALL,	"arithmetic right shift, >",
46112944Srrh 	XOR,		SMALL,	"exclusive or, ^",
46212944Srrh 
46312944Srrh 	PLUS,		SMALL,	"plus, +",
46412944Srrh 	MINUS,		SMALL,	"minus, -",
46512944Srrh 	MUL,		SMALL,	"multiply, *",
46612944Srrh 	DIV,		SMALL,	"divide, /",
46712944Srrh 	SEMI,		SMALL,	"semi colon, ;",
46812944Srrh 	COLON,		SMALL,	"colon, :",
46912944Srrh 	IOR,		SMALL,	"inclusive or, |",
47012944Srrh 	AND,		SMALL,	"and, &",
47112944Srrh 
47212944Srrh 	TILDE,		SMALL,	"one's complement, ~",
47312944Srrh 	ORNOT,		SMALL,	"ornot, !",
47412944Srrh 	CM,		SMALL,	"comma",
47512944Srrh 
47612944Srrh 	LB,		SMALL,	"left bracket, [",
47712944Srrh 	RB,		SMALL,	"right bracket, ]",
47812944Srrh 	LP,		SMALL,	"left parenthesis, (",
47912944Srrh 	RP,		SMALL,	"right parentheis, )",
48012944Srrh 
48112944Srrh 	LASTTOKEN,	SMALL,	"last token",
48212944Srrh };
483593Sbill /*
484593Sbill  *	turn a token type into a string
485593Sbill  */
486593Sbill char *tok_to_name(token)
487593Sbill {
4885823Srrh 	static	int	fixed = 0;
48912944Srrh 	static	char	buf[64];
49012944Srrh 	static	struct	Tok_Desc 	NA = {0, (char *)0, "NOT ASSIGNED"};
49112944Srrh 		int	i;
49212944Srrh 		char	*cp;
4935823Srrh 
494593Sbill 	if (!fixed){
495593Sbill 		for (i = FIRSTTOKEN; i <= LASTTOKEN; i++)
49612944Srrh 			tok_name[i] = &NA;
49712944Srrh 		for (i = 0; i <= sizeof(tok_desc)/sizeof(struct Tok_Desc); i++){
49812944Srrh 			tok_name[tok_desc[i].tok_which] = &tok_desc[i];
499593Sbill 		}
500593Sbill 		fixed = 1;
501593Sbill 	}
50212944Srrh 	if (FIRSTTOKEN <= token && token <= LASTTOKEN){
50312944Srrh 		sprintf(buf, "%s %s", tok_name[token]->tok_kind,
50412944Srrh 			tok_name[token]->tok_name);
50512944Srrh 		return(buf);
50612944Srrh 	} else {
507593Sbill 		panic("Unknown token number, %d\n", token);
50812944Srrh 		/*NOTREACHED*/
50912944Srrh 	}
510593Sbill }
511