xref: /csrg-svn/old/as.tahoe/asexpr.c (revision 29831)
1*29831Ssam /*
2*29831Ssam  *	Copyright (c) 1982 Regents of the University of California
3*29831Ssam  */
4*29831Ssam #ifndef lint
5*29831Ssam static char sccsid[] = "@(#)asexpr.c 4.5 6/30/83";
6*29831Ssam 
7*29831Ssam #endif not lint
8*29831Ssam #include <stdio.h>
9*29831Ssam #include "as.h"
10*29831Ssam #include "asscan.h"
11*29831Ssam #include "asexpr.h"
12*29831Ssam 
13*29831Ssam /*
14*29831Ssam  * Tables for combination of operands.
15*29831Ssam  */
16*29831Ssam #define	XTXRN	5<<1		/* indexes last row/column when right shifted */
17*29831Ssam 
18*29831Ssam /*
19*29831Ssam  *	table for +
20*29831Ssam  */
21*29831Ssam readonly char pltab[6][6] = {
22*29831Ssam /*		UND	ABS	TXT	DAT	BSS	EXT */
23*29831Ssam 
24*29831Ssam /*UND*/		XUNDEF,	XUNDEF,	XUNDEF,	XUNDEF,	XUNDEF,	XUNDEF,
25*29831Ssam /*ABS*/		XUNDEF,	XABS,	XTEXT,	XDATA,	XBSS,	XXTRN,
26*29831Ssam /*TXT*/		XUNDEF,	XTEXT,	ERR,	ERR,	ERR,	ERR,
27*29831Ssam /*DAT*/		XUNDEF,	XDATA,	ERR,	ERR,	ERR,	ERR,
28*29831Ssam /*BSS*/		XUNDEF,	XBSS,	ERR,	ERR,	ERR,	ERR,
29*29831Ssam /*EXT*/		XUNDEF,	XXTRN,	ERR,	ERR,	ERR,	ERR,
30*29831Ssam };
31*29831Ssam 
32*29831Ssam /*
33*29831Ssam  *	table for -
34*29831Ssam  */
35*29831Ssam readonly char mintab[6][6] = {
36*29831Ssam /*		UND	ABS	TXT	DAT	BSS	EXT */
37*29831Ssam 
38*29831Ssam /*UND*/		XUNDEF,	XUNDEF,	XUNDEF,	XUNDEF,	XUNDEF,	XUNDEF,
39*29831Ssam /*ABS*/		XUNDEF,	XABS,	ERR,	ERR,	ERR,	ERR,
40*29831Ssam /*TXT*/		XUNDEF,	XTEXT,	XABS,	ERR,	ERR,	ERR,
41*29831Ssam /*DAT*/		XUNDEF,	XDATA,	ERR,	XABS,	ERR,	ERR,
42*29831Ssam /*BSS*/		XUNDEF,	XBSS,	ERR,	ERR,	XABS,	ERR,
43*29831Ssam /*EXT*/		XUNDEF,	XXTRN,	ERR,	ERR,	ERR,	ERR,
44*29831Ssam };
45*29831Ssam 
46*29831Ssam /*
47*29831Ssam  *	table for other operators
48*29831Ssam  */
49*29831Ssam readonly char othtab[6][6] = {
50*29831Ssam /*		UND	ABS	TXT	DAT	BSS	EXT */
51*29831Ssam 
52*29831Ssam /*UND*/		XUNDEF,	XUNDEF,	XUNDEF,	XUNDEF,	XUNDEF,	XUNDEF,
53*29831Ssam /*ABS*/		XUNDEF,	XABS,	ERR,	ERR,	ERR,	ERR,
54*29831Ssam /*TXT*/		XUNDEF,	ERR,	ERR,	ERR,	ERR,	ERR,
55*29831Ssam /*DAT*/		XUNDEF,	ERR,	ERR,	ERR,	ERR,	ERR,
56*29831Ssam /*BSS*/		XUNDEF,	ERR,	ERR,	ERR,	ERR,	ERR,
57*29831Ssam /*EXT*/		XUNDEF,	ERR,	ERR,	ERR,	ERR,	ERR,
58*29831Ssam };
59*29831Ssam 
60*29831Ssam struct exp *combine(op, exp1, exp2)
61*29831Ssam 	reg struct exp *exp1, *exp2;
62*29831Ssam {
63*29831Ssam 	reg 	int e1_type, e2_type;
64*29831Ssam 	reg	int back_type;
65*29831Ssam 	char	*btype = "The assembler can only do arithmetic on 1,2, or 4 byte integers";
66*29831Ssam 
67*29831Ssam 	lastnam=0; 			/* kludge for jxxx instructions */
68*29831Ssam 
69*29831Ssam 	e1_type = exp1->e_xtype&XTYPE;
70*29831Ssam 	e2_type = exp2->e_xtype&XTYPE;
71*29831Ssam 
72*29831Ssam 	if (exp1->e_xtype==XXTRN+XUNDEF)
73*29831Ssam 		e1_type = XTXRN;
74*29831Ssam 	if (exp2->e_xtype==XXTRN+XUNDEF)
75*29831Ssam 		e2_type = XTXRN;
76*29831Ssam 	if (passno==1)
77*29831Ssam 		if (exp1->e_xloc!=exp2->e_xloc && e1_type==e2_type)
78*29831Ssam 			e1_type = e2_type = XTXRN;	/* error on != loc ctrs */
79*29831Ssam 	e1_type >>= 1;		/*dispose of the external (XXTRN) bit*/
80*29831Ssam 	e2_type >>= 1;
81*29831Ssam 
82*29831Ssam 	switch (op){
83*29831Ssam 	case PLUS:
84*29831Ssam 		exp1->e_xvalue += exp2->e_xvalue;
85*29831Ssam 		back_type = pltab[e1_type][e2_type];
86*29831Ssam 		break;
87*29831Ssam 	case MINUS:
88*29831Ssam 		exp1->e_xvalue -= exp2->e_xvalue;
89*29831Ssam 		back_type = mintab[e1_type][e2_type];
90*29831Ssam 		break;
91*29831Ssam 	case IOR:
92*29831Ssam 		exp1->e_xvalue |= exp2->e_xvalue;
93*29831Ssam 		goto comm;
94*29831Ssam 	case XOR:
95*29831Ssam 		exp1->e_xvalue ^= exp2->e_xvalue;
96*29831Ssam 		goto comm;
97*29831Ssam 	case AND:
98*29831Ssam 		exp1->e_xvalue &= exp2->e_xvalue;
99*29831Ssam 		goto comm;
100*29831Ssam 	case ORNOT:
101*29831Ssam 		exp1->e_xvalue |= ~exp2->e_xvalue;
102*29831Ssam 		goto comm;
103*29831Ssam 	case LSH:
104*29831Ssam 		exp1->e_xvalue <<= exp2->e_xvalue;
105*29831Ssam 		goto comm;
106*29831Ssam 	case RSH:
107*29831Ssam 		exp1->e_xvalue >>= exp2->e_xvalue;
108*29831Ssam 		goto comm;
109*29831Ssam 	case TILDE:
110*29831Ssam 		exp1->e_xvalue |= ~ exp2->e_xvalue;
111*29831Ssam 		goto comm;
112*29831Ssam 	case MUL:
113*29831Ssam 		exp1->e_xvalue *= exp2->e_xvalue;
114*29831Ssam 		goto comm;
115*29831Ssam 	case DIV:
116*29831Ssam 		if (exp2->e_xvalue == 0)
117*29831Ssam 			yyerror("Divide check");
118*29831Ssam 		else
119*29831Ssam 			exp1->e_xvalue /= exp2->e_xvalue;
120*29831Ssam 		goto comm;
121*29831Ssam 	case REGOP:
122*29831Ssam 		if (exp2->e_xvalue == 0)
123*29831Ssam 			yyerror("Divide check (modulo)");
124*29831Ssam 		else
125*29831Ssam 			exp1->e_xvalue %= exp2->e_xvalue;
126*29831Ssam 		goto comm;
127*29831Ssam 
128*29831Ssam 	comm:
129*29831Ssam 		back_type = othtab[e1_type][e2_type];
130*29831Ssam 		break;
131*29831Ssam 	default:
132*29831Ssam 		yyerror("Internal error: unknown operator");
133*29831Ssam 	}
134*29831Ssam 
135*29831Ssam 	if (e2_type==(XTXRN>>1))
136*29831Ssam 		exp1->e_xname = exp2->e_xname;
137*29831Ssam 	exp1->e_xtype = back_type | (
138*29831Ssam 			(exp1->e_xtype|exp2->e_xtype) & (XFORW|XXTRN) );
139*29831Ssam 	if (back_type==ERR)
140*29831Ssam 		yyerror("Relocation error");
141*29831Ssam 	return(exp1);
142*29831Ssam }
143*29831Ssam 
144*29831Ssam buildtokensets()
145*29831Ssam {
146*29831Ssam #define clobber(val, set) tokensets[(val)] |= (set)
147*29831Ssam 
148*29831Ssam 	clobber(SEMI,	LINSTBEGIN);
149*29831Ssam 	clobber(NL,	LINSTBEGIN);
150*29831Ssam 	clobber(INT,	LINSTBEGIN);
151*29831Ssam 
152*29831Ssam 	clobber(NAME,	YUKKYEXPRBEG + LINSTBEGIN);
153*29831Ssam 	clobber(INSTn,	YUKKYEXPRBEG);
154*29831Ssam 	clobber(INST0,	YUKKYEXPRBEG);
155*29831Ssam 	clobber(REG,	YUKKYEXPRBEG);
156*29831Ssam 	clobber(BFINT,	YUKKYEXPRBEG);
157*29831Ssam 
158*29831Ssam 	clobber(INT,	SAFEEXPRBEG);
159*29831Ssam 	clobber(BIGNUM,	SAFEEXPRBEG);
160*29831Ssam 
161*29831Ssam 	clobber(PLUS,	ADDOPS);
162*29831Ssam 	clobber(MINUS,	ADDOPS + EBEGOPS);
163*29831Ssam 
164*29831Ssam 	clobber(LP,	EBEGOPS);
165*29831Ssam 
166*29831Ssam 	clobber(IOR,	BOOLOPS);
167*29831Ssam 	clobber(XOR,	BOOLOPS);
168*29831Ssam 	clobber(AND,	BOOLOPS);
169*29831Ssam 	clobber(ORNOT,	BOOLOPS);
170*29831Ssam 
171*29831Ssam 	clobber(TILDE,	MULOPS + EBEGOPS);
172*29831Ssam 	clobber(LSH,	MULOPS);
173*29831Ssam 	clobber(RSH,	MULOPS);
174*29831Ssam 	clobber(MUL,	MULOPS);
175*29831Ssam 	clobber(DIV,	MULOPS);
176*29831Ssam 	clobber(REGOP,	MULOPS);	/* % */
177*29831Ssam 
178*29831Ssam }
179*29831Ssam 
180*29831Ssam /*
181*29831Ssam  *	We keep the current token class in this global variable, so
182*29831Ssam  *	the recursive descent expression analyzers can talk amongst
183*29831Ssam  *	themselves, and so that we may use the macros shift and shift over
184*29831Ssam  */
185*29831Ssam 
186*29831Ssam extern	int	yylval;		/*the value of the lexical value*/
187*29831Ssam extern	struct	exp	*xp;	/*the next free expression slot*/
188*29831Ssam 
189*29831Ssam static	inttoktype	val;
190*29831Ssam 
191*29831Ssam /*
192*29831Ssam  *	return the value the read head is sitting on
193*29831Ssam  */
194*29831Ssam inttoktype exprparse(inval, backexpr)
195*29831Ssam 	inttoktype	inval;
196*29831Ssam 	struct	exp **backexpr;
197*29831Ssam {
198*29831Ssam 	reg	struct exp *lexpr;
199*29831Ssam 	inttoktype	op;
200*29831Ssam 
201*29831Ssam 	val = inval;
202*29831Ssam 	lexpr = boolterm();
203*29831Ssam 	while (INTOKSET(val, ADDOPS)){
204*29831Ssam 		op = val;
205*29831Ssam 		shift;
206*29831Ssam 		lexpr = combine(op, lexpr, boolterm());
207*29831Ssam 	}
208*29831Ssam 	*backexpr = lexpr;
209*29831Ssam 	return(val);
210*29831Ssam }
211*29831Ssam 
212*29831Ssam struct exp *boolterm()
213*29831Ssam {
214*29831Ssam 	reg	struct exp *lexpr;
215*29831Ssam 	inttoktype	op;
216*29831Ssam 
217*29831Ssam 	lexpr = term();
218*29831Ssam 	while(INTOKSET(val, BOOLOPS)){
219*29831Ssam 		op = val;
220*29831Ssam 		shift;
221*29831Ssam 		lexpr = combine(op, lexpr, term());
222*29831Ssam 	}
223*29831Ssam 	return(lexpr);
224*29831Ssam }
225*29831Ssam 
226*29831Ssam struct exp *term()
227*29831Ssam {
228*29831Ssam 	reg	struct	exp	*lexpr;
229*29831Ssam 	inttoktype	op;
230*29831Ssam 
231*29831Ssam 	lexpr = factor();
232*29831Ssam 	while(INTOKSET(val, MULOPS)){
233*29831Ssam 		op = val;
234*29831Ssam 		shift;
235*29831Ssam 		lexpr = combine(op, lexpr, factor());
236*29831Ssam 	}
237*29831Ssam 	return(lexpr);
238*29831Ssam }
239*29831Ssam 
240*29831Ssam struct exp *factor()
241*29831Ssam {
242*29831Ssam 	struct	exp *lexpr;
243*29831Ssam 	inttoktype	op;
244*29831Ssam 	extern		int	droppedLP;	/*called exprparse after consuming an LP*/
245*29831Ssam 
246*29831Ssam 	if (val == LP || droppedLP){
247*29831Ssam 		if (droppedLP)
248*29831Ssam 			droppedLP = 0;
249*29831Ssam 		else
250*29831Ssam 			shift;		/*the LP*/
251*29831Ssam 		val = exprparse(val, &lexpr);
252*29831Ssam 		if (val != RP)
253*29831Ssam 			yyerror("right parenthesis expected");
254*29831Ssam 		else
255*29831Ssam 			shift;
256*29831Ssam 	} else
257*29831Ssam 	if (INTOKSET(val, YUKKYEXPRBEG)){
258*29831Ssam 		lexpr = yukkyexpr(val, yylval);
259*29831Ssam 		shift;
260*29831Ssam 	}
261*29831Ssam 	else if (INTOKSET(val, SAFEEXPRBEG)){
262*29831Ssam 		lexpr = (struct exp *)yylval;
263*29831Ssam 		shift;
264*29831Ssam 	}
265*29831Ssam 	else if ( (val == TILDE) || (val == MINUS) ){
266*29831Ssam 		op = val;
267*29831Ssam 		shift;
268*29831Ssam 		lexpr = xp++;
269*29831Ssam 		lexpr->e_xtype = XABS;
270*29831Ssam 		lexpr->e_number = Znumber;
271*29831Ssam 		lexpr->e_number.num_tag = TYPL;
272*29831Ssam 		lexpr = combine(op, lexpr, factor());
273*29831Ssam 	} else {
274*29831Ssam 		yyerror("Bad expression syntax");
275*29831Ssam 		lexpr = xp++;
276*29831Ssam 		lexpr->e_xtype = XABS;
277*29831Ssam 		lexpr->e_number = Znumber;
278*29831Ssam 		lexpr->e_number.num_tag = TYPL;
279*29831Ssam 	}
280*29831Ssam 	return(lexpr);
281*29831Ssam }
282*29831Ssam 
283*29831Ssam struct exp *yukkyexpr(val, np)
284*29831Ssam 	int	val;
285*29831Ssam 	reg	int np;
286*29831Ssam {
287*29831Ssam 	reg	struct exp *locxp;
288*29831Ssam 	extern	int	exprisname;	/*last factor is a name*/
289*29831Ssam 		int	off = 0;
290*29831Ssam 
291*29831Ssam 	exprisname = 0;
292*29831Ssam 	locxp = xp++;
293*29831Ssam 	locxp->e_number = Znumber;
294*29831Ssam 	locxp->e_number.num_tag = TYPL;
295*29831Ssam 
296*29831Ssam 	switch(val){
297*29831Ssam 	case BFINT:
298*29831Ssam 		yylval = ((struct exp *)np)->e_xvalue;
299*29831Ssam 		if (yylval < 0) {
300*29831Ssam 			yylval = -yylval;
301*29831Ssam 			yylval--;
302*29831Ssam 			off = -1;
303*29831Ssam 			if (lgensym[yylval] == 1)
304*29831Ssam 				yyerror("Reference to undefined local label %db", yylval);
305*29831Ssam 		} else {
306*29831Ssam 			yylval--;
307*29831Ssam 			genref[yylval] = 1;
308*29831Ssam 		}
309*29831Ssam 		(void)sprintf(yytext, "L%d\001%d", yylval, lgensym[yylval] + off);
310*29831Ssam 		yylval = np = (int)*lookup(passno == 1);
311*29831Ssam 		lastnam = (struct symtab *)np;
312*29831Ssam 		/* FALLTHROUGH */
313*29831Ssam 	case NAME:
314*29831Ssam 		exprisname++;
315*29831Ssam 		locxp->e_xtype = ((struct symtab *)np)->s_type;
316*29831Ssam 		if (( ((struct symtab *)np)->s_type&XTYPE)==XUNDEF) { /*forward*/
317*29831Ssam 			locxp->e_xname = (struct symtab *)np;
318*29831Ssam 			locxp->e_xvalue = 0;
319*29831Ssam 			if (passno==1)
320*29831Ssam 				((struct symtab *)np)->s_type |= XFORW;
321*29831Ssam 		} else {	/*otherwise, just get the value*/
322*29831Ssam 			locxp->e_xvalue = ((struct symtab *)np)->s_value;
323*29831Ssam 			locxp->e_xname = NULL;
324*29831Ssam 		}
325*29831Ssam 		break;
326*29831Ssam 	default:
327*29831Ssam 		yyerror("Internal Error in yukkyexpr");
328*29831Ssam 		/* FALLTHROUGH */
329*29831Ssam 
330*29831Ssam 	case INSTn:
331*29831Ssam 	case INST0:
332*29831Ssam 	case REG:
333*29831Ssam 		locxp->e_xtype = XABS;
334*29831Ssam 		locxp->e_xvalue = ( (int)np) & 0xFF;
335*29831Ssam 		locxp->e_xloc = 0;
336*29831Ssam 		locxp->e_xname = NULL;
337*29831Ssam 		break;
338*29831Ssam 	}
339*29831Ssam 
340*29831Ssam 	return(locxp);
341*29831Ssam }
342*29831Ssam 
343*29831Ssam /*
344*29831Ssam  *	Print definitions for token kinds
345*29831Ssam  */
346*29831Ssam static char pdirect[]	= "directive";
347*29831Ssam static char pinstr[]	= "instruction";
348*29831Ssam static char phunk[]	= "lexeme";
349*29831Ssam static char psmall[]	= "small symbol";
350*29831Ssam static char pcntrl[]	= "control token";
351*29831Ssam 
352*29831Ssam #define	DIRECT	pdirect
353*29831Ssam #define	INSTR	pinstr
354*29831Ssam #define	HUNK	phunk
355*29831Ssam #define	SMALL	psmall
356*29831Ssam #define	CNTRL	pcntrl
357*29831Ssam 
358*29831Ssam struct Tok_Desc{
359*29831Ssam 	int		tok_which;
360*29831Ssam 	char		*tok_kind;
361*29831Ssam 	char		*tok_name;
362*29831Ssam };
363*29831Ssam struct Tok_Desc *tok_name[LASTTOKEN - FIRSTTOKEN + 1];
364*29831Ssam 
365*29831Ssam struct Tok_Desc tok_desc[] = {
366*29831Ssam 	FIRSTTOKEN,	DIRECT,	"first token",
367*29831Ssam 
368*29831Ssam 	IBYTE,		DIRECT,	".byte",
369*29831Ssam 	IWORD,		DIRECT,	".word",
370*29831Ssam 	IINT,		DIRECT,	".int",
371*29831Ssam 	ILONG,		DIRECT,	".long",
372*29831Ssam 	IQUAD,		DIRECT,	".quad",
373*29831Ssam 	IFFLOAT,	DIRECT,	".ffloat",
374*29831Ssam 	IDFLOAT,	DIRECT,	".dfloat",
375*29831Ssam 	IASCII,		DIRECT,	".ascii",
376*29831Ssam 	IASCIZ,		DIRECT,	".asciz",
377*29831Ssam 	IFILL,		DIRECT,	".fill",
378*29831Ssam 	ISPACE,		DIRECT,	".space",
379*29831Ssam 
380*29831Ssam 	IDATA,		DIRECT,	".data",
381*29831Ssam 	ITEXT,		DIRECT,	".text",
382*29831Ssam 	IGLOBAL,	DIRECT,	".global",
383*29831Ssam 	IALIGN,		DIRECT,	".align",
384*29831Ssam 
385*29831Ssam 	ISET,		DIRECT,	".set",
386*29831Ssam 	ICOMM,		DIRECT,	".comm",
387*29831Ssam 	ILCOMM,		DIRECT,	".lcomm",
388*29831Ssam 	IORG,		DIRECT,	".org",
389*29831Ssam 	ILSYM,		DIRECT,	".lsym",
390*29831Ssam 
391*29831Ssam 	ISTAB,		DIRECT,	".stab",
392*29831Ssam 	ISTABSTR,	DIRECT,	".stabstr",
393*29831Ssam 	ISTABNONE,	DIRECT,	".stabnone",
394*29831Ssam 	ISTABDOT,	DIRECT,	".stabdot",
395*29831Ssam 
396*29831Ssam 	IFILE,		DIRECT,	".file",
397*29831Ssam 	ILINENO,	DIRECT,	".lineno",
398*29831Ssam 	IABORT,		DIRECT,	".abort",
399*29831Ssam 
400*29831Ssam 	IJXXX,		INSTR,	"jump pseudo",
401*29831Ssam 	INST0,		INSTR,	"0 argument inst",
402*29831Ssam 	INSTn,		INSTR,	"n argument inst",
403*29831Ssam 
404*29831Ssam 	PARSEEOF,	CNTRL,	"parse end of file",
405*29831Ssam 	ILINESKIP,	CNTRL,	"skip lines",
406*29831Ssam 	VOID,		CNTRL,	"void",
407*29831Ssam 	SKIP,		CNTRL,	"skip",
408*29831Ssam 	NL,		CNTRL,	"new line",
409*29831Ssam 	SCANEOF,	CNTRL,	"scanner end of file",
410*29831Ssam 	BADCHAR,	CNTRL,	"bad character",
411*29831Ssam 	SH,		CNTRL,	"comment, #",
412*29831Ssam 
413*29831Ssam 	INT,		HUNK,	"int",
414*29831Ssam 	BFINT,		HUNK,	"local label",
415*29831Ssam 	BIGNUM,		HUNK,	"big number",
416*29831Ssam 	NAME,		HUNK,	"name",
417*29831Ssam 	STRING,		HUNK,	"string",
418*29831Ssam 	REG,		HUNK,	"register specifier",
419*29831Ssam 
420*29831Ssam 	SIZESPEC,	SMALL,	"size specifier, [BWLbwl]",
421*29831Ssam 	SIZEQUOTE,	SMALL,	"sizequote, [^']",
422*29831Ssam 	LITOP,		SMALL,	"litop",
423*29831Ssam 
424*29831Ssam 	MP,		SMALL,	"minus parenthesis, -(",
425*29831Ssam 	REGOP,		SMALL,	"register operator, %",
426*29831Ssam 
427*29831Ssam 	SP,		SMALL,	"space",
428*29831Ssam 	ALPH,		SMALL,	"alphabetic character, [A-Za-z_]",
429*29831Ssam 	DIG,		SMALL,	"digit character, [A-Fa-f0-9]",
430*29831Ssam 
431*29831Ssam 	SQ,		SMALL,	"single quote, '",
432*29831Ssam 	DQ,		SMALL,	"double quote, \"",
433*29831Ssam 
434*29831Ssam 	LSH,		SMALL,	"arithmetic left shift, <",
435*29831Ssam 	RSH,		SMALL,	"arithmetic right shift, >",
436*29831Ssam 	XOR,		SMALL,	"exclusive or, ^",
437*29831Ssam 
438*29831Ssam 	PLUS,		SMALL,	"plus, +",
439*29831Ssam 	MINUS,		SMALL,	"minus, -",
440*29831Ssam 	MUL,		SMALL,	"multiply, *",
441*29831Ssam 	DIV,		SMALL,	"divide, /",
442*29831Ssam 	SEMI,		SMALL,	"semi colon, ;",
443*29831Ssam 	COLON,		SMALL,	"colon, :",
444*29831Ssam 	IOR,		SMALL,	"inclusive or, |",
445*29831Ssam 	AND,		SMALL,	"and, &",
446*29831Ssam 
447*29831Ssam 	TILDE,		SMALL,	"one's complement, ~",
448*29831Ssam 	ORNOT,		SMALL,	"ornot, !",
449*29831Ssam 	CM,		SMALL,	"comma",
450*29831Ssam 
451*29831Ssam 	LB,		SMALL,	"left bracket, [",
452*29831Ssam 	RB,		SMALL,	"right bracket, ]",
453*29831Ssam 	LP,		SMALL,	"left parenthesis, (",
454*29831Ssam 	RP,		SMALL,	"right parentheis, )",
455*29831Ssam 
456*29831Ssam 	LASTTOKEN,	SMALL,	"last token",
457*29831Ssam };
458*29831Ssam /*
459*29831Ssam  *	turn a token type into a string
460*29831Ssam  */
461*29831Ssam char *tok_to_name(token)
462*29831Ssam {
463*29831Ssam 	static	int	fixed = 0;
464*29831Ssam 	static	char	buf[64];
465*29831Ssam 	static	struct	Tok_Desc 	NA = {0, (char *)0, "NOT ASSIGNED"};
466*29831Ssam 		int	i;
467*29831Ssam 
468*29831Ssam 	if (!fixed){
469*29831Ssam 		for (i = FIRSTTOKEN; i <= LASTTOKEN; i++)
470*29831Ssam 			tok_name[i] = &NA;
471*29831Ssam 		for (i = 0; i <= sizeof(tok_desc)/sizeof(struct Tok_Desc); i++){
472*29831Ssam 			tok_name[tok_desc[i].tok_which] = &tok_desc[i];
473*29831Ssam 		}
474*29831Ssam 		fixed = 1;
475*29831Ssam 	}
476*29831Ssam 	if (FIRSTTOKEN <= token && token <= LASTTOKEN){
477*29831Ssam 		sprintf(buf, "%s %s", tok_name[token]->tok_kind,
478*29831Ssam 			tok_name[token]->tok_name);
479*29831Ssam 		return(buf);
480*29831Ssam 	} else {
481*29831Ssam 		panic("Unknown token number, %d\n", token);
482*29831Ssam 		/*NOTREACHED*/
483*29831Ssam 	}
484*29831Ssam }
485