xref: /csrg-svn/old/as.vax/asparse.c (revision 647)
1597Sbill /* Copyright (c) 1980 Regents of the University of California */
2*647Shenry static	char sccsid[] = "@(#)asparse.c 4.4 08/16/80";
3597Sbill #include <stdio.h>
4597Sbill #include "as.h"
5597Sbill #include "asexpr.h"
6597Sbill #include "asscan.h"
7597Sbill #include "assyms.h"
8597Sbill 
9597Sbill int	lgensym[10];
10597Sbill char	genref[10];
11597Sbill 
12597Sbill long	bitfield;
13597Sbill int	bitoff;
14597Sbill int	curlen;			/* current length of literals */
15597Sbill 
16597Sbill /*
17597Sbill  *	The following three variables are communication between various
18597Sbill  *	modules to special case a number of things.  They are properly
19597Sbill  *	categorized as hacks.
20597Sbill  */
21597Sbill extern	struct	symtab *lastnam;/*last name seen by the lexical analyzer*/
22597Sbill int	exprisname;		/*last factor in an expression was a name*/
23597Sbill int	droppedLP;		/*one is analyzing an expression beginning with*/
24597Sbill 				/*a left parenthesis, which has already been*/
25597Sbill 				/*shifted. (Used to parse (<expr>)(rn)*/
26597Sbill 
27597Sbill char	yytext[NCPS+2];		/*the lexical image*/
28597Sbill int	yylval;			/*the lexical value; sloppy typing*/
29597Sbill /*
30597Sbill  *	Expression and argument managers
31597Sbill  */
32597Sbill struct	exp	*xp;		/*next free expression slot, used by expr.c*/
33597Sbill struct	exp	explist[NEXP];	/*max of 20 expressions in one opcode*/
34597Sbill struct	arg	arglist[NARG];	/*building up operands in instructions*/
35597Sbill /*
36597Sbill  *	Sets to accelerate token discrimination
37597Sbill  */
38597Sbill char	tokensets[(LASTTOKEN) - (FIRSTTOKEN) + 1];
39597Sbill 
40597Sbill static	char	UDotsname[32];	/*name of the assembly source*/
41597Sbill 
42597Sbill int	yyparse()
43597Sbill {
44597Sbill 	register	struct	exp	*locxp;
45597Sbill 			/*
46597Sbill 			 *	loc1xp and ptrloc1xp are used in the
47597Sbill 			 * 	expression lookahead
48597Sbill 			 */
49597Sbill 			struct	exp	*loc1xp;	/*must be non register*/
50597Sbill 			struct	exp	**ptrloc1xp = & loc1xp;
51597Sbill 			struct	exp	*pval;		/*hacking expr:expr*/
52597Sbill 
53597Sbill 	register	struct	symtab	*np;
54597Sbill 	register	int		argcnt;
55597Sbill 
56597Sbill 	register	int		val;		/*what yylex gives*/
57597Sbill 	register	int		auxval;		/*saves val*/
58597Sbill 
59597Sbill 	register	struct 	arg	*ap;		/*first free argument*/
60597Sbill 
61597Sbill 			struct	symtab	*p;
62597Sbill 	register	struct	symtab	*stpt;
63597Sbill 
64597Sbill 			struct	strdesc	*stringp;	/*handles string lists*/
65597Sbill 
66597Sbill 			int		regno;		/*handles arguments*/
67597Sbill 			int		*ptrregno = &regno;
68597Sbill 			int		sawmul;		/*saw * */
69597Sbill 			int		sawindex;	/*saw [rn]*/
70597Sbill 			int		sawsize;
71597Sbill 			int		seg_type; 	/*the kind of segment: data or text*/
72597Sbill 			int		seg_number;	/*the segment number*/
73597Sbill 			int		space_value;	/*how much .space needs*/
74*647Shenry 			int		fill_rep;	/*how many reps for .fill */
75*647Shenry 			int		fill_size;	/*how many bytes for .fill */
76597Sbill 
77597Sbill 			int		field_width;	/*how wide a field is to be*/
78597Sbill 			int		field_value;	/*the value to stuff in a field*/
79597Sbill 			char		*stabname;	/*name of stab dealing with*/
80597Sbill 			ptrall		stabstart;	/*where the stab starts in the buffer*/
81597Sbill 
82597Sbill 	xp = explist;
83597Sbill 	ap = arglist;
84597Sbill 
85597Sbill 	val = yylex();
86597Sbill 
87597Sbill     while (val != PARSEEOF){	/* primary loop */
88597Sbill 
89597Sbill 	while (INTOKSET(val, LINSTBEGIN)){
90597Sbill 		if (val == INT) {
91632Shenry 			int i = ((struct exp *)yylval)->e_xvalue;
92597Sbill 			shift;
93597Sbill 			if (val != COLON)
94597Sbill 				goto nocolon;
95597Sbill 			if (i < 0 || i > 9) {
96597Sbill 				yyerror("Local labels are 0-9");
97597Sbill 				goto errorfix;
98597Sbill 			}
99597Sbill 			sprintf(yytext, "L%d\001%d", i, lgensym[i]);
100597Sbill 			lgensym[i]++;
101597Sbill 			genref[i] = 0;
102597Sbill 			yylval = (int)*lookup(passno == 1);
103597Sbill 			val = NAME;
104597Sbill 			np = (struct symtab *)yylval;
105597Sbill 			goto restlab;
106597Sbill 		}
107597Sbill 		if (val == NL){
108597Sbill 			lineno++;
109597Sbill 			shift;
110597Sbill 		} else
111597Sbill 		if (val == SEMI)
112597Sbill 			shift;
113597Sbill 		else {	/*its a name, so we have a label or def */
114597Sbill 			if (val != NAME){
115597Sbill 				ERROR("Name expected for a label");
116597Sbill 			}
117597Sbill 			np = (struct symtab *)yylval;
118597Sbill 			shiftover(NAME);
119597Sbill nocolon:
120597Sbill 			if (val != COLON) {
121632Shenry #ifdef FLEXNAMES
122597Sbill 				yyerror("\"%s\" is not followed by a ':' for a label definition",
123632Shenry #else not FLEXNAMES
124632Shenry 				yyerror("\"%.*s\" is not followed by a ':' for a label definition",
125632Shenry 					NCPS,
126632Shenry #endif not FLEXNAMES
127632Shenry 					np->s_name);
128597Sbill 				goto  errorfix;
129597Sbill 			}
130597Sbill restlab:
131597Sbill 			shift;
132597Sbill 			flushfield(NBPW/4);
133632Shenry 			if ((np->s_type&XTYPE)!=XUNDEF) {
134632Shenry 				if(  (np->s_type&XTYPE)!=dotp->e_xtype
135632Shenry 				   || np->s_value!=dotp->e_xvalue
136597Sbill 				   || (  (passno==1)
137632Shenry 				       &&(np->s_index != dotp->e_xloc)
138597Sbill 				      )
139597Sbill 				  ){
140597Sbill #ifndef DEBUG
141632Shenry 					if (np->s_name[0] != 'L')
142597Sbill #endif not DEBUG
143597Sbill 					{
144597Sbill 						if (passno == 1)
145632Shenry #ifdef FLEXNAMES
146632Shenry 						  yyerror("%s redefined",
147632Shenry #else not FLEXNAMES
148632Shenry 						  yyerror("%.*s redefined",
149632Shenry 							NCPS,
150632Shenry #endif not FLEXNAMES
151632Shenry 							np->s_name);
152597Sbill 						else
153632Shenry #ifdef FLEXNAMES
154632Shenry 						  yyerror("%s redefined: PHASE ERROR, 1st: %d, 2nd: %d",
155632Shenry #else not FLEXNAMES
156632Shenry 						  yyerror("%.*s redefined: PHASE ERROR, 1st: %d, 2nd: %d",
157632Shenry 							NCPS,
158632Shenry #endif not FLEXNAMES
159632Shenry 							np->s_name,
160632Shenry 							np->s_value,
161632Shenry 							dotp->e_xvalue);
162597Sbill 					}
163597Sbill 				}
164597Sbill 			}
165632Shenry 			np->s_type &= ~(XTYPE|XFORW);
166632Shenry 			np->s_type |= dotp->e_xtype;
167632Shenry 			np->s_value = dotp->e_xvalue;
168597Sbill 			if (passno == 1){
169632Shenry 				np->s_index = dotp-usedot;
170632Shenry 				if (np->s_name[0] == 'L'){
171597Sbill 					nlabels++;
172597Sbill 				}
173632Shenry 				np->s_tag = LABELID;
174597Sbill 			}
175597Sbill 		}	/*end of this being a label*/
176597Sbill 	}	/*end of to consuming all labels, NLs and SEMIS */
177597Sbill 
178597Sbill 	xp = explist;
179597Sbill 	ap = arglist;
180597Sbill 
181597Sbill 	/*
182597Sbill 	 *	process the INSTRUCTION body
183597Sbill 	 */
184597Sbill 	switch(val){
185597Sbill 
186597Sbill     default:
187597Sbill 	ERROR("Unrecognized instruction or directive");
188597Sbill 
189597Sbill    case IABORT:
190597Sbill 	shift;
191597Sbill 	sawabort();
192597Sbill 	/*NOTREACHED*/
193597Sbill 	break;
194597Sbill 
195597Sbill    case PARSEEOF:
196597Sbill 	tokptr -= sizeof(toktype);
197597Sbill 	*tokptr++ = VOID;
198597Sbill 	tokptr[1] = VOID;
199597Sbill 	tokptr[2] = PARSEEOF;
200597Sbill 	break;
201597Sbill 
202597Sbill    case IFILE:
203597Sbill 	shift;
204597Sbill 	stringp = (struct strdesc *)yylval;
205597Sbill 	shiftover(STRING);
206597Sbill 	dotsname = &UDotsname[0];
207597Sbill 	movestr(dotsname, stringp->str,
208597Sbill 		stringp->str_lg >= 32? 32 :stringp->str_lg);
209597Sbill 	dotsname[stringp->str_lg] = '\0';
210597Sbill 	break;
211597Sbill 
212597Sbill    case ILINENO:
213597Sbill 	shift;		/*over the ILINENO*/
214597Sbill 	expr(locxp, val);
215632Shenry 	lineno = locxp->e_xvalue;
216597Sbill 	break;
217597Sbill 
218597Sbill    case ISET: 	/* .set  <name> , <expr> */
219597Sbill 	shift;
220597Sbill 	np = (struct symtab *)yylval;
221597Sbill 	shiftover(NAME);
222597Sbill 	shiftover(CM);
223597Sbill 	expr(locxp, val);
224632Shenry 	np->s_type &= (XXTRN|XFORW);
225632Shenry 	np->s_type |= locxp->e_xtype&(XTYPE|XFORW);
226632Shenry 	np->s_value = locxp->e_xvalue;
227597Sbill 	if (passno==1)
228632Shenry 		np->s_index = locxp->e_xloc;
229632Shenry 	if ((locxp->e_xtype&XTYPE) == XUNDEF)
230597Sbill 		yyerror("Illegal set?");
231597Sbill 	break;
232597Sbill 
233597Sbill    case ILSYM: 	/*.lsym name , expr */
234597Sbill 	shift;
235597Sbill 	np = (struct symtab *)yylval;
236597Sbill 	shiftover(NAME);
237597Sbill 	shiftover(CM);
238597Sbill 	expr(locxp, val);
239597Sbill 	/*
240597Sbill 	 *	Build the unique occurance of the
241597Sbill 	 *	symbol.
242597Sbill 	 *	The character scanner will have
243597Sbill 	 *	already entered it into the symbol
244597Sbill 	 *	table, but we should remove it
245597Sbill 	 */
246597Sbill 	if (passno == 1){
247597Sbill 		stpt = (struct symtab *)symalloc();
248597Sbill #ifdef FLEXNAMES
249632Shenry 		stpt->s_name = np->s_name;
250597Sbill #else
251632Shenry 		movestr(stpt->s_name, np->s_name, NCPS);
252597Sbill #endif
253632Shenry 		np->s_tag = OBSOLETE;	/*invalidate original */
254597Sbill 		nforgotten++;
255597Sbill 		np = stpt;
256632Shenry 		if (locxp->e_xtype != XABS)
257597Sbill 			("Illegal lsym");
258632Shenry 		np->s_value=locxp->e_xvalue;
259632Shenry 		np->s_type=XABS;
260632Shenry 		np->s_tag = ILSYM;
261597Sbill 	}
262597Sbill 	break;
263597Sbill 
264597Sbill    case IGLOBAL: 	/*.globl <name> */
265597Sbill 	shift;
266597Sbill 	np = (struct symtab *)yylval;
267597Sbill 	shiftover(NAME);
268632Shenry 	np->s_type |= XXTRN;
269597Sbill 	break;
270597Sbill 
271597Sbill    case IDATA: 	/*.data [ <expr> ] */
272597Sbill    case ITEXT: 	/*.text [ <expr> ] */
273597Sbill 	seg_type = -val;
274597Sbill 	shift;
275597Sbill 	if (INTOKSET(val, EBEGOPS+YUKKYEXPRBEG+SAFEEXPRBEG)){
276597Sbill 		expr(locxp, val);
277597Sbill 		seg_type = -seg_type;   /*now, it is positive*/
278597Sbill 	}
279597Sbill 
280597Sbill 	if (seg_type < 0) {	/*there wasn't an associated expr*/
281597Sbill 		seg_number = 0;
282597Sbill 		seg_type = -seg_type;
283597Sbill 	} else {
284632Shenry 		if (locxp->e_xtype != XABS || (seg_number=locxp->e_xvalue) >= NLOC) {
285597Sbill 			yyerror("illegal location counter");
286597Sbill 			seg_number = 0;
287597Sbill 		}
288597Sbill 	}
289597Sbill 	if (seg_type == IDATA)
290597Sbill 		seg_number += NLOC;
291597Sbill 	flushfield(NBPW/4);
292597Sbill 	dotp = &usedot[seg_number];
293597Sbill #ifdef UNIX
294597Sbill 	if (passno==2) {	/* go salt away in pass 2*/
295597Sbill 		txtfil = usefile[seg_number];
296597Sbill 		relfil = rusefile[seg_number];
297597Sbill 	}
298597Sbill #endif UNIX
299597Sbill #ifdef VMS
300597Sbill 	if (passno==2) {
301597Sbill 		puchar(vms_obj_ptr,6);		/*  setpl  */
302597Sbill 		puchar(vms_obj_ptr,seg_number);	/* psect # */
303632Shenry 		plong(vms_obj_ptr,dotp->e_xvalue);/*  offset */
304597Sbill 		puchar(vms_obj_ptr,80);		/*  setrb  */
305597Sbill 		if((vms_obj_ptr-sobuf) > 400){
306597Sbill 			write(objfil,sobuf,vms_obj_ptr-sobuf);
307597Sbill 			vms_obj_ptr=sobuf+1;	/*flush buf*/
308597Sbill 		}
309597Sbill 	}
310597Sbill #endif VMS
311597Sbill 	break;
312597Sbill 
313597Sbill 	/*
314597Sbill 	 *	Storage filler directives:
315597Sbill 	 *
316597Sbill 	 *	.byte	[<exprlist>]
317597Sbill 	 *
318597Sbill 	 *	exprlist:  empty | exprlist outexpr
319597Sbill 	 *	outexpr:   <expr> | <expr> : <expr>
320597Sbill 	 */
321597Sbill    case IBYTE:	curlen = NBPW/4; goto elist;
322597Sbill 
323597Sbill    case IINT:
324597Sbill    case ILONG:	curlen = NBPW;   goto elist;
325597Sbill 
326597Sbill    case IWORD:
327597Sbill 	curlen = NBPW/2;
328597Sbill    elist:
329597Sbill 	seg_type = val;
330597Sbill 	shift;
331597Sbill 
332597Sbill 	/*
333597Sbill 	 *	Expression List processing
334597Sbill 	 */
335597Sbill 	if (INTOKSET(val, EBEGOPS+YUKKYEXPRBEG+SAFEEXPRBEG)){
336597Sbill 	    do{
337597Sbill 		/*
338597Sbill 		 *	expression list consists of a list of :
339597Sbill 		 *	<expr>
340597Sbill 		 *	<expr> : <expr>
341597Sbill 		 *		(pack expr2 into expr1 bits
342597Sbill 		 */
343597Sbill 		expr(locxp, val);
344597Sbill 		/*
345597Sbill 		 *	now, pointing at the next token
346597Sbill 		 */
347597Sbill 		if (val == COLON){
348597Sbill 			shiftover(COLON);
349597Sbill 			expr(pval, val);
350632Shenry 			if (locxp->e_xtype != XABS)
351597Sbill 			  yyerror("Width not absolute");
352632Shenry 			field_width = locxp->e_xvalue;
353597Sbill 			locxp = pval;
354597Sbill 			if (bitoff + field_width >
355597Sbill 			  curlen)
356597Sbill 				flushfield(curlen);
357597Sbill 			if (field_width > curlen)
358597Sbill 				yyerror("Expression crosses field boundary");
359597Sbill 		} else {
360597Sbill 			field_width = curlen;
361597Sbill 			flushfield(curlen);
362597Sbill 		}
363597Sbill 
364632Shenry 		 if ((locxp->e_xtype&XTYPE)!=XABS) {
365597Sbill 			if (bitoff)
366597Sbill 				yyerror("Illegal relocation in field");
367597Sbill 			field_width=LEN1;
368597Sbill 			if (curlen==NBPW)
369597Sbill 				field_width = LEN4;
370597Sbill 			if (curlen==NBPW/2)
371597Sbill 				field_width = LEN2;
372597Sbill 			if (passno == 1){
373632Shenry 				dotp->e_xvalue += reflen[field_width];
374597Sbill 			} else {
375632Shenry 				outrel(&locxp->e_xvalue,
376597Sbill 					field_width,
377632Shenry 					locxp->e_xtype,
378632Shenry 					locxp->e_xname);
379597Sbill 			}
380597Sbill 		} else {
381632Shenry 			field_value = locxp->e_xvalue & ( (1L << field_width)-1);
382597Sbill 			bitfield |= field_value << bitoff;
383597Sbill 			bitoff += field_width;
384597Sbill 		}
385597Sbill 		if ( auxval = (val == CM)) shift;
386597Sbill 		xp = explist;
387597Sbill 	    } while (auxval);
388597Sbill 	}	/*existed an expression  at all*/
389597Sbill 
390597Sbill 	flushfield(curlen);
391597Sbill 	if ( ( curlen == NBPW/4) && bitoff)
392632Shenry 		dotp->e_xvalue ++;
393597Sbill 	break;
394597Sbill 	/*end of case IBYTE, IWORD, ILONG, IINT*/
395597Sbill 
396597Sbill    case ISPACE: 	/* .space <expr> */
397597Sbill 	shift;
398597Sbill 	expr(locxp, val);
399632Shenry 	if (locxp->e_xtype != XABS)
400597Sbill 		yyerror("Space size not absolute");
401632Shenry 	space_value = locxp->e_xvalue;
402597Sbill   ospace:
403597Sbill 	flushfield(NBPW/4);
404597Sbill #ifdef UNIX
405597Sbill 	while (space_value > 96){
406597Sbill 		outs(strbuf[2].str, 96);
407597Sbill 		space_value -= 96;
408597Sbill 	}
409597Sbill 	outs(strbuf[2].str, space_value);
410597Sbill #endif UNIX
411597Sbill #ifdef VMS
412632Shenry 	dotp->e_xvalue += space_value;		/*bump pc*/
413597Sbill 	if (passno==2){
414597Sbill 	  if(*(strbuf[2].str)==0) {
415597Sbill 		puchar(vms_obj_ptr,81);		/* AUGR  */
416597Sbill 		pulong(vms_obj_ptr,space_value);/* incr  */
417597Sbill 	  } else yyerror("VMS, encountered non-0 .space");
418597Sbill 	  if ((vms_obj_ptr-sobuf) > 400) {
419597Sbill 		write(objfil,sobuf,vms_obj_ptr-sobuf);
420597Sbill 		vms_obj_ptr=sobuf+1;		/*pur buf*/
421597Sbill 	  }
422597Sbill 	}
423597Sbill #endif VMS
424597Sbill 	break;
425597Sbill 
426597Sbill #ifdef UNIX
427*647Shenry 	/*
428*647Shenry 	 *	.fill rep, size, value
429*647Shenry 	 *	repeat rep times: fill size bytes with (truncated) value
430*647Shenry 	 *	size must be between 1 and 8
431*647Shenry 	 */
432*647Shenry    case	IFILL:
433597Sbill 	shift;
434597Sbill 	expr(locxp, val);
435632Shenry 	if (locxp->e_xtype != XABS)
436597Sbill 		yyerror("Fill repetition count not absolute");
437*647Shenry 	fill_rep = locxp->e_xvalue;
438597Sbill 	shiftover(CM);
439597Sbill 	expr(locxp, val);
440632Shenry 	if (locxp->e_xtype != XABS)
441*647Shenry 		yyerror("Fill size not absolute");
442*647Shenry 	fill_size = locxp->e_xvalue;
443*647Shenry 	if (fill_size <= 0 || fill_size > 8)
444*647Shenry 		yyerror("Fill count not in in 1..8");
445*647Shenry 	shiftover(CM);
446*647Shenry 	expr(locxp, val);
447*647Shenry 	if (passno == 2 && locxp->e_xtype != XABS)
448*647Shenry 			yyerror("Fill value not absolute");
449597Sbill 	flushfield(NBPW/4);
450*647Shenry 	if (passno == 1) {
451*647Shenry 		locxp->e_xvalue += fill_rep * fill_size;
452*647Shenry 	} else {
453*647Shenry 		while(fill_rep-- > 0)
454*647Shenry 			bwrite(&locxp->e_xvalue, fill_size, txtfil);
455*647Shenry 	}
456597Sbill 	break;
457597Sbill #endif UNIX
458597Sbill 
459597Sbill    case IASCII:	/* .ascii [ <stringlist> ] */
460597Sbill    case IASCIZ: 	/* .asciz [ <stringlist> ] */
461597Sbill 	auxval = val;
462597Sbill 	shift;
463597Sbill 
464597Sbill 	/*
465597Sbill 	 *	Code to consume a string list
466597Sbill 	 *
467597Sbill 	 *	stringlist: empty | STRING | stringlist STRING
468597Sbill 	 */
469597Sbill 	while (val ==  STRING){
470597Sbill 		flushfield(NBPW/4);
471597Sbill 		if (bitoff)
472632Shenry 		  dotp->e_xvalue++;
473597Sbill 		stringp = (struct strdesc *)yylval;
474597Sbill #ifdef UNIX
475597Sbill 		outs(stringp->str, stringp->str_lg);
476597Sbill #endif UNIX
477597Sbill #ifdef VMS
478597Sbill 		{
479597Sbill 			register int i;
480597Sbill 			for (i=0; i < stringp->str_lg; i++){
481632Shenry 			  dotp->e_xvalue += 1;
482597Sbill 			    if (passno==2){
483597Sbill 				puchar(vms_obj_ptr,-1);
484597Sbill 			  	puchar(vms_obj_ptr,stringp->str[i]);
485597Sbill 			  	if (vms_obj_ptr-sobuf > 400) {
486597Sbill 				  write(objfil,sobuf,vms_obj_ptr-sobuf);
487597Sbill 				  vms_obj_ptr = sobuf + 1;
488597Sbill 			  	}
489597Sbill 			    }
490597Sbill 			}
491597Sbill 		}
492597Sbill #endif VMS
493597Sbill 		shift;		/*over the STRING*/
494597Sbill 		if (val == CM)	/*could be a split string*/
495597Sbill 			shift;
496597Sbill 	}
497597Sbill 
498597Sbill 	if (auxval == IASCIZ){
499597Sbill 		flushfield(NBPW/4);
500597Sbill #ifdef UNIX
501597Sbill 		outb(0);
502597Sbill #endif UNIX
503597Sbill #ifdef VMS
504597Sbill 		if (passno == 2) {
505597Sbill 			puchar(vms_obj_ptr,-1);
506597Sbill 			puchar(vms_obj_ptr,0);
507597Sbill 		}
508632Shenry 		dotp->e_xvalue += 1;
509597Sbill #endif VMS
510597Sbill 	}
511597Sbill 	break;
512597Sbill 
513597Sbill    case IORG: 	/* .org <expr> */
514597Sbill 	shift;
515597Sbill 	expr(locxp, val);
516597Sbill 
517632Shenry 	if (locxp->e_xtype==XABS)
518597Sbill 		orgwarn++;
519632Shenry 	else if ((locxp->e_xtype & ~XXTRN) != dotp->e_xtype)
520597Sbill 		yyerror("Illegal expression to set origin");
521632Shenry 	space_value = locxp->e_xvalue - dotp->e_xvalue;
522597Sbill 	if (space_value < 0)
523597Sbill 		yyerror("Backwards 'org'");
524597Sbill 	goto ospace;
525597Sbill 	break;
526597Sbill 
527597Sbill /*
528597Sbill  *
529597Sbill  *	Process stabs.  Stabs are created only by the f77
530597Sbill  *	and the C compiler with the -g flag set.
531597Sbill  *	We only look at the stab ONCE, during pass 1, and
532597Sbill  *	virtually remove the stab from the intermediate file
533597Sbill  *	so it isn't seen during pass2.  This makes for some
534597Sbill  *	hairy processing to handle labels occuring in
535597Sbill  *	stab entries, but since most expressions in the
536597Sbill  *	stab are integral we save lots of time in the second
537597Sbill  *	pass by not looking at the stabs.
538597Sbill  *	A stab that is tagged floating will be bumped during
539597Sbill  *	the jxxx resolution phase.  A stab tagged fixed will
540597Sbill  *	not be be bumped.
541597Sbill  *
542597Sbill  *	.stab:	Old fashioned stabs
543597Sbill  *	.stabn: For stabs without names
544597Sbill  *	.stabs:	For stabs with string names
545597Sbill  *	.stabd: For stabs for line numbers or bracketing,
546597Sbill  *		without a string name, without
547597Sbill  *		a final expression.  The value of the
548597Sbill  *		final expression is taken to be  the current
549597Sbill  *		location counter, and is patched by the 2nd pass
550597Sbill  *
551597Sbill  *	.stab{<expr>,}*8,<expr>, <expr>, <expr>, <expr>
552597Sbill  *	.stabn		 <expr>, <expr>, <expr>, <expr>
553597Sbill  *	.stabs   STRING, <expr>, <expr>, <expr>, <expr>
554597Sbill  *	.stabd		 <expr>, <expr>, <expr> # .
555597Sbill  */
556597Sbill    case ISTAB:
557597Sbill #ifndef FLEXNAMES
558597Sbill 	stabname = ".stab";
559597Sbill 	if (passno == 2)	goto errorfix;
560597Sbill 	stpt = (struct symtab *)yylval;
561597Sbill 	/*
562597Sbill 	 *	Make a pointer to the .stab slot.
563597Sbill 	 *	There is a pointer in the way (stpt), and
564597Sbill 	 *	tokptr points to the next token.
565597Sbill 	 */
566597Sbill 	stabstart = tokptr;
567597Sbill 	(char *)stabstart -= sizeof(struct symtab *);
568597Sbill 	(char *)stabstart -= sizeof(toktype);
569597Sbill 	shift;
570597Sbill 	for (argcnt = 0; argcnt < 8; argcnt++){
571597Sbill 		expr(locxp, val);
572632Shenry 		stpt->s_name[argcnt] = locxp->e_xvalue;
573597Sbill 		xp = explist;
574597Sbill 		shiftover(CM);
575597Sbill 	}
576597Sbill 	goto tailstab;
577597Sbill #else	FLEXNAMES
578597Sbill 	yyerror(".stab directive not supported in; report this compiler bug to system administrator");
579597Sbill 	goto errorfix;
580597Sbill #endif FLEXNAMES
581597Sbill 
582597Sbill   tailstab:
583597Sbill 	expr(locxp, val);
584632Shenry 	if (! (locxp->e_xvalue & STABTYPS)){
585597Sbill 		yyerror("Invalid type in %s",stabname);
586597Sbill 		goto errorfix;
587597Sbill 	}
588632Shenry 	stpt->s_ptype = locxp->e_xvalue;
589597Sbill 	shiftover(CM);
590597Sbill 	expr(locxp, val);
591632Shenry 	stpt->s_other = locxp->e_xvalue;
592597Sbill 	shiftover(CM);
593597Sbill 	expr(locxp, val);
594632Shenry 	stpt->s_desc = locxp->e_xvalue;
595597Sbill 	shiftover(CM);
596597Sbill 	exprisname = 0;
597597Sbill 	expr(locxp, val);
598632Shenry 	p = locxp->e_xname;
599597Sbill 	if (p == NULL) {	/*absolute expr to begin with*/
600632Shenry 		stpt->s_value = locxp->e_xvalue;
601632Shenry 		stpt->s_index = dotp - usedot;
602597Sbill 		if (exprisname){
603632Shenry 			switch(stpt->s_ptype){
604597Sbill 				case N_GSYM:
605597Sbill 				case N_FNAME:
606597Sbill 				case N_RSYM:
607597Sbill 				case N_SSYM:
608597Sbill 				case N_LSYM:
609597Sbill 				case N_PSYM:
610597Sbill 				case N_BCOMM:
611597Sbill 				case N_ECOMM:
612597Sbill 				case N_LENG:
613632Shenry 					stpt->s_tag = STABFIXED;
614597Sbill 					break;
615597Sbill 				default:
616632Shenry 					stpt->s_tag = STABFLOATING;
617597Sbill 					break;
618597Sbill 			}
619597Sbill 		} else
620632Shenry 			stpt->s_tag = STABFIXED;
621597Sbill 	}
622597Sbill 	else {		/*really have a name*/
623632Shenry 		stpt->s_dest = locxp->e_xname;
624632Shenry 		stpt->s_index = p->s_index;
625632Shenry 		stpt->s_type = p->s_type | STABFLAG;
626597Sbill 		/*
627597Sbill 		 *	We will assign a more accruate
628597Sbill 		 *	guess of locxp's location when
629597Sbill 		 *	we sort the symbol table
630597Sbill 		 *	The final value of value is
631597Sbill 		 *	given by stabfix()
632597Sbill 		 */
633632Shenry 		stpt->s_tag = STABFLOATING;
634597Sbill 	}
635597Sbill 	/*
636597Sbill 	 *	tokptr now points at one token beyond
637597Sbill 	 *	the current token stored in val and yylval,
638597Sbill 	 *	which are the next tokens after the end of
639597Sbill 	 *	this .stab directive.  This next token must
640597Sbill 	 *	be either a SEMI or NL, so is of width just
641597Sbill 	 *	one.  Therefore, to point to the next token
642597Sbill 	 *	after the end of this stab, just back up one..
643597Sbill 	 */
644597Sbill 	buildskip(stabstart, (char *)tokptr - sizeof(toktype));
645597Sbill 	break;	/*end of the .stab*/
646597Sbill 
647597Sbill    case ISTABDOT:
648597Sbill 	stabname = ".stabd";
649597Sbill 	stpt = (struct symtab *)yylval;
650597Sbill 	/*
651597Sbill 	 *	We clobber everything after the
652597Sbill 	 *	.stabd and its pointer... we MUST
653597Sbill 	 *	be able to get back to this .stabd
654597Sbill 	 *	so that we can resolve its final value
655597Sbill 	 */
656597Sbill 	stabstart = tokptr;
657597Sbill 	shift;		/*over the ISTABDOT*/
658597Sbill 	if (passno == 1){
659597Sbill 		expr(locxp, val);
660632Shenry 		if (! (locxp->e_xvalue & STABTYPS)){
661597Sbill 			yyerror("Invalid type in .stabd");
662597Sbill 			goto errorfix;
663597Sbill 		}
664632Shenry 		stpt->s_ptype = locxp->e_xvalue;
665597Sbill 		shiftover(CM);
666597Sbill 		expr(locxp, val);
667632Shenry 		stpt->s_other = locxp->e_xvalue;
668597Sbill 		shiftover(CM);
669597Sbill 		expr(locxp, val);
670632Shenry 		stpt->s_desc = locxp->e_xvalue;
671597Sbill 		/*
672597Sbill 		 *
673597Sbill 		 *	Now, clobber everything but the
674597Sbill 		 *	.stabd pseudo and the pointer
675597Sbill 		 *	to its symbol table entry
676597Sbill 		 *	tokptr points to the next token,
677597Sbill 		 *	build the skip up to this
678597Sbill 		 */
679597Sbill 		buildskip(stabstart, (toktype *)tokptr - sizeof(toktype));
680597Sbill 	}
681597Sbill 	/*
682597Sbill 	 *	pass 1:	Assign a good guess for its position
683597Sbill 	 *		(ensures they are sorted into right place)/
684597Sbill 	 *	pass 2:	Fix the actual value
685597Sbill 	 */
686632Shenry 	stpt->s_value = dotp->e_xvalue;
687632Shenry 	stpt->s_index = dotp - usedot;
688632Shenry 	stpt->s_tag = STABFLOATING;	/*although it has no effect in pass 2*/
689597Sbill 	break;
690597Sbill 
691597Sbill    case ISTABNONE:	stabname = ".stabn"; goto shortstab;
692597Sbill 
693597Sbill    case ISTABSTR: 	stabname = ".stabs";
694597Sbill    shortstab:
695597Sbill 	auxval = val;
696597Sbill 	if (passno == 2) goto errorfix;
697597Sbill 	stpt = (struct symtab *)yylval;
698597Sbill 	stabstart = tokptr;
699597Sbill 	(char *)stabstart -= sizeof(struct symtab *);
700597Sbill 	(char *)stabstart -= sizeof(toktype);
701597Sbill 	shift;
702597Sbill 	if (auxval == ISTABSTR){
703597Sbill 		stringp = (struct strdesc *)yylval;
704597Sbill 		shiftover(STRING);
705597Sbill #ifndef FLEXNAMES
706597Sbill 		auxval = stringp->str_lg > NCPS ? NCPS : stringp->str_lg;
707597Sbill #else
708597Sbill 		stringp->str[stringp->str_lg] = 0;
709597Sbill #endif
710597Sbill 		shiftover(CM);
711597Sbill 	} else {
712597Sbill 		stringp = &(strbuf[2]);
713597Sbill #ifndef FLEXNAMES
714597Sbill 		auxval = NCPS;
715597Sbill #endif
716597Sbill 	}
717597Sbill #ifndef FLEXNAMES
718632Shenry 	movestr(stpt->s_name, stringp->str, auxval);
719597Sbill #else
720632Shenry 	stpt->s_name = savestr(stringp->str);
721597Sbill #endif
722597Sbill 	goto tailstab;
723597Sbill 	break;
724597Sbill 
725597Sbill    case ICOMM:	/* .comm  <name> , <expr> */
726597Sbill    case ILCOMM: 	/* .lcomm <name> , <expr> */
727597Sbill 	auxval = val;
728597Sbill 	shift;
729597Sbill 	np = (struct symtab *)yylval;
730597Sbill 	shiftover(NAME);
731597Sbill 	shiftover(CM);
732597Sbill 	expr(locxp, val);
733597Sbill 
734632Shenry 	if (locxp->e_xtype != XABS)
735597Sbill 		yyerror("comm size not absolute");
736632Shenry 	if (passno==1 && (np->s_type&XTYPE)!=XUNDEF)
737632Shenry #ifdef FLEXNAMES
738632Shenry 		yyerror("Redefinition of %s",
739632Shenry #else not FLEXNAMES
740632Shenry 		yyerror("Redefinition of %.*s",
741632Shenry 			NCPS,
742632Shenry #endif not FLEXNAMES
743632Shenry 			np->s_name);
744597Sbill 	if (passno==1) {
745632Shenry 		np->s_value = locxp->e_xvalue;
746597Sbill 		if (auxval == ICOMM)
747632Shenry 			np->s_type |= XXTRN;
748597Sbill 		else {
749632Shenry 			np->s_type &= ~XTYPE;
750632Shenry 			np->s_type |= XBSS;
751597Sbill 		}
752597Sbill 	}
753597Sbill 	break;
754597Sbill 
755597Sbill    case IALIGN: 		/* .align <expr> */
756597Sbill 	stpt = (struct symtab *)yylval;
757597Sbill 	shift;
758597Sbill 	expr(locxp, val);
759597Sbill 	jalign(locxp, stpt);
760597Sbill 	break;
761597Sbill 
762597Sbill    case INST0: 		/* instructions w/o arguments*/
763597Sbill 	insout(yylval, (struct arg *)0, 0);
764597Sbill 	shift;
765597Sbill 	break;
766597Sbill 
767597Sbill    case INSTn:		/* instructions with arguments*/
768597Sbill    case IJXXX: 		/* UNIX style jump instructions */
769597Sbill 	auxval = val;
770597Sbill 	seg_type = yylval;
771597Sbill 	/*
772597Sbill 	 *	Code to process an argument list
773597Sbill 	 */
774597Sbill 	ap = arglist;
775597Sbill 	xp = explist;
776597Sbill 
777597Sbill 	shift;		/* bring in the first token for the arg list*/
778597Sbill 
779597Sbill 	for (argcnt = 1; argcnt <= 6; argcnt++, ap++){
780597Sbill 		/*
781597Sbill 		 *	code to process an argument proper
782597Sbill 		 */
783597Sbill 	    sawindex  = sawmul = sawsize = 0;
784597Sbill 	    {
785597Sbill 		switch(val) {
786597Sbill 
787597Sbill 		   default:
788597Sbill 		     disp:
789597Sbill 			if( !(INTOKSET(val,
790597Sbill 				 EBEGOPS
791597Sbill 				+YUKKYEXPRBEG
792597Sbill 				+SAFEEXPRBEG)) ) {
793597Sbill 				ERROR("expression expected");
794597Sbill 			}
795632Shenry 			expr(ap->a_xp,val);
796597Sbill 		     overdisp:
797597Sbill 			if ( val == LP || sawsize){
798597Sbill 				shiftover(LP);
799597Sbill 				findreg(regno);
800597Sbill 				shiftover(RP);
801632Shenry 				ap->a_atype = ADISP;
802632Shenry 				ap->a_areg1 = regno;
803597Sbill 			} else {
804632Shenry 				ap->a_atype = AEXP;
805632Shenry 				ap->a_areg1 = 0;
806597Sbill 			}
807597Sbill 			goto index;
808597Sbill 
809597Sbill 		   case SIZESPEC:
810597Sbill 		     sizespec:
811597Sbill 			sawsize = yylval;
812597Sbill 			shift;
813597Sbill 			goto disp;
814597Sbill 
815597Sbill 		   case REG:
816597Sbill 		   case REGOP:
817597Sbill 			findreg(regno);
818632Shenry 			ap->a_atype = AREG;
819632Shenry 			ap->a_areg1 = regno;
820597Sbill 			break;
821597Sbill 
822597Sbill 		   case MUL:
823597Sbill 			sawmul = 1;
824597Sbill 			shift;
825597Sbill 			if (val == LP) goto base;
826597Sbill 			if (val == LITOP) goto imm;
827597Sbill 			if (val == SIZESPEC) goto sizespec;
828597Sbill 			if (INTOKSET(val,
829597Sbill 				 EBEGOPS
830597Sbill 				+YUKKYEXPRBEG
831597Sbill 				+SAFEEXPRBEG)) goto disp;
832597Sbill 			ERROR("expression, '(' or '$' expected");
833597Sbill 			break;
834597Sbill 
835597Sbill 		   case LP:
836597Sbill 		     base:
837597Sbill 			shift;	/*consume the LP*/
838597Sbill 			/*
839597Sbill 			 *	hack the ambiguity of
840597Sbill 			 *	movl (expr) (rn), ...
841597Sbill 			 *	note that (expr) could also
842597Sbill 			 *	be (rn) (by special hole in the
843597Sbill 			 *	grammar), which we ensure
844597Sbill 			 *	means register indirection, instead
845597Sbill 			 *	of an expression with value n
846597Sbill 			 */
847597Sbill 			if (val != REG && val != REGOP){
848597Sbill 				droppedLP = 1;
849632Shenry 				val = exprparse(val, &(ap->a_xp));
850597Sbill 				droppedLP = 0;
851597Sbill 				goto overdisp;
852597Sbill 			}
853597Sbill 			findreg(regno);
854597Sbill 			shiftover(RP);
855597Sbill 			if (val == PLUS){
856597Sbill 				shift;
857632Shenry 				ap->a_atype = AINCR;
858597Sbill 			} else
859632Shenry 				ap->a_atype = ABASE;
860632Shenry 			ap->a_areg1 = regno;
861597Sbill 			goto index;
862597Sbill 
863597Sbill 		   case LITOP:
864597Sbill 		      imm:
865597Sbill 			shift;
866597Sbill 			expr(locxp, val);
867632Shenry 			ap->a_atype = AIMM;
868632Shenry 			ap->a_areg1 = 0;
869632Shenry 			ap->a_xp = locxp;
870597Sbill 			goto index;
871597Sbill 
872597Sbill 		   case MP:
873597Sbill 			shift;	/* -(reg) */
874597Sbill 			findreg(regno);
875597Sbill 			shiftover(RP);
876632Shenry 			ap->a_atype = ADECR;
877632Shenry 			ap->a_areg1 = regno;
878597Sbill 	  index:			/*look for [reg] */
879597Sbill 			if (val == LB){
880597Sbill 				shift;
881597Sbill 				findreg(regno);
882597Sbill 				shiftover(RB);
883597Sbill 				sawindex = 1;
884632Shenry 				ap->a_areg2 = regno;
885597Sbill 			}
886597Sbill 			break;
887597Sbill 
888597Sbill 		}	/*end of the switch to process an arg*/
889597Sbill 	    }	/*end of processing an argument*/
890597Sbill 
891597Sbill 	    if (sawmul){
892597Sbill 			/*
893597Sbill 			 * Make a concession for *(%r)
894597Sbill 			 * meaning *0(%r)
895597Sbill 			 */
896632Shenry 			if (ap->a_atype == ABASE) {
897632Shenry 				ap->a_atype = ADISP;
898632Shenry 				xp->e_xtype = XABS;
899632Shenry 				xp->e_xvalue = 0;
900632Shenry 				xp->e_xloc = 0;
901632Shenry 				ap->a_xp = xp++;
902597Sbill 			}
903632Shenry 			ap->a_atype |= ASTAR;
904597Sbill 			sawmul = 0;
905597Sbill 	    }
906597Sbill 	    if (sawindex){
907632Shenry 		ap->a_atype |= AINDX;
908597Sbill 		sawindex = 0;
909597Sbill 	    }
910632Shenry 	    ap->a_dispsize = sawsize == 0 ? d124 : sawsize;
911597Sbill 		if (val != CM) break;
912597Sbill 		shiftover(CM);
913597Sbill 	}	/*processing all the arguments*/
914597Sbill 
915597Sbill 	if (argcnt > 6){
916597Sbill 		yyerror("More than 6 arguments");
917597Sbill 		goto errorfix;
918597Sbill 	}
919597Sbill 
920597Sbill 	insout(seg_type, arglist,
921597Sbill 		auxval == INSTn ? argcnt : - argcnt);
922597Sbill 	break;
923597Sbill 
924597Sbill    case IFLOAT:	curlen = 4;	goto floatlist;
925645Shenry    case IQUAD:
926597Sbill    case IDOUBLE:
927597Sbill 	curlen = 8;
928597Sbill       floatlist:
929597Sbill 	/*
930597Sbill 	 *	eat a list of floating point numbers
931597Sbill 	 */
932597Sbill 	shift;
933597Sbill 	if (val == FLTNUM){
934597Sbill 		/* KLS MOD */
935597Sbill 		float flocal;
936597Sbill 		do{
937597Sbill 			if (val == CM) shift;
938597Sbill 			if (val != FLTNUM) {
939597Sbill 			  ERROR("floating number expected");
940597Sbill 			}
941632Shenry 			dotp->e_xvalue += curlen;
942597Sbill #ifdef UNIX
943597Sbill 			if (passno == 2) {
944597Sbill 			  if(curlen == 8)
945597Sbill 			   bwrite((char *)&(((union Double *)yylval)->dvalue),
946597Sbill 				curlen, txtfil);
947597Sbill 			  else  {
948597Sbill 			   flocal = ((union Double *)yylval)->dvalue;
949597Sbill 			   bwrite((char *)&flocal, curlen, txtfil);
950597Sbill 			  }
951597Sbill 			}
952597Sbill #endif UNIX
953597Sbill 
954597Sbill #ifdef VMS
955597Sbill 			if (passno == 2) {
956597Sbill 			   puchar(vms_obj_ptr,-4);
957597Sbill 			   pulong(vms_obj_ptr,
958597Sbill 			    ((struct exp *)yylval)
959597Sbill 				->doub_MSW);
960597Sbill 			   if (curlen==8) {
961597Sbill 			    puchar(vms_obj_ptr,-4);
962597Sbill 			    pulong(vms_obj_ptr,
963597Sbill 			    ((struct exp *)yylval)
964597Sbill 				->doub_LSW);
965597Sbill 			   }
966597Sbill 			   if((vms_obj_ptr-sobuf) > 400) {
967597Sbill 			    write(objfil,sobuf,vms_obj_ptr-sobuf);
968597Sbill 			    vms_obj_ptr = sobuf + 1;
969597Sbill 			   }
970597Sbill 			}
971597Sbill #endif VMS
972597Sbill 			shift;
973597Sbill 			xp = explist;
974597Sbill 		} while (val == CM);
975597Sbill 	}
976597Sbill 	break;
977597Sbill     }	/*end of the switch for looking at each reserved word*/
978597Sbill 
979597Sbill      continue;
980597Sbill 
981597Sbill    errorfix:
982597Sbill 	/*
983597Sbill 	 *	got here by either requesting to skip to the
984597Sbill 	 *	end of this statement, or by erroring out and
985597Sbill 	 *	wanting to apply panic mode recovery
986597Sbill 	 */
987597Sbill 	while (    (val != NL)
988597Sbill 		&& (val != SEMI)
989597Sbill 		&& (val != PARSEEOF)
990597Sbill 	      ){
991597Sbill 		shift;
992597Sbill 	}
993597Sbill 	if (val == NL)
994597Sbill 		lineno++;
995597Sbill 	shift;
996597Sbill 
997597Sbill     }	/*end of the loop to read the entire file, line by line*/
998597Sbill 
999597Sbill }	/*end of yyparse*/
1000597Sbill 
1001597Sbill /*
1002597Sbill  *	Process a register declaration of the form
1003597Sbill  *	% <expr>
1004597Sbill  *
1005597Sbill  *	Note:
1006597Sbill  *		The scanner has already processed funny registers of the form
1007597Sbill  *	%dd[+-]*, where dd is a decimal number in the range 00 to 15 (optional
1008597Sbill  *	preceding zero digit).  If there was any space between the % and
1009597Sbill  *	the digit, the scanner wouldn't have recognized it, so we
1010597Sbill  *	hack it out here.
1011597Sbill  */
1012597Sbill int funnyreg(val, regnoback)		/*what the read head will sit on*/
1013597Sbill 	int	val;			/*what the read head is sitting on*/
1014597Sbill 	int	*regnoback;		/*call by return*/
1015597Sbill {
1016597Sbill 	register	struct	exp *locxp;
1017597Sbill 			struct	exp *loc1xp;
1018597Sbill 			struct	exp **ptrloc1xp = & loc1xp;
1019597Sbill 
1020597Sbill 	expr(locxp, val);	/*and leave the current read head with value*/
1021597Sbill 	if ( (passno == 2) &&
1022632Shenry 	    (   locxp->e_xtype & XTYPE != XABS
1023632Shenry 	     || locxp->e_xvalue < 0
1024632Shenry 	     || locxp->e_xvalue >= 16
1025597Sbill 	    )
1026597Sbill 	  ){
1027597Sbill 		yyerror("Illegal register");
1028597Sbill 		return(0);
1029597Sbill 	}
1030632Shenry 	*regnoback = locxp->e_xvalue;
1031597Sbill 	return(val);
1032597Sbill }
1033597Sbill 
1034597Sbill /*VARARGS1*/
1035597Sbill yyerror(s, a1, a2,a3,a4,a5)
1036597Sbill 	char	*s;
1037597Sbill {
1038597Sbill 	FILE		*sink;
1039597Sbill 
1040597Sbill #ifdef DEBUG
1041597Sbill 	sink = stdout;
1042597Sbill #else not DEBUG
1043597Sbill 	sink = stderr;
1044597Sbill #endif DEBUG
1045597Sbill 
1046597Sbill 	if (anyerrs == 0 && ! silent)
1047597Sbill 		fprintf(sink, "Assembler:\n");
1048597Sbill 	anyerrs++;
1049597Sbill 	if (silent) return;
1050597Sbill 
1051597Sbill 	fprintf(sink, "\"%s\", line %d: ", dotsname, lineno);
1052597Sbill 	fprintf(sink, s, a1, a2,a3,a4,a5);
1053597Sbill 	fprintf(sink, "\n");
1054597Sbill }
1055