xref: /csrg-svn/old/as.vax/asparse.c (revision 597)
1*597Sbill /* Copyright (c) 1980 Regents of the University of California */
2*597Sbill static	char sccsid[] = "@(#)asparse.c 4.1 08/13/80";
3*597Sbill #include <stdio.h>
4*597Sbill #include <sys/types.h>
5*597Sbill #ifdef UNIX
6*597Sbill #  include <a.out.h>
7*597Sbill #endif UNIX
8*597Sbill 
9*597Sbill #ifdef VMS
10*597Sbill #  ifdef UNIXDEVEL
11*597Sbill #	include <a.out.h>
12*597Sbill #  else VMSDEVEL
13*597Sbill #  	include <aout.h>
14*597Sbill #  endif
15*597Sbill #endif VMS
16*597Sbill #include "as.h"
17*597Sbill #include "asexpr.h"
18*597Sbill #include "asscan.h"
19*597Sbill #include "assyms.h"
20*597Sbill 
21*597Sbill int	lgensym[10];
22*597Sbill char	genref[10];
23*597Sbill 
24*597Sbill long	bitfield;
25*597Sbill int	bitoff;
26*597Sbill int	curlen;			/* current length of literals */
27*597Sbill 
28*597Sbill /*
29*597Sbill  *	The following three variables are communication between various
30*597Sbill  *	modules to special case a number of things.  They are properly
31*597Sbill  *	categorized as hacks.
32*597Sbill  */
33*597Sbill extern	struct	symtab *lastnam;/*last name seen by the lexical analyzer*/
34*597Sbill int	exprisname;		/*last factor in an expression was a name*/
35*597Sbill int	droppedLP;		/*one is analyzing an expression beginning with*/
36*597Sbill 				/*a left parenthesis, which has already been*/
37*597Sbill 				/*shifted. (Used to parse (<expr>)(rn)*/
38*597Sbill 
39*597Sbill char	yytext[NCPS+2];		/*the lexical image*/
40*597Sbill int	yylval;			/*the lexical value; sloppy typing*/
41*597Sbill /*
42*597Sbill  *	Expression and argument managers
43*597Sbill  */
44*597Sbill struct	exp	*xp;		/*next free expression slot, used by expr.c*/
45*597Sbill struct	exp	explist[NEXP];	/*max of 20 expressions in one opcode*/
46*597Sbill struct	arg	arglist[NARG];	/*building up operands in instructions*/
47*597Sbill /*
48*597Sbill  *	Sets to accelerate token discrimination
49*597Sbill  */
50*597Sbill char	tokensets[(LASTTOKEN) - (FIRSTTOKEN) + 1];
51*597Sbill 
52*597Sbill static	char	UDotsname[32];	/*name of the assembly source*/
53*597Sbill 
54*597Sbill int	yyparse()
55*597Sbill {
56*597Sbill 	register	struct	exp	*locxp;
57*597Sbill 			/*
58*597Sbill 			 *	loc1xp and ptrloc1xp are used in the
59*597Sbill 			 * 	expression lookahead
60*597Sbill 			 */
61*597Sbill 			struct	exp	*loc1xp;	/*must be non register*/
62*597Sbill 			struct	exp	**ptrloc1xp = & loc1xp;
63*597Sbill 			struct	exp	*pval;		/*hacking expr:expr*/
64*597Sbill 
65*597Sbill 	register	struct	symtab	*np;
66*597Sbill 	register	int		argcnt;
67*597Sbill 
68*597Sbill 	register	int		val;		/*what yylex gives*/
69*597Sbill 	register	int		auxval;		/*saves val*/
70*597Sbill 
71*597Sbill 	register	struct 	arg	*ap;		/*first free argument*/
72*597Sbill 
73*597Sbill 			struct	symtab	*p;
74*597Sbill 	register	struct	symtab	*stpt;
75*597Sbill 
76*597Sbill 			struct	strdesc	*stringp;	/*handles string lists*/
77*597Sbill 
78*597Sbill 			int		regno;		/*handles arguments*/
79*597Sbill 			int		*ptrregno = &regno;
80*597Sbill 			int		sawmul;		/*saw * */
81*597Sbill 			int		sawindex;	/*saw [rn]*/
82*597Sbill 			int		sawsize;
83*597Sbill 			int		seg_type; 	/*the kind of segment: data or text*/
84*597Sbill 			int		seg_number;	/*the segment number*/
85*597Sbill 			int		space_value;	/*how much .space needs*/
86*597Sbill 
87*597Sbill 			int		field_width;	/*how wide a field is to be*/
88*597Sbill 			int		field_value;	/*the value to stuff in a field*/
89*597Sbill 			char		*stabname;	/*name of stab dealing with*/
90*597Sbill 			ptrall		stabstart;	/*where the stab starts in the buffer*/
91*597Sbill 
92*597Sbill 	xp = explist;
93*597Sbill 	ap = arglist;
94*597Sbill 
95*597Sbill 	val = yylex();
96*597Sbill 
97*597Sbill     while (val != PARSEEOF){	/* primary loop */
98*597Sbill 
99*597Sbill 	while (INTOKSET(val, LINSTBEGIN)){
100*597Sbill 		if (val == INT) {
101*597Sbill 			int i = ((struct exp *)yylval)->xvalue;
102*597Sbill 			shift;
103*597Sbill 			if (val != COLON)
104*597Sbill 				goto nocolon;
105*597Sbill 			if (i < 0 || i > 9) {
106*597Sbill 				yyerror("Local labels are 0-9");
107*597Sbill 				goto errorfix;
108*597Sbill 			}
109*597Sbill 			sprintf(yytext, "L%d\001%d", i, lgensym[i]);
110*597Sbill 			lgensym[i]++;
111*597Sbill 			genref[i] = 0;
112*597Sbill 			yylval = (int)*lookup(passno == 1);
113*597Sbill 			val = NAME;
114*597Sbill 			np = (struct symtab *)yylval;
115*597Sbill 			goto restlab;
116*597Sbill 		}
117*597Sbill 		if (val == NL){
118*597Sbill 			lineno++;
119*597Sbill 			shift;
120*597Sbill 		} else
121*597Sbill 		if (val == SEMI)
122*597Sbill 			shift;
123*597Sbill 		else {	/*its a name, so we have a label or def */
124*597Sbill 			if (val != NAME){
125*597Sbill 				ERROR("Name expected for a label");
126*597Sbill 			}
127*597Sbill 			np = (struct symtab *)yylval;
128*597Sbill 			shiftover(NAME);
129*597Sbill nocolon:
130*597Sbill 			if (val != COLON) {
131*597Sbill 				yyerror("\"%s\" is not followed by a ':' for a label definition",
132*597Sbill 					np->name);
133*597Sbill 				goto  errorfix;
134*597Sbill 			}
135*597Sbill restlab:
136*597Sbill 			shift;
137*597Sbill 			flushfield(NBPW/4);
138*597Sbill 			if ((np->type&XTYPE)!=XUNDEF) {
139*597Sbill 				if(  (np->type&XTYPE)!=dotp->xtype
140*597Sbill 				   || np->value!=dotp->xvalue
141*597Sbill 				   || (  (passno==1)
142*597Sbill 				       &&(np->index != dotp->xloc)
143*597Sbill 				      )
144*597Sbill 				  ){
145*597Sbill #ifndef DEBUG
146*597Sbill 					if (np->name[0] != 'L')
147*597Sbill #endif not DEBUG
148*597Sbill 					{
149*597Sbill 						if (passno == 1)
150*597Sbill 						  yyerror("%.8s redefined", np->name);
151*597Sbill 						else
152*597Sbill 						  yyerror("%.8s redefined: PHASE ERROR, 1st: %d, 2nd: %d",
153*597Sbill 						   np->name,
154*597Sbill 						   np->value,
155*597Sbill 						   dotp->xvalue);
156*597Sbill 					}
157*597Sbill 				}
158*597Sbill 			}
159*597Sbill 			np->type &= ~(XTYPE|XFORW);
160*597Sbill 			np->type |= dotp->xtype;
161*597Sbill 			np->value = dotp->xvalue;
162*597Sbill 			if (passno == 1){
163*597Sbill 				np->index = dotp-usedot;
164*597Sbill 				if (np->name[0] == 'L'){
165*597Sbill 					nlabels++;
166*597Sbill 				}
167*597Sbill 				np->tag = LABELID;
168*597Sbill 			}
169*597Sbill 		}	/*end of this being a label*/
170*597Sbill 	}	/*end of to consuming all labels, NLs and SEMIS */
171*597Sbill 
172*597Sbill 	xp = explist;
173*597Sbill 	ap = arglist;
174*597Sbill 
175*597Sbill 	/*
176*597Sbill 	 *	process the INSTRUCTION body
177*597Sbill 	 */
178*597Sbill 	switch(val){
179*597Sbill 
180*597Sbill     default:
181*597Sbill 	ERROR("Unrecognized instruction or directive");
182*597Sbill 
183*597Sbill    case IABORT:
184*597Sbill 	shift;
185*597Sbill 	sawabort();
186*597Sbill 	/*NOTREACHED*/
187*597Sbill 	break;
188*597Sbill 
189*597Sbill    case PARSEEOF:
190*597Sbill 	tokptr -= sizeof(toktype);
191*597Sbill 	*tokptr++ = VOID;
192*597Sbill 	tokptr[1] = VOID;
193*597Sbill 	tokptr[2] = PARSEEOF;
194*597Sbill 	break;
195*597Sbill 
196*597Sbill    case IFILE:
197*597Sbill 	shift;
198*597Sbill 	stringp = (struct strdesc *)yylval;
199*597Sbill 	shiftover(STRING);
200*597Sbill 	dotsname = &UDotsname[0];
201*597Sbill 	movestr(dotsname, stringp->str,
202*597Sbill 		stringp->str_lg >= 32? 32 :stringp->str_lg);
203*597Sbill 	dotsname[stringp->str_lg] = '\0';
204*597Sbill 	break;
205*597Sbill 
206*597Sbill    case ILINENO:
207*597Sbill 	shift;		/*over the ILINENO*/
208*597Sbill 	expr(locxp, val);
209*597Sbill 	lineno = locxp->xvalue;
210*597Sbill 	break;
211*597Sbill 
212*597Sbill    case ISET: 	/* .set  <name> , <expr> */
213*597Sbill 	shift;
214*597Sbill 	np = (struct symtab *)yylval;
215*597Sbill 	shiftover(NAME);
216*597Sbill 	shiftover(CM);
217*597Sbill 	expr(locxp, val);
218*597Sbill 	np->type &= (XXTRN|XFORW);
219*597Sbill 	np->type |= locxp->xtype&(XTYPE|XFORW);
220*597Sbill 	np->value = locxp->xvalue;
221*597Sbill 	if (passno==1)
222*597Sbill 		np->index = locxp->xloc;
223*597Sbill 	if ((locxp->xtype&XTYPE) == XUNDEF)
224*597Sbill 		yyerror("Illegal set?");
225*597Sbill 	break;
226*597Sbill 
227*597Sbill    case ILSYM: 	/*.lsym name , expr */
228*597Sbill 	shift;
229*597Sbill 	np = (struct symtab *)yylval;
230*597Sbill 	shiftover(NAME);
231*597Sbill 	shiftover(CM);
232*597Sbill 	expr(locxp, val);
233*597Sbill 	/*
234*597Sbill 	 *	Build the unique occurance of the
235*597Sbill 	 *	symbol.
236*597Sbill 	 *	The character scanner will have
237*597Sbill 	 *	already entered it into the symbol
238*597Sbill 	 *	table, but we should remove it
239*597Sbill 	 */
240*597Sbill 	if (passno == 1){
241*597Sbill 		stpt = (struct symtab *)symalloc();
242*597Sbill #ifdef FLEXNAMES
243*597Sbill 		stpt->name = np->name;
244*597Sbill #else
245*597Sbill 		movestr(stpt->name, np->name, NCPS);
246*597Sbill #endif
247*597Sbill 		np->tag = OBSOLETE;	/*invalidate original */
248*597Sbill 		nforgotten++;
249*597Sbill 		np = stpt;
250*597Sbill 		if (locxp->xtype != XABS)
251*597Sbill 			("Illegal lsym");
252*597Sbill 		np->value=locxp->xvalue;
253*597Sbill 		np->type=XABS;
254*597Sbill 		np->tag = ILSYM;
255*597Sbill 	}
256*597Sbill 	break;
257*597Sbill 
258*597Sbill    case IGLOBAL: 	/*.globl <name> */
259*597Sbill 	shift;
260*597Sbill 	np = (struct symtab *)yylval;
261*597Sbill 	shiftover(NAME);
262*597Sbill 	np->type |= XXTRN;
263*597Sbill 	break;
264*597Sbill 
265*597Sbill    case IDATA: 	/*.data [ <expr> ] */
266*597Sbill    case ITEXT: 	/*.text [ <expr> ] */
267*597Sbill 	seg_type = -val;
268*597Sbill 	shift;
269*597Sbill 	if (INTOKSET(val, EBEGOPS+YUKKYEXPRBEG+SAFEEXPRBEG)){
270*597Sbill 		expr(locxp, val);
271*597Sbill 		seg_type = -seg_type;   /*now, it is positive*/
272*597Sbill 	}
273*597Sbill 
274*597Sbill 	if (seg_type < 0) {	/*there wasn't an associated expr*/
275*597Sbill 		seg_number = 0;
276*597Sbill 		seg_type = -seg_type;
277*597Sbill 	} else {
278*597Sbill 		if (locxp->xtype != XABS || (seg_number=locxp->xvalue) >= NLOC) {
279*597Sbill 			yyerror("illegal location counter");
280*597Sbill 			seg_number = 0;
281*597Sbill 		}
282*597Sbill 	}
283*597Sbill 	if (seg_type == IDATA)
284*597Sbill 		seg_number += NLOC;
285*597Sbill 	flushfield(NBPW/4);
286*597Sbill 	dotp = &usedot[seg_number];
287*597Sbill #ifdef UNIX
288*597Sbill 	if (passno==2) {	/* go salt away in pass 2*/
289*597Sbill 		txtfil = usefile[seg_number];
290*597Sbill 		relfil = rusefile[seg_number];
291*597Sbill 	}
292*597Sbill #endif UNIX
293*597Sbill #ifdef VMS
294*597Sbill 	if (passno==2) {
295*597Sbill 		puchar(vms_obj_ptr,6);		/*  setpl  */
296*597Sbill 		puchar(vms_obj_ptr,seg_number);	/* psect # */
297*597Sbill 		plong(vms_obj_ptr,dotp->xvalue);/*  offset */
298*597Sbill 		puchar(vms_obj_ptr,80);		/*  setrb  */
299*597Sbill 		if((vms_obj_ptr-sobuf) > 400){
300*597Sbill 			write(objfil,sobuf,vms_obj_ptr-sobuf);
301*597Sbill 			vms_obj_ptr=sobuf+1;	/*flush buf*/
302*597Sbill 		}
303*597Sbill 	}
304*597Sbill #endif VMS
305*597Sbill 	break;
306*597Sbill 
307*597Sbill 	/*
308*597Sbill 	 *	Storage filler directives:
309*597Sbill 	 *
310*597Sbill 	 *	.byte	[<exprlist>]
311*597Sbill 	 *
312*597Sbill 	 *	exprlist:  empty | exprlist outexpr
313*597Sbill 	 *	outexpr:   <expr> | <expr> : <expr>
314*597Sbill 	 */
315*597Sbill    case IBYTE:	curlen = NBPW/4; goto elist;
316*597Sbill 
317*597Sbill    case IINT:
318*597Sbill    case ILONG:	curlen = NBPW;   goto elist;
319*597Sbill 
320*597Sbill    case IWORD:
321*597Sbill 	curlen = NBPW/2;
322*597Sbill    elist:
323*597Sbill 	seg_type = val;
324*597Sbill 	shift;
325*597Sbill 
326*597Sbill 	/*
327*597Sbill 	 *	Expression List processing
328*597Sbill 	 */
329*597Sbill 	if (INTOKSET(val, EBEGOPS+YUKKYEXPRBEG+SAFEEXPRBEG)){
330*597Sbill 	    do{
331*597Sbill 		/*
332*597Sbill 		 *	expression list consists of a list of :
333*597Sbill 		 *	<expr>
334*597Sbill 		 *	<expr> : <expr>
335*597Sbill 		 *		(pack expr2 into expr1 bits
336*597Sbill 		 */
337*597Sbill 		expr(locxp, val);
338*597Sbill 		/*
339*597Sbill 		 *	now, pointing at the next token
340*597Sbill 		 */
341*597Sbill 		if (val == COLON){
342*597Sbill 			shiftover(COLON);
343*597Sbill 			expr(pval, val);
344*597Sbill 			if (locxp->xtype != XABS)
345*597Sbill 			  yyerror("Width not absolute");
346*597Sbill 			field_width = locxp->xvalue;
347*597Sbill 			locxp = pval;
348*597Sbill 			if (bitoff + field_width >
349*597Sbill 			  curlen)
350*597Sbill 				flushfield(curlen);
351*597Sbill 			if (field_width > curlen)
352*597Sbill 				yyerror("Expression crosses field boundary");
353*597Sbill 		} else {
354*597Sbill 			field_width = curlen;
355*597Sbill 			flushfield(curlen);
356*597Sbill 		}
357*597Sbill 
358*597Sbill 		 if ((locxp->xtype&XTYPE)!=XABS) {
359*597Sbill 			if (bitoff)
360*597Sbill 				yyerror("Illegal relocation in field");
361*597Sbill 			field_width=LEN1;
362*597Sbill 			if (curlen==NBPW)
363*597Sbill 				field_width = LEN4;
364*597Sbill 			if (curlen==NBPW/2)
365*597Sbill 				field_width = LEN2;
366*597Sbill 			if (passno == 1){
367*597Sbill 				dotp->xvalue += reflen[field_width];
368*597Sbill 			} else {
369*597Sbill 				outrel(&locxp->xvalue,
370*597Sbill 					field_width,
371*597Sbill 					locxp->xtype,
372*597Sbill 					locxp->xname);
373*597Sbill 			}
374*597Sbill 		} else {
375*597Sbill 			field_value = locxp->xvalue & ( (1L << field_width)-1);
376*597Sbill 			bitfield |= field_value << bitoff;
377*597Sbill 			bitoff += field_width;
378*597Sbill 		}
379*597Sbill 		if ( auxval = (val == CM)) shift;
380*597Sbill 		xp = explist;
381*597Sbill 	    } while (auxval);
382*597Sbill 	}	/*existed an expression  at all*/
383*597Sbill 
384*597Sbill 	flushfield(curlen);
385*597Sbill 	if ( ( curlen == NBPW/4) && bitoff)
386*597Sbill 		dotp->xvalue ++;
387*597Sbill 	break;
388*597Sbill 	/*end of case IBYTE, IWORD, ILONG, IINT*/
389*597Sbill 
390*597Sbill    case ISPACE: 	/* .space <expr> */
391*597Sbill 	shift;
392*597Sbill 	expr(locxp, val);
393*597Sbill 	if (locxp->xtype != XABS)
394*597Sbill 		yyerror("Space size not absolute");
395*597Sbill 	space_value = locxp->xvalue;
396*597Sbill   ospace:
397*597Sbill 	flushfield(NBPW/4);
398*597Sbill #ifdef UNIX
399*597Sbill 	while (space_value > 96){
400*597Sbill 		outs(strbuf[2].str, 96);
401*597Sbill 		space_value -= 96;
402*597Sbill 	}
403*597Sbill 	outs(strbuf[2].str, space_value);
404*597Sbill #endif UNIX
405*597Sbill #ifdef VMS
406*597Sbill 	dotp->xvalue += space_value;		/*bump pc*/
407*597Sbill 	if (passno==2){
408*597Sbill 	  if(*(strbuf[2].str)==0) {
409*597Sbill 		puchar(vms_obj_ptr,81);		/* AUGR  */
410*597Sbill 		pulong(vms_obj_ptr,space_value);/* incr  */
411*597Sbill 	  } else yyerror("VMS, encountered non-0 .space");
412*597Sbill 	  if ((vms_obj_ptr-sobuf) > 400) {
413*597Sbill 		write(objfil,sobuf,vms_obj_ptr-sobuf);
414*597Sbill 		vms_obj_ptr=sobuf+1;		/*pur buf*/
415*597Sbill 	  }
416*597Sbill 	}
417*597Sbill #endif VMS
418*597Sbill 	break;
419*597Sbill 
420*597Sbill #ifdef UNIX
421*597Sbill    case	IFILL:	/* .fill count, value */
422*597Sbill 		/* fill count bytes with value */
423*597Sbill 	shift;
424*597Sbill 	expr(locxp, val);
425*597Sbill 	if (locxp->xtype != XABS)
426*597Sbill 		yyerror("Fill repetition count not absolute");
427*597Sbill 	space_value = locxp->xvalue;
428*597Sbill 	shiftover(CM);
429*597Sbill 	expr(locxp, val);
430*597Sbill 	if (locxp->xtype != XABS)
431*597Sbill 		yyerror("Fill value not absolute");
432*597Sbill 	flushfield(NBPW/4);
433*597Sbill 	while(space_value-- > 0)
434*597Sbill 		outb(locxp->xvalue & 0xFF);
435*597Sbill 	break;
436*597Sbill #endif UNIX
437*597Sbill 
438*597Sbill    case IASCII:	/* .ascii [ <stringlist> ] */
439*597Sbill    case IASCIZ: 	/* .asciz [ <stringlist> ] */
440*597Sbill 	auxval = val;
441*597Sbill 	shift;
442*597Sbill 
443*597Sbill 	/*
444*597Sbill 	 *	Code to consume a string list
445*597Sbill 	 *
446*597Sbill 	 *	stringlist: empty | STRING | stringlist STRING
447*597Sbill 	 */
448*597Sbill 	while (val ==  STRING){
449*597Sbill 		flushfield(NBPW/4);
450*597Sbill 		if (bitoff)
451*597Sbill 		  dotp->xvalue++;
452*597Sbill 		stringp = (struct strdesc *)yylval;
453*597Sbill #ifdef UNIX
454*597Sbill 		outs(stringp->str, stringp->str_lg);
455*597Sbill #endif UNIX
456*597Sbill #ifdef VMS
457*597Sbill 		{
458*597Sbill 			register int i;
459*597Sbill 			for (i=0; i < stringp->str_lg; i++){
460*597Sbill 			  dotp->xvalue += 1;
461*597Sbill 			    if (passno==2){
462*597Sbill 				puchar(vms_obj_ptr,-1);
463*597Sbill 			  	puchar(vms_obj_ptr,stringp->str[i]);
464*597Sbill 			  	if (vms_obj_ptr-sobuf > 400) {
465*597Sbill 				  write(objfil,sobuf,vms_obj_ptr-sobuf);
466*597Sbill 				  vms_obj_ptr = sobuf + 1;
467*597Sbill 			  	}
468*597Sbill 			    }
469*597Sbill 			}
470*597Sbill 		}
471*597Sbill #endif VMS
472*597Sbill 		shift;		/*over the STRING*/
473*597Sbill 		if (val == CM)	/*could be a split string*/
474*597Sbill 			shift;
475*597Sbill 	}
476*597Sbill 
477*597Sbill 	if (auxval == IASCIZ){
478*597Sbill 		flushfield(NBPW/4);
479*597Sbill #ifdef UNIX
480*597Sbill 		outb(0);
481*597Sbill #endif UNIX
482*597Sbill #ifdef VMS
483*597Sbill 		if (passno == 2) {
484*597Sbill 			puchar(vms_obj_ptr,-1);
485*597Sbill 			puchar(vms_obj_ptr,0);
486*597Sbill 		}
487*597Sbill 		dotp->xvalue += 1;
488*597Sbill #endif VMS
489*597Sbill 	}
490*597Sbill 	break;
491*597Sbill 
492*597Sbill    case IORG: 	/* .org <expr> */
493*597Sbill 	shift;
494*597Sbill 	expr(locxp, val);
495*597Sbill 
496*597Sbill 	if (locxp->xtype==XABS)
497*597Sbill 		orgwarn++;
498*597Sbill 	else if ((locxp->xtype & ~XXTRN) != dotp->xtype)
499*597Sbill 		yyerror("Illegal expression to set origin");
500*597Sbill 	space_value = locxp->xvalue - dotp->xvalue;
501*597Sbill 	if (space_value < 0)
502*597Sbill 		yyerror("Backwards 'org'");
503*597Sbill 	goto ospace;
504*597Sbill 	break;
505*597Sbill 
506*597Sbill /*
507*597Sbill  *
508*597Sbill  *	Process stabs.  Stabs are created only by the f77
509*597Sbill  *	and the C compiler with the -g flag set.
510*597Sbill  *	We only look at the stab ONCE, during pass 1, and
511*597Sbill  *	virtually remove the stab from the intermediate file
512*597Sbill  *	so it isn't seen during pass2.  This makes for some
513*597Sbill  *	hairy processing to handle labels occuring in
514*597Sbill  *	stab entries, but since most expressions in the
515*597Sbill  *	stab are integral we save lots of time in the second
516*597Sbill  *	pass by not looking at the stabs.
517*597Sbill  *	A stab that is tagged floating will be bumped during
518*597Sbill  *	the jxxx resolution phase.  A stab tagged fixed will
519*597Sbill  *	not be be bumped.
520*597Sbill  *
521*597Sbill  *	.stab:	Old fashioned stabs
522*597Sbill  *	.stabn: For stabs without names
523*597Sbill  *	.stabs:	For stabs with string names
524*597Sbill  *	.stabd: For stabs for line numbers or bracketing,
525*597Sbill  *		without a string name, without
526*597Sbill  *		a final expression.  The value of the
527*597Sbill  *		final expression is taken to be  the current
528*597Sbill  *		location counter, and is patched by the 2nd pass
529*597Sbill  *
530*597Sbill  *	.stab{<expr>,}*8,<expr>, <expr>, <expr>, <expr>
531*597Sbill  *	.stabn		 <expr>, <expr>, <expr>, <expr>
532*597Sbill  *	.stabs   STRING, <expr>, <expr>, <expr>, <expr>
533*597Sbill  *	.stabd		 <expr>, <expr>, <expr> # .
534*597Sbill  */
535*597Sbill    case ISTAB:
536*597Sbill #ifndef FLEXNAMES
537*597Sbill 	stabname = ".stab";
538*597Sbill 	if (passno == 2)	goto errorfix;
539*597Sbill 	stpt = (struct symtab *)yylval;
540*597Sbill 	/*
541*597Sbill 	 *	Make a pointer to the .stab slot.
542*597Sbill 	 *	There is a pointer in the way (stpt), and
543*597Sbill 	 *	tokptr points to the next token.
544*597Sbill 	 */
545*597Sbill 	stabstart = tokptr;
546*597Sbill 	(char *)stabstart -= sizeof(struct symtab *);
547*597Sbill 	(char *)stabstart -= sizeof(toktype);
548*597Sbill 	shift;
549*597Sbill 	for (argcnt = 0; argcnt < 8; argcnt++){
550*597Sbill 		expr(locxp, val);
551*597Sbill 		stpt->name[argcnt] = locxp->xvalue;
552*597Sbill 		xp = explist;
553*597Sbill 		shiftover(CM);
554*597Sbill 	}
555*597Sbill 	goto tailstab;
556*597Sbill #else	FLEXNAMES
557*597Sbill 	yyerror(".stab directive not supported in; report this compiler bug to system administrator");
558*597Sbill 	goto errorfix;
559*597Sbill #endif FLEXNAMES
560*597Sbill 
561*597Sbill   tailstab:
562*597Sbill 	expr(locxp, val);
563*597Sbill 	if (! (locxp->xvalue & STABTYPS)){
564*597Sbill 		yyerror("Invalid type in %s",stabname);
565*597Sbill 		goto errorfix;
566*597Sbill 	}
567*597Sbill 	stpt->ptype = locxp->xvalue;
568*597Sbill 	shiftover(CM);
569*597Sbill 	expr(locxp, val);
570*597Sbill 	stpt->other = locxp->xvalue;
571*597Sbill 	shiftover(CM);
572*597Sbill 	expr(locxp, val);
573*597Sbill 	stpt->desc = locxp->xvalue;
574*597Sbill 	shiftover(CM);
575*597Sbill 	exprisname = 0;
576*597Sbill 	expr(locxp, val);
577*597Sbill 	p = locxp->xname;
578*597Sbill 	if (p == NULL) {	/*absolute expr to begin with*/
579*597Sbill 		stpt->value = locxp->xvalue;
580*597Sbill 		stpt->index = dotp - usedot;
581*597Sbill 		if (exprisname){
582*597Sbill 			switch(stpt->ptype){
583*597Sbill 				case N_GSYM:
584*597Sbill 				case N_FNAME:
585*597Sbill 				case N_RSYM:
586*597Sbill 				case N_SSYM:
587*597Sbill 				case N_LSYM:
588*597Sbill 				case N_PSYM:
589*597Sbill 				case N_BCOMM:
590*597Sbill 				case N_ECOMM:
591*597Sbill 				case N_LENG:
592*597Sbill 					stpt->tag = STABFIXED;
593*597Sbill 					break;
594*597Sbill 				default:
595*597Sbill 					stpt->tag = STABFLOATING;
596*597Sbill 					break;
597*597Sbill 			}
598*597Sbill 		} else
599*597Sbill 			stpt->tag = STABFIXED;
600*597Sbill 	}
601*597Sbill 	else {		/*really have a name*/
602*597Sbill 		stpt->dest = locxp->xname;
603*597Sbill 		stpt->index = p->index;
604*597Sbill 		stpt->type = p->type | STABFLAG;
605*597Sbill 		/*
606*597Sbill 		 *	We will assign a more accruate
607*597Sbill 		 *	guess of locxp's location when
608*597Sbill 		 *	we sort the symbol table
609*597Sbill 		 *	The final value of value is
610*597Sbill 		 *	given by stabfix()
611*597Sbill 		 */
612*597Sbill 		stpt->tag = STABFLOATING;
613*597Sbill 	}
614*597Sbill 	/*
615*597Sbill 	 *	tokptr now points at one token beyond
616*597Sbill 	 *	the current token stored in val and yylval,
617*597Sbill 	 *	which are the next tokens after the end of
618*597Sbill 	 *	this .stab directive.  This next token must
619*597Sbill 	 *	be either a SEMI or NL, so is of width just
620*597Sbill 	 *	one.  Therefore, to point to the next token
621*597Sbill 	 *	after the end of this stab, just back up one..
622*597Sbill 	 */
623*597Sbill 	buildskip(stabstart, (char *)tokptr - sizeof(toktype));
624*597Sbill 	break;	/*end of the .stab*/
625*597Sbill 
626*597Sbill    case ISTABDOT:
627*597Sbill 	stabname = ".stabd";
628*597Sbill 	stpt = (struct symtab *)yylval;
629*597Sbill 	/*
630*597Sbill 	 *	We clobber everything after the
631*597Sbill 	 *	.stabd and its pointer... we MUST
632*597Sbill 	 *	be able to get back to this .stabd
633*597Sbill 	 *	so that we can resolve its final value
634*597Sbill 	 */
635*597Sbill 	stabstart = tokptr;
636*597Sbill 	shift;		/*over the ISTABDOT*/
637*597Sbill 	if (passno == 1){
638*597Sbill 		expr(locxp, val);
639*597Sbill 		if (! (locxp->xvalue & STABTYPS)){
640*597Sbill 			yyerror("Invalid type in .stabd");
641*597Sbill 			goto errorfix;
642*597Sbill 		}
643*597Sbill 		stpt->ptype = locxp->xvalue;
644*597Sbill 		shiftover(CM);
645*597Sbill 		expr(locxp, val);
646*597Sbill 		stpt->other = locxp->xvalue;
647*597Sbill 		shiftover(CM);
648*597Sbill 		expr(locxp, val);
649*597Sbill 		stpt->desc = locxp->xvalue;
650*597Sbill 		/*
651*597Sbill 		 *
652*597Sbill 		 *	Now, clobber everything but the
653*597Sbill 		 *	.stabd pseudo and the pointer
654*597Sbill 		 *	to its symbol table entry
655*597Sbill 		 *	tokptr points to the next token,
656*597Sbill 		 *	build the skip up to this
657*597Sbill 		 */
658*597Sbill 		buildskip(stabstart, (toktype *)tokptr - sizeof(toktype));
659*597Sbill 	}
660*597Sbill 	/*
661*597Sbill 	 *	pass 1:	Assign a good guess for its position
662*597Sbill 	 *		(ensures they are sorted into right place)/
663*597Sbill 	 *	pass 2:	Fix the actual value
664*597Sbill 	 */
665*597Sbill 	stpt->value = dotp->xvalue;
666*597Sbill 	stpt->index = dotp - usedot;
667*597Sbill 	stpt->tag = STABFLOATING;	/*although it has no effect in pass 2*/
668*597Sbill 	break;
669*597Sbill 
670*597Sbill    case ISTABNONE:	stabname = ".stabn"; goto shortstab;
671*597Sbill 
672*597Sbill    case ISTABSTR: 	stabname = ".stabs";
673*597Sbill    shortstab:
674*597Sbill 	auxval = val;
675*597Sbill 	if (passno == 2) goto errorfix;
676*597Sbill 	stpt = (struct symtab *)yylval;
677*597Sbill 	stabstart = tokptr;
678*597Sbill 	(char *)stabstart -= sizeof(struct symtab *);
679*597Sbill 	(char *)stabstart -= sizeof(toktype);
680*597Sbill 	shift;
681*597Sbill 	if (auxval == ISTABSTR){
682*597Sbill 		stringp = (struct strdesc *)yylval;
683*597Sbill 		shiftover(STRING);
684*597Sbill #ifndef FLEXNAMES
685*597Sbill 		auxval = stringp->str_lg > NCPS ? NCPS : stringp->str_lg;
686*597Sbill #else
687*597Sbill 		stringp->str[stringp->str_lg] = 0;
688*597Sbill #endif
689*597Sbill 		shiftover(CM);
690*597Sbill 	} else {
691*597Sbill 		stringp = &(strbuf[2]);
692*597Sbill #ifndef FLEXNAMES
693*597Sbill 		auxval = NCPS;
694*597Sbill #endif
695*597Sbill 	}
696*597Sbill #ifndef FLEXNAMES
697*597Sbill 	movestr(stpt->name, stringp->str, auxval);
698*597Sbill #else
699*597Sbill 	stpt->name = savestr(stringp->str);
700*597Sbill #endif
701*597Sbill 	goto tailstab;
702*597Sbill 	break;
703*597Sbill 
704*597Sbill    case ICOMM:	/* .comm  <name> , <expr> */
705*597Sbill    case ILCOMM: 	/* .lcomm <name> , <expr> */
706*597Sbill 	auxval = val;
707*597Sbill 	shift;
708*597Sbill 	np = (struct symtab *)yylval;
709*597Sbill 	shiftover(NAME);
710*597Sbill 	shiftover(CM);
711*597Sbill 	expr(locxp, val);
712*597Sbill 
713*597Sbill 	if (locxp->xtype != XABS)
714*597Sbill 		yyerror("comm size not absolute");
715*597Sbill 	if (passno==1 && (np->type&XTYPE)!=XUNDEF)
716*597Sbill 		yyerror("Redefinition of %.8s", np->name);
717*597Sbill 	if (passno==1) {
718*597Sbill 		np->value = locxp->xvalue;
719*597Sbill 		if (auxval == ICOMM)
720*597Sbill 			np->type |= XXTRN;
721*597Sbill 		else {
722*597Sbill 			np->type &= ~XTYPE;
723*597Sbill 			np->type |= XBSS;
724*597Sbill 		}
725*597Sbill 	}
726*597Sbill 	break;
727*597Sbill 
728*597Sbill    case IALIGN: 		/* .align <expr> */
729*597Sbill 	stpt = (struct symtab *)yylval;
730*597Sbill 	shift;
731*597Sbill 	expr(locxp, val);
732*597Sbill 	jalign(locxp, stpt);
733*597Sbill 	break;
734*597Sbill 
735*597Sbill    case INST0: 		/* instructions w/o arguments*/
736*597Sbill 	insout(yylval, (struct arg *)0, 0);
737*597Sbill 	shift;
738*597Sbill 	break;
739*597Sbill 
740*597Sbill    case INSTn:		/* instructions with arguments*/
741*597Sbill    case IJXXX: 		/* UNIX style jump instructions */
742*597Sbill 	auxval = val;
743*597Sbill 	seg_type = yylval;
744*597Sbill 	/*
745*597Sbill 	 *	Code to process an argument list
746*597Sbill 	 */
747*597Sbill 	ap = arglist;
748*597Sbill 	xp = explist;
749*597Sbill 
750*597Sbill 	shift;		/* bring in the first token for the arg list*/
751*597Sbill 
752*597Sbill 	for (argcnt = 1; argcnt <= 6; argcnt++, ap++){
753*597Sbill 		/*
754*597Sbill 		 *	code to process an argument proper
755*597Sbill 		 */
756*597Sbill 	    sawindex  = sawmul = sawsize = 0;
757*597Sbill 	    {
758*597Sbill 		switch(val) {
759*597Sbill 
760*597Sbill 		   default:
761*597Sbill 		     disp:
762*597Sbill 			if( !(INTOKSET(val,
763*597Sbill 				 EBEGOPS
764*597Sbill 				+YUKKYEXPRBEG
765*597Sbill 				+SAFEEXPRBEG)) ) {
766*597Sbill 				ERROR("expression expected");
767*597Sbill 			}
768*597Sbill 			expr(ap->xp,val);
769*597Sbill 		     overdisp:
770*597Sbill 			if ( val == LP || sawsize){
771*597Sbill 				shiftover(LP);
772*597Sbill 				findreg(regno);
773*597Sbill 				shiftover(RP);
774*597Sbill 				ap->atype = ADISP;
775*597Sbill 				ap->areg1 = regno;
776*597Sbill 			} else {
777*597Sbill 				ap->atype = AEXP;
778*597Sbill 				ap->areg1 = 0;
779*597Sbill 			}
780*597Sbill 			goto index;
781*597Sbill 
782*597Sbill 		   case SIZESPEC:
783*597Sbill 		     sizespec:
784*597Sbill 			sawsize = yylval;
785*597Sbill 			shift;
786*597Sbill 			goto disp;
787*597Sbill 
788*597Sbill 		   case REG:
789*597Sbill 		   case REGOP:
790*597Sbill 			findreg(regno);
791*597Sbill 			ap->atype = AREG;
792*597Sbill 			ap->areg1 = regno;
793*597Sbill 			break;
794*597Sbill 
795*597Sbill 		   case MUL:
796*597Sbill 			sawmul = 1;
797*597Sbill 			shift;
798*597Sbill 			if (val == LP) goto base;
799*597Sbill 			if (val == LITOP) goto imm;
800*597Sbill 			if (val == SIZESPEC) goto sizespec;
801*597Sbill 			if (INTOKSET(val,
802*597Sbill 				 EBEGOPS
803*597Sbill 				+YUKKYEXPRBEG
804*597Sbill 				+SAFEEXPRBEG)) goto disp;
805*597Sbill 			ERROR("expression, '(' or '$' expected");
806*597Sbill 			break;
807*597Sbill 
808*597Sbill 		   case LP:
809*597Sbill 		     base:
810*597Sbill 			shift;	/*consume the LP*/
811*597Sbill 			/*
812*597Sbill 			 *	hack the ambiguity of
813*597Sbill 			 *	movl (expr) (rn), ...
814*597Sbill 			 *	note that (expr) could also
815*597Sbill 			 *	be (rn) (by special hole in the
816*597Sbill 			 *	grammar), which we ensure
817*597Sbill 			 *	means register indirection, instead
818*597Sbill 			 *	of an expression with value n
819*597Sbill 			 */
820*597Sbill 			if (val != REG && val != REGOP){
821*597Sbill 				droppedLP = 1;
822*597Sbill 				val = exprparse(val, &(ap->xp));
823*597Sbill 				droppedLP = 0;
824*597Sbill 				goto overdisp;
825*597Sbill 			}
826*597Sbill 			findreg(regno);
827*597Sbill 			shiftover(RP);
828*597Sbill 			if (val == PLUS){
829*597Sbill 				shift;
830*597Sbill 				ap->atype = AINCR;
831*597Sbill 			} else
832*597Sbill 				ap->atype = ABASE;
833*597Sbill 			ap->areg1 = regno;
834*597Sbill 			goto index;
835*597Sbill 
836*597Sbill 		   case LITOP:
837*597Sbill 		      imm:
838*597Sbill 			shift;
839*597Sbill 			expr(locxp, val);
840*597Sbill 			ap->atype = AIMM;
841*597Sbill 			ap->areg1 = 0;
842*597Sbill 			ap->xp = locxp;
843*597Sbill 			goto index;
844*597Sbill 
845*597Sbill 		   case MP:
846*597Sbill 			shift;	/* -(reg) */
847*597Sbill 			findreg(regno);
848*597Sbill 			shiftover(RP);
849*597Sbill 			ap->atype = ADECR;
850*597Sbill 			ap->areg1 = regno;
851*597Sbill 	  index:			/*look for [reg] */
852*597Sbill 			if (val == LB){
853*597Sbill 				shift;
854*597Sbill 				findreg(regno);
855*597Sbill 				shiftover(RB);
856*597Sbill 				sawindex = 1;
857*597Sbill 				ap->areg2 = regno;
858*597Sbill 			}
859*597Sbill 			break;
860*597Sbill 
861*597Sbill 		}	/*end of the switch to process an arg*/
862*597Sbill 	    }	/*end of processing an argument*/
863*597Sbill 
864*597Sbill 	    if (sawmul){
865*597Sbill 			/*
866*597Sbill 			 * Make a concession for *(%r)
867*597Sbill 			 * meaning *0(%r)
868*597Sbill 			 */
869*597Sbill 			if (ap->atype == ABASE) {
870*597Sbill 				ap->atype = ADISP;
871*597Sbill 				xp->xtype = XABS;
872*597Sbill 				xp->xvalue = 0;
873*597Sbill 				xp->xloc = 0;
874*597Sbill 				ap->xp = xp++;
875*597Sbill 			}
876*597Sbill 			ap->atype |= ASTAR;
877*597Sbill 			sawmul = 0;
878*597Sbill 	    }
879*597Sbill 	    if (sawindex){
880*597Sbill 		ap->atype |= AINDX;
881*597Sbill 		sawindex = 0;
882*597Sbill 	    }
883*597Sbill 	    ap->dispsize = sawsize == 0 ? d124 : sawsize;
884*597Sbill 		if (val != CM) break;
885*597Sbill 		shiftover(CM);
886*597Sbill 	}	/*processing all the arguments*/
887*597Sbill 
888*597Sbill 	if (argcnt > 6){
889*597Sbill 		yyerror("More than 6 arguments");
890*597Sbill 		goto errorfix;
891*597Sbill 	}
892*597Sbill 
893*597Sbill 	insout(seg_type, arglist,
894*597Sbill 		auxval == INSTn ? argcnt : - argcnt);
895*597Sbill 	break;
896*597Sbill 
897*597Sbill    case IFLOAT:	curlen = 4;	goto floatlist;
898*597Sbill    case IDOUBLE:
899*597Sbill 	curlen = 8;
900*597Sbill       floatlist:
901*597Sbill 	/*
902*597Sbill 	 *	eat a list of floating point numbers
903*597Sbill 	 */
904*597Sbill 	shift;
905*597Sbill 	if (val == FLTNUM){
906*597Sbill 		/* KLS MOD */
907*597Sbill 		float flocal;
908*597Sbill 		do{
909*597Sbill 			if (val == CM) shift;
910*597Sbill 			if (val != FLTNUM) {
911*597Sbill 			  ERROR("floating number expected");
912*597Sbill 			}
913*597Sbill 			dotp->xvalue += curlen;
914*597Sbill #ifdef UNIX
915*597Sbill 			if (passno == 2) {
916*597Sbill 			  if(curlen == 8)
917*597Sbill 			   bwrite((char *)&(((union Double *)yylval)->dvalue),
918*597Sbill 				curlen, txtfil);
919*597Sbill 			  else  {
920*597Sbill 			   flocal = ((union Double *)yylval)->dvalue;
921*597Sbill 			   bwrite((char *)&flocal, curlen, txtfil);
922*597Sbill 			  }
923*597Sbill 			}
924*597Sbill #endif UNIX
925*597Sbill 
926*597Sbill #ifdef VMS
927*597Sbill 			if (passno == 2) {
928*597Sbill 			   puchar(vms_obj_ptr,-4);
929*597Sbill 			   pulong(vms_obj_ptr,
930*597Sbill 			    ((struct exp *)yylval)
931*597Sbill 				->doub_MSW);
932*597Sbill 			   if (curlen==8) {
933*597Sbill 			    puchar(vms_obj_ptr,-4);
934*597Sbill 			    pulong(vms_obj_ptr,
935*597Sbill 			    ((struct exp *)yylval)
936*597Sbill 				->doub_LSW);
937*597Sbill 			   }
938*597Sbill 			   if((vms_obj_ptr-sobuf) > 400) {
939*597Sbill 			    write(objfil,sobuf,vms_obj_ptr-sobuf);
940*597Sbill 			    vms_obj_ptr = sobuf + 1;
941*597Sbill 			   }
942*597Sbill 			}
943*597Sbill #endif VMS
944*597Sbill 			shift;
945*597Sbill 			xp = explist;
946*597Sbill 		} while (val == CM);
947*597Sbill 	}
948*597Sbill 	break;
949*597Sbill     }	/*end of the switch for looking at each reserved word*/
950*597Sbill 
951*597Sbill      continue;
952*597Sbill 
953*597Sbill    errorfix:
954*597Sbill 	/*
955*597Sbill 	 *	got here by either requesting to skip to the
956*597Sbill 	 *	end of this statement, or by erroring out and
957*597Sbill 	 *	wanting to apply panic mode recovery
958*597Sbill 	 */
959*597Sbill 	while (    (val != NL)
960*597Sbill 		&& (val != SEMI)
961*597Sbill 		&& (val != PARSEEOF)
962*597Sbill 	      ){
963*597Sbill 		shift;
964*597Sbill 	}
965*597Sbill 	if (val == NL)
966*597Sbill 		lineno++;
967*597Sbill 	shift;
968*597Sbill 
969*597Sbill     }	/*end of the loop to read the entire file, line by line*/
970*597Sbill 
971*597Sbill }	/*end of yyparse*/
972*597Sbill 
973*597Sbill /*
974*597Sbill  *	Process a register declaration of the form
975*597Sbill  *	% <expr>
976*597Sbill  *
977*597Sbill  *	Note:
978*597Sbill  *		The scanner has already processed funny registers of the form
979*597Sbill  *	%dd[+-]*, where dd is a decimal number in the range 00 to 15 (optional
980*597Sbill  *	preceding zero digit).  If there was any space between the % and
981*597Sbill  *	the digit, the scanner wouldn't have recognized it, so we
982*597Sbill  *	hack it out here.
983*597Sbill  */
984*597Sbill int funnyreg(val, regnoback)		/*what the read head will sit on*/
985*597Sbill 	int	val;			/*what the read head is sitting on*/
986*597Sbill 	int	*regnoback;		/*call by return*/
987*597Sbill {
988*597Sbill 	register	struct	exp *locxp;
989*597Sbill 			struct	exp *loc1xp;
990*597Sbill 			struct	exp **ptrloc1xp = & loc1xp;
991*597Sbill 
992*597Sbill 	expr(locxp, val);	/*and leave the current read head with value*/
993*597Sbill 	if ( (passno == 2) &&
994*597Sbill 	    (   locxp->xtype & XTYPE != XABS
995*597Sbill 	     || locxp->xvalue < 0
996*597Sbill 	     || locxp->xvalue >= 16
997*597Sbill 	    )
998*597Sbill 	  ){
999*597Sbill 		yyerror("Illegal register");
1000*597Sbill 		return(0);
1001*597Sbill 	}
1002*597Sbill 	*regnoback = locxp->xvalue;
1003*597Sbill 	return(val);
1004*597Sbill }
1005*597Sbill 
1006*597Sbill /*VARARGS1*/
1007*597Sbill yyerror(s, a1, a2,a3,a4,a5)
1008*597Sbill 	char	*s;
1009*597Sbill {
1010*597Sbill 	FILE		*sink;
1011*597Sbill 
1012*597Sbill #ifdef DEBUG
1013*597Sbill 	sink = stdout;
1014*597Sbill #else not DEBUG
1015*597Sbill 	sink = stderr;
1016*597Sbill #endif DEBUG
1017*597Sbill 
1018*597Sbill 	if (anyerrs == 0 && ! silent)
1019*597Sbill 		fprintf(sink, "Assembler:\n");
1020*597Sbill 	anyerrs++;
1021*597Sbill 	if (silent) return;
1022*597Sbill 
1023*597Sbill 	fprintf(sink, "\"%s\", line %d: ", dotsname, lineno);
1024*597Sbill 	fprintf(sink, s, a1, a2,a3,a4,a5);
1025*597Sbill 	fprintf(sink, "\n");
1026*597Sbill }
1027