xref: /original-bsd/old/as.tahoe/asparse.c (revision f1656be1)
1 /*
2  *	Copyright (c) 1982 Regents of the University of California
3  */
4 #ifndef lint
5 static char sccsid[] = "$W$ (Berkeley) 05/31/88";
6 #endif not lint
7 
8 #include <stdio.h>
9 #include "as.h"
10 #include "asscan.h"
11 #include "assyms.h"
12 #include "asexpr.h"
13 
14 int	lgensym[10];
15 char	genref[10];
16 
17 long	bitfield;
18 int	bitoff;
19 int	curlen;			/* current length of literals */
20 int	printblank;
21 
22 /*
23  *	The following three variables are communication between various
24  *	modules to special case a number of things.  They are properly
25  *	categorized as hacks.
26  */
27 extern	struct	symtab *lastnam;/*last name seen by the lexical analyzer*/
28 int	exprisname;		/*last factor in an expression was a name*/
29 int	droppedLP;		/*one is analyzing an expression beginning with*/
30 				/*a left parenthesis, which has already been*/
31 				/*shifted. (Used to parse (<expr>)(rn)*/
32 
33 char	yytext[NCPName+2];	/*the lexical image*/
34 int	yylval;			/*the lexical value; sloppy typing*/
35 u_char	yyopcode;		/* lexical value for an opcode */
36 Bignum	yybignum;		/* lexical value for a big number */
37 int	num_type;		/* type of bignums */
38 /*
39  *	Expression and argument managers
40  */
41 struct	exp	*xp;		/*next free expression slot, used by expr.c*/
42 struct	exp	explist[NEXP];	/*max of 20 expressions in one opcode*/
43 struct	arg	arglist[NARG];	/*building up operands in instructions*/
44 /*
45  *	Sets to accelerate token discrimination
46  */
47 char	tokensets[(LASTTOKEN) - (FIRSTTOKEN) + 1];
48 
49 static	char	UDotsname[64];	/*name of the assembly source*/
50 
51 yyparse()
52 {
53 	reg	struct	exp	*locxp;
54 		/*
55 		 *	loc1xp and ptrloc1xp are used in the
56 		 * 	expression lookahead
57 		 */
58 		struct	exp	*loc1xp;	/*must be non register*/
59 		struct	exp	**ptrloc1xp = & loc1xp;
60 		struct	exp	*pval;		/*hacking expr:expr*/
61 
62 	reg	struct	symtab	*np;
63 	reg	int		argcnt;
64 
65 	reg	inttoktype	val;		/*what yylex gives*/
66 	reg	inttoktype	auxval;		/*saves val*/
67 
68 	reg	struct 	arg	*ap;		/*first free argument*/
69 
70 	reg	struct	symtab	*p;
71 	reg	struct	symtab	*stpt;
72 
73 		struct	strdesc *stringp;	/*handles string lists*/
74 
75 		int	regno;		/*handles arguments*/
76 		int	*ptrregno = &regno;
77 		int	sawmul;		/*saw * */
78 		int	sawindex;	/*saw [rn]*/
79 		int	sawsize;
80 		int	seg_type; 	/*the kind of segment: data or text*/
81 		int	seg_number;	/*the segment number*/
82 		int	space_value;	/*how much .space needs*/
83 		int	fill_rep;	/*how many reps for .fill */
84 		int	rep_fill;	/*the same - temprary */
85 		int	fill_size;	/*how many bytes for .fill */
86 
87 		int	field_width;	/*how wide a field is to be*/
88 		int	field_value;	/*the value to stuff in a field*/
89 		char	*stabname;	/*name of stab dealing with*/
90 		ptrall	stabstart;	/*where the stab starts in the buffer*/
91 		int	reloc_how;	/* how to relocate expressions */
92 		int	incasetable;	/* set if in a case table */
93 		int 	j, k;
94 		char	ch;
95 		int	length;		/* for printout */
96 	union twolong
97 	{
98 		long lpart[2];
99 		char strpart [8];
100 	}fillval;
101 
102 
103 	incasetable = 0;
104 	xp = explist;
105 	ap = arglist;
106 
107 	val = yylex();
108 
109     while (val != PARSEEOF){	/* primary loop */
110 
111 	while (INTOKSET(val, LINSTBEGIN)){
112 		if (val == INT) {
113 			int i = ((struct exp *)yylval)->e_xvalue;
114 			shift;
115 			if (val != COLON){
116 				yyerror("Local label %d is not followed by a ':' for a label definition",
117 					i);
118 				goto  errorfix;
119 			}
120 			if (i < 0 || i > 9) {
121 				yyerror("Local labels are 0-9");
122 				goto errorfix;
123 			}
124 			(void)sprintf(yytext, "L%d\001%d", i, lgensym[i]);
125 			lgensym[i]++;
126 			genref[i] = 0;
127 			yylval = (int)*lookup(passno == 1);
128 			val = NAME;
129 			np = (struct symtab *)yylval;
130 			goto restlab;
131 		}
132 		if (val == NL){
133 			lineno++;
134 			if (liston && (passno == 2) && (! endofsource))
135 			{
136 				/* printing previous line & layout */
137 				length = strlen (layout);
138 				fprintf (listfile, "%*.*s", LHEAD, LHEAD, layout);
139 				if (length <= LHEAD+LLEN)
140 					j = LLEN;
141 				else {	/* break line at last blank */
142 					j = LHEAD+LLEN;
143 					while(j>LHEAD && layout[j]!= ' ')
144 						j--;
145 					if(j == LHEAD)
146 						j = LLEN;
147 					else
148 						j -= LHEAD;
149 				}
150 				k = LHEAD+j;
151 				fprintf (listfile, "%-*.*s", LLEN, j, &layout[LHEAD]);
152 				fprintf (listfile, "     ");
153 				do {
154 					ch = getc (source);
155 					putc (ch, listfile);
156 				} while (ch != '\n');
157 				while (k < length)
158 				{
159 					fprintf (listfile, "%*s", LHEAD, "");
160 					/* break line at last blank */
161 					if(layout[k] == ' ')
162 						k++;
163 					if((j = k+LLEN) >= length)
164 						j = length;
165 					else
166 						while(j>k && layout[j]!= ' ')
167 							j--;
168 					if(j == k)
169 						j = LLEN;
170 					else
171 						j -= k;
172 					fprintf (listfile, "%-*.*s\n", j, j, &layout[k]);
173 					k += j;
174 				}
175 				k = 0;
176 				while (layout[k] != '\0')
177 					layout[k++] = '\0';
178 				ch = getc (source);
179 				if (ch == EOF)
180 				{
181 					if (ind == ninfiles)
182 						endofsource = 1;
183 					else
184 					{
185 						source = fopen (innames[ind++], "r");
186 						lineno = 1;
187 					}
188 				}
189 				else
190 					ungetc (ch, source);
191 				layoutpos = layout;
192 				(void)sprintf (layoutpos, "%4ld  ", lineno);
193 				layoutpos += 6;
194 				long_out (dotp->e_xvalue);
195 				if (dotp->e_xvalue >= datbase)
196 					(void)sprintf (layoutpos," *  ");
197 				else
198 					(void)sprintf (layoutpos,"    ");
199 				layoutpos += 4;
200 			}
201 			shift;
202 		} else
203 		if (val == SEMI)
204 			shift;
205 		else {	/*its a name, so we have a label or def */
206 			if (val != NAME){
207 				ERROR("Name expected for a label");
208 			}
209 			np = (struct symtab *)yylval;
210 			shiftover(NAME);
211 			if (val != COLON) {
212 				yyerror("\"%s\" is not followed by a ':' for a label definition",
213 					FETCHNAME(np));
214 				goto  errorfix;
215 			}
216 restlab:
217 			shift;
218 			flushfield(NBPW/4);
219 			if ((np->s_type&XTYPE)!=XUNDEF) {
220 				if(  (np->s_type&XTYPE)!=dotp->e_xtype
221 				   || np->s_value!=dotp->e_xvalue
222 				   || (  (passno==1)
223 				       &&(np->s_index != dotp->e_xloc)
224 				      )
225 				  ){
226 #ifndef DEBUG
227 					if (FETCHNAME(np)[0] != 'L')
228 #endif not DEBUG
229 					{
230 						if (passno == 1)
231 						  yyerror("%s redefined",
232 							FETCHNAME(np));
233 						else
234 						  yyerror("%s redefined: PHASE ERROR, 1st: %d, 2nd: %d",
235 							FETCHNAME(np),
236 							np->s_value,
237 							dotp->e_xvalue);
238 					}
239 				}
240 			}
241 			np->s_type &= ~(XTYPE|XFORW);
242 			np->s_type |= dotp->e_xtype;
243 			np->s_value = dotp->e_xvalue;
244 			if (passno == 1){
245 				np->s_index = dotp-usedot;
246 				if (FETCHNAME(np)[0] == 'L'){
247 					nlabels++;
248 				}
249 				np->s_tag = LABELID;
250 			}
251 		}	/*end of this being a label*/
252 	}	/*end of to consuming all labels, NLs and SEMIS */
253 
254 	xp = explist;
255 	ap = arglist;
256 
257 	/*
258 	 *	process the INSTRUCTION body
259 	 */
260 	switch(val){
261 
262     default:
263 	ERROR("Unrecognized instruction or directive");
264 
265    case IABORT:
266 	shift;
267 	sawabort();
268 	/*NOTREACHED*/
269 	break;
270 
271    case PARSEEOF:
272 	tokptr -= sizeof(bytetoktype);
273 	*tokptr++ = VOID;
274 	tokptr[1] = VOID;
275 	tokptr[2] = PARSEEOF;
276 	break;
277 
278    case IFILE:
279 	shift;
280 	stringp = (struct strdesc *)yylval;
281 	shiftover(STRING);
282 	dotsname = &UDotsname[0];
283 	movestr(dotsname, stringp->sd_string,
284 		min(stringp->sd_strlen, sizeof(UDotsname)));
285 	break;
286 
287    case ILINENO:
288 	shift;		/*over the ILINENO*/
289 	expr(locxp, val);
290 	lineno = locxp->e_xvalue;
291 	break;
292 
293    case ISET: 	/* .set  <name> , <expr> */
294 	shift;
295 	np = (struct symtab *)yylval;
296 	shiftover(NAME);
297 	shiftover(CM);
298 	expr(locxp, val);
299 	np->s_type &= (XXTRN|XFORW);
300 	np->s_type |= locxp->e_xtype&(XTYPE|XFORW);
301 	np->s_value = locxp->e_xvalue;
302 	if (passno==1)
303 		np->s_index = locxp->e_xloc;
304 	if ((locxp->e_xtype&XTYPE) == XUNDEF)
305 		yyerror("Illegal set?");
306 	break;
307 
308    case ILSYM: 	/*.lsym name , expr */
309 	shift;
310 	np = (struct symtab *)yylval;
311 	shiftover(NAME);
312 	shiftover(CM);
313 	expr(locxp, val);
314 	/*
315 	 *	Build the unique occurance of the
316 	 *	symbol.
317 	 *	The character scanner will have
318 	 *	already entered it into the symbol
319 	 *	table, but we should remove it
320 	 */
321 	if (passno == 1){
322 		stpt = (struct symtab *)symalloc();
323 		stpt->s_name = np->s_name;
324 		np->s_tag = OBSOLETE;	/*invalidate original */
325 		nforgotten++;
326 		np = stpt;
327 		if ( (locxp->e_xtype & XTYPE) != XABS)
328 			yyerror("Illegal second argument to lsym");
329 		np->s_value = locxp->e_xvalue;
330 		np->s_type = XABS;
331 		np->s_tag = ILSYM;
332 	}
333 	break;
334 
335    case IGLOBAL: 	/*.globl <name> */
336 	shift;
337 	np = (struct symtab *)yylval;
338 	shiftover(NAME);
339 	np->s_type |= XXTRN;
340 	break;
341 
342    case IDATA: 	/*.data [ <expr> ] */
343    case ITEXT: 	/*.text [ <expr> ] */
344 	incasetable = 0;
345 	seg_type = -val;
346 	shift;
347 	if (INTOKSET(val, EBEGOPS+YUKKYEXPRBEG+SAFEEXPRBEG)){
348 		expr(locxp, val);
349 		seg_type = -seg_type;   /*now, it is positive*/
350 	}
351 
352 	if (seg_type < 0) {	/*there wasn't an associated expr*/
353 		seg_number = 0;
354 		seg_type = -seg_type;
355 	} else {
356 		if (   ((locxp->e_xtype & XTYPE) != XABS)	/* tekmdp */
357 		    || (seg_number = locxp->e_xvalue) >= NLOC) {
358 			yyerror("illegal location counter");
359 			seg_number = 0;
360 		}
361 	}
362 	if (seg_type == IDATA)
363 		seg_number += NLOC;
364 	flushfield(NBPW/4);
365 	dotp = &usedot[seg_number];
366 	if (passno==2) {	/* go salt away in pass 2*/
367 		txtfil = usefile[seg_number];
368 		relfil = rusefile[seg_number];
369 	}
370 	break;
371 
372 	/*
373 	 *	Storage filler directives:
374 	 *
375 	 *	.byte	[<exprlist>]
376 	 *
377 	 *	exprlist:  empty | exprlist outexpr
378 	 *	outexpr:   <expr> | <expr> : <expr>
379 	 */
380    case IBYTE:	curlen = NBPW/4; goto elist;
381    case IWORD:	curlen = NBPW/2; goto elist;
382    case IINT:	curlen = NBPW;   goto elist;
383    case ILONG:	curlen = NBPW;   goto elist;
384 
385    elist:
386 	seg_type = val;
387 	shift;
388 
389 	/*
390 	 *	Expression List processing
391 	 */
392 	if (INTOKSET(val, EBEGOPS+YUKKYEXPRBEG+SAFEEXPRBEG)){
393 	    do{
394 		/*
395 		 *	expression list consists of a list of :
396 		 *	<expr>
397 		 *	<expr> : <expr>
398 		 *		(pack expr2 into expr1 bits
399 		 */
400 		expr(locxp, val);
401 		/*
402 		 *	now, pointing at the next token
403 		 */
404 		/* if (val == COLON){ */
405 		/* 	shiftover(COLON); */
406 		/* 	expr(pval, val); */
407 		/* 	if ((locxp->e_xtype & XTYPE) != XABS)  */
408 		/* 		yyerror("Width not absolute"); */
409 		/* 	field_width = locxp->e_xvalue; */
410 		/* 	locxp = pval; */
411 		/* 	if (bitoff + field_width > curlen) */
412 		/* 		flushfield(curlen); */
413 		/* 	if (field_width > curlen) */
414 		/* 		yyerror("Expression crosses field boundary"); */
415 		/* } else { */
416 			field_width = curlen;
417 			if (bitoff == 0)	printblank = 0;
418 			else			printblank = 1;
419 			flushfield(curlen);
420 			if (liston && (passno == 2) && printblank)
421 				*layoutpos++ = ' ';
422 		/* } */
423 
424 		if ((locxp->e_xtype & XTYPE) != XABS) {
425 			if (bitoff)
426 				yyerror("Illegal relocation in field");
427 			switch(curlen){
428 				case NBPW/4:	reloc_how = TYPB; break;
429 				case NBPW/2:	reloc_how = TYPW; break;
430 				case NBPW:	reloc_how = TYPL; break;
431 			}
432 			if (passno == 1){
433 				dotp->e_xvalue += ty_nbyte[reloc_how];
434 			} else {
435 				outrel(locxp, reloc_how);
436 				if (liston)
437 					*layoutpos++ = ' ';
438 			}
439 		} else {
440 			/*
441 			 *
442 			 *	See if we are doing a case instruction.
443 			 *	If so, then see if the branch distance,
444 			 *	stored as a word,
445 			 *	is going to loose sig bits.
446 			 */
447 			if (passno == 2 && incasetable){
448 				if (  !(ISWORD(locxp->e_xvalue)))
449 					yyerror("Case will branch too far");
450 			}
451 			field_value = locxp->e_xvalue & ( (1L << field_width)-1);
452 			bitfield |= field_value << bitoff;
453 			bitoff += field_width;
454 		}
455 		xp = explist;
456 		if (auxval = (val == CM))
457 			shift;
458 	    } while (auxval);
459 	}	/* there existed an expression at all */
460 
461 	flushfield(curlen);
462 	if ( ( curlen == NBPW/4) && bitoff)
463 		dotp->e_xvalue ++;
464 	break;
465 	/*end of case IBYTE, IWORD, ILONG, IINT*/
466 
467    case ISPACE: 	/* .space <expr> */
468 	shift;
469 	expr(locxp, val);
470 	if ((locxp->e_xtype & XTYPE) != XABS)	/* tekmdp */
471 		yyerror("Space size not absolute");
472 	if (locxp->e_xvalue < 0)
473 		yyerror("Space size not positive");
474 	space_value = locxp->e_xvalue;
475   ospace:
476 	flushfield(NBPW/4);
477 	{
478 		static char spacebuf[128];
479 		while (space_value > sizeof(spacebuf)){
480 			outs(spacebuf, sizeof(spacebuf));
481 			space_value -= sizeof(spacebuf);
482 		}
483 		outs(spacebuf, space_value);
484 	}
485 	if (liston && (passno == 2))
486 		(void)sprintf (layoutpos, "****");
487 	break;
488 
489 	/*
490 	 *	.fill rep, size, value
491 	 *	repeat rep times: fill size bytes with (truncated) value
492 	 *	size must be between 1 and 8
493 	 */
494    case	IFILL:
495 	shift;
496 	expr(locxp, val);
497 	if ( (locxp->e_xtype & XTYPE) != XABS)	/* tekmdp */
498 		yyerror("Fill repetition count not absolute");
499 	rep_fill = fill_rep = locxp->e_xvalue;
500 	shiftover(CM);
501 	expr(locxp, val);
502 	if ( (locxp->e_xtype & XTYPE) != XABS)	/* tekmdp */
503 		yyerror("Fill size not absolute");
504 	fill_size = locxp->e_xvalue;
505 	if (fill_size <= 0 || fill_size > 8)
506 		yyerror("Fill count not in in 1..8");
507 	shiftover(CM);
508 	expr(locxp, val);
509 	if (passno == 2 && (locxp->e_xtype & XTYPE) != XABS)	/* tekmdp */
510 		yyerror("Fill value not absolute");
511 	flushfield(NBPW/4);
512 	dotp->e_xvalue += fill_rep * fill_size;
513 	if (passno == 1) {
514 		locxp->e_xvalue += fill_rep * fill_size;
515 	} else {
516 		fillval.lpart[0] = locxp->e_yvalue;
517 		fillval.lpart[1] = locxp->e_xvalue;
518 		while (fill_rep-- > 0)
519 			bwrite(&(fillval.strpart[8-fill_size]),fill_size,txtfil);
520 		if (liston) {
521 		   while (rep_fill--  > 0)
522 		   {
523 			switch (fill_size)
524 			{
525 				case 1:
526 					byte_out (locxp->e_xvalue);
527 					*layoutpos++ = ' ';
528 					break;
529 				case 2:
530 					word_out (locxp->e_xvalue);
531 					*layoutpos++ = ' ';
532 					break;
533 				case 3:
534 					byte_out (locxp->e_xvalue >> 16);
535 					byte_out (locxp->e_xvalue >>  8);
536 					byte_out (locxp->e_xvalue);
537 					*layoutpos++ = ' ';
538 					break;
539 				case 4:
540 					long_out (locxp->e_xvalue);
541 					*layoutpos++ = ' ';
542 					break;
543 				case 5:
544 					byte_out (locxp->e_yvalue);
545 					long_out (locxp->e_xvalue);
546 					*layoutpos++ = ' ';
547 					break;
548 				case 6:
549 					word_out (locxp->e_yvalue);
550 					long_out (locxp->e_xvalue);
551 					*layoutpos++ = ' ';
552 					break;
553 				case 7:
554 					byte_out (locxp->e_yvalue >> 16);
555 					byte_out (locxp->e_yvalue >>  8);
556 					byte_out (locxp->e_yvalue);
557 					long_out (locxp->e_xvalue);
558 					*layoutpos++ = ' ';
559 					break;
560 				case 8:
561 					long_out (locxp->e_yvalue);
562 					long_out (locxp->e_xvalue);
563 					*layoutpos++ = ' ';
564 					break;
565 				}
566 			    }
567 		}
568 	}
569 	break;
570 
571    case IASCII:		/* .ascii [ <stringlist> ] */
572    case IASCIZ: 	/* .asciz [ <stringlist> ] */
573 	auxval = val;
574 	shift;
575 	/*
576 	 *	Code to consume a string list
577 	 *
578 	 *	stringlist: empty | STRING | stringlist STRING
579 	 */
580 	while (val == STRING){
581 		int	mystrlen;
582 		flushfield(NBPW/4);
583 		if (bitoff)
584 			dotp->e_xvalue++;
585 		stringp = (struct strdesc *)yylval;
586 		/*
587 		 *	utilize the string scanner cheat;
588 		 *	the scanner appended a null byte on the string,
589 		 *	but didn't charge it to sd_strlen
590 		 */
591 		mystrlen = stringp->sd_strlen;
592 		mystrlen += (auxval == IASCIZ) ? 1 : 0;
593 		if (passno == 2){
594 			if (stringp->sd_place & STR_CORE){
595 				outs(stringp->sd_string, mystrlen);
596 				if (liston)
597 				{
598 					int i;
599 					for (i = 0;i < mystrlen; i++)
600 					{
601 						(void)sprintf (layoutpos, "%02x",
602 						stringp->sd_string[i]);
603 						layoutpos += 2;
604 					}
605 				}
606 			} else {
607 				int	i, nread;
608 				fseek(strfile, stringp->sd_stroff, 0);
609 				for (i = 0; i < mystrlen;/*VOID*/){
610 					nread = fread(yytext, 1,
611 						min(mystrlen - i,
612 						  sizeof(yytext)), strfile);
613 					outs(yytext, nread);
614 					if (liston)
615 					{
616 						int k;
617 						for (k = 0;k < nread; k++)
618 						{
619 							(void)sprintf (layoutpos,
620 							 "%02x", yytext[k]);
621 							layoutpos += 2;
622 						}
623 					}
624 					i += nread;
625 				}
626 			}
627 		} else {
628 			dotp->e_xvalue += mystrlen;
629 		}
630 		shift;		/*over the STRING*/
631 		if (val == CM)	/*could be a split string*/
632 			shift;
633 	}
634 	break;
635 
636    case IORG: 	/* .org <expr> */
637 	shift;
638 	expr(locxp, val);
639 
640 	if ((locxp->e_xtype & XTYPE) == XABS)	/* tekmdp */
641 		orgwarn++;
642 	else if ((locxp->e_xtype & ~XXTRN) != dotp->e_xtype)
643 		yyerror("Illegal expression to set origin");
644 	if ((unsigned)locxp->e_xvalue < (unsigned)dotp->e_xvalue)
645 	{
646 		ERROR("Backwards 'org'");
647 	}
648 	space_value = locxp->e_xvalue - dotp->e_xvalue;
649 	goto ospace;
650 	break;
651 
652 /*
653  *
654  *	Process stabs.  Stabs are created only by the f77
655  *	and the C compiler with the -g flag set.
656  *	We only look at the stab ONCE, during pass 1, and
657  *	virtually remove the stab from the intermediate file
658  *	so it isn't seen during pass2.  This makes for some
659  *	hairy processing to handle labels occuring in
660  *	stab entries, but since most expressions in the
661  *	stab are integral we save lots of time in the second
662  *	pass by not looking at the stabs.
663  *	A stab that is tagged floating will be bumped during
664  *	the jxxx resolution phase.  A stab tagged fixed will
665  *	not be be bumped.
666  *
667  *	.stab:	Old fashioned stabs
668  *	.stabn: For stabs without names
669  *	.stabs:	For stabs with string names
670  *	.stabd: For stabs for line numbers or bracketing,
671  *		without a string name, without
672  *		a final expression.  The value of the
673  *		final expression is taken to be  the current
674  *		location counter, and is patched by the 2nd pass
675  *
676  *	.stab{<expr>,}*NCPName,<expr>, <expr>, <expr>, <expr>
677  *	.stabn		 <expr>, <expr>, <expr>, <expr>
678  *	.stabs   STRING, <expr>, <expr>, <expr>, <expr>
679  *	.stabd		 <expr>, <expr>, <expr> # .
680  */
681    case ISTAB:
682 	yyerror(".stab directive no longer supported");
683 	goto errorfix;
684 
685   tailstab:
686 	expr(locxp, val);
687 	if (! (locxp->e_xvalue & STABTYPS)){
688 		yyerror("Invalid type in %s", stabname);
689 		goto errorfix;
690 	}
691 	stpt->s_ptype = locxp->e_xvalue;
692 	shiftover(CM);
693 	expr(locxp, val);
694 	stpt->s_other = locxp->e_xvalue;
695 	shiftover(CM);
696 	expr(locxp, val);
697 	stpt->s_desc = locxp->e_xvalue;
698 	shiftover(CM);
699 	exprisname = 0;
700 	expr(locxp, val);
701 	p = locxp->e_xname;
702 	if (p == NULL) {	/*absolute expr to begin with*/
703 		stpt->s_value = locxp->e_xvalue;
704 		stpt->s_index = dotp - usedot;
705 		if (exprisname){
706 			stpt->s_type = locxp->e_xtype;
707 			switch(stpt->s_ptype){
708 				case N_LCSYM:
709 					stpt->s_dest = (struct symtab *)exprisname;
710 					stpt->s_type |= STABFLAG;
711 				case N_GSYM:
712 				case N_FNAME:
713 				case N_RSYM:
714 				case N_SSYM:
715 				case N_LSYM:
716 				case N_PSYM:
717 				case N_BCOMM:
718 				case N_ECOMM:
719 				case N_LENG:
720 					stpt->s_tag = STABFIXED;
721 					break;
722 				default:
723 					stpt->s_tag = STABFLOATING;
724 					break;
725 			}
726 		} else
727 			stpt->s_tag = STABFIXED;
728 	}
729 	else {		/*really have a name*/
730 		stpt->s_dest = locxp->e_xname;
731 		stpt->s_index = p->s_index;
732 		stpt->s_type = p->s_type | STABFLAG;
733 		/*
734 		 *	We will assign a more accruate
735 		 *	guess of locxp's location when
736 		 *	we sort the symbol table
737 		 *	The final value of value is
738 		 *	given by stabfix()
739 		 */
740 /*
741  * For exprs of the form (name + value) one needs to remember locxp->e_xvalue
742  * for use in stabfix. The right place to keep this is in stpt->s_value
743  * however this gets corrupted at an unknown point.
744  * As a bandaid hack the value is preserved in s_desc and s_other (a
745  * short and a char). This destroys these two values and will
746  * be fixed. May 19 ,1983 Alastair Fyfe
747  */
748 		if(locxp->e_xvalue) {
749 			stpt->s_other = (locxp->e_xvalue >> 16);
750 			stpt->s_desc =  (locxp->e_xvalue  & 0x0000ffff);
751 			stpt->s_tag = STABFLOATING;
752 		}
753 	}
754 	/*
755 	 *	tokptr now points at one token beyond
756 	 *	the current token stored in val and yylval,
757 	 *	which are the next tokens after the end of
758 	 *	this .stab directive.  This next token must
759 	 *	be either a SEMI or NL, so is of width just
760 	 *	one.  Therefore, to point to the next token
761 	 *	after the end of this stab, just back up one..
762 	 */
763 	buildskip(stabstart, (bytetoktype *)tokptr - sizeof(bytetoktype));
764 	break;	/*end of the .stab*/
765 
766    case ISTABDOT:
767 	stabname = ".stabd";
768 	stpt = (struct symtab *)yylval;
769 	/*
770 	 *	We clobber everything after the
771 	 *	.stabd and its pointer... we MUST
772 	 *	be able to get back to this .stabd
773 	 *	so that we can resolve its final value
774 	 */
775 	stabstart = tokptr;
776 	shift;		/*over the ISTABDOT*/
777 	if (passno == 1){
778 		expr(locxp, val);
779 		if (! (locxp->e_xvalue & STABTYPS)){
780 			yyerror("Invalid type in .stabd");
781 			goto errorfix;
782 		}
783 		stpt->s_ptype = locxp->e_xvalue;
784 		shiftover(CM);
785 		expr(locxp, val);
786 		stpt->s_other = locxp->e_xvalue;
787 		shiftover(CM);
788 		expr(locxp, val);
789 		stpt->s_desc = locxp->e_xvalue;
790 		/*
791 		 *
792 		 *	Now, clobber everything but the
793 		 *	.stabd pseudo and the pointer
794 		 *	to its symbol table entry
795 		 *	tokptr points to the next token,
796 		 *	build the skip up to this
797 		 */
798 		buildskip(stabstart, (bytetoktype *)tokptr - sizeof(bytetoktype));
799 	}
800 	/*
801 	 *	pass 1:	Assign a good guess for its position
802 	 *		(ensures they are sorted into right place)/
803 	 *	pass 2:	Fix the actual value
804 	 */
805 	stpt->s_value = dotp->e_xvalue;
806 	stpt->s_index = dotp - usedot;
807 	stpt->s_tag = STABFLOATING;	/*although it has no effect in pass 2*/
808 	break;
809 
810    case ISTABNONE:	stabname = ".stabn"; goto shortstab;
811 
812    case ISTABSTR: 	stabname = ".stabs";
813    shortstab:
814 	auxval = val;
815 	if (passno == 2) goto errorfix;
816 	stpt = (struct symtab *)yylval;
817 	stabstart = tokptr;
818 	(bytetoktype *)stabstart -= sizeof(struct symtab *);
819 	(bytetoktype *)stabstart -= sizeof(bytetoktype);
820 	shift;
821 	if (auxval == ISTABSTR){
822 		stringp = (struct strdesc *)yylval;
823 		shiftover(STRING);
824 		stpt->s_name = (char *)stringp;
825 		/*
826 		 *	We want the trailing null included in this string.
827 		 *	We utilize the cheat the string scanner used,
828 		 *	and merely increment the string length
829 		 */
830 		stringp->sd_strlen += 1;
831 		shiftover(CM);
832 	} else {
833 		stpt->s_name = (char *)savestr("\0", 0, STR_BOTH);
834 	}
835 	goto tailstab;
836 	break;
837 
838    case ICOMM:		/* .comm  <name> , <expr> */
839    case ILCOMM: 	/* .lcomm <name> , <expr> */
840 	auxval = val;
841 	shift;
842 	np = (struct symtab *)yylval;
843 	shiftover(NAME);
844 	shiftover(CM);
845 	expr(locxp, val);
846 
847 	if ( (locxp->e_xtype & XTYPE) != XABS)	/* tekmdp */
848 		yyerror("comm size not absolute");
849 	if (passno == 1 && (np->s_type&XTYPE) != XUNDEF)
850 		yyerror("Redefinition of %s", FETCHNAME(np));
851 	if (passno==1) {
852 		np->s_value = locxp->e_xvalue;
853 		if (auxval == ICOMM)
854 			np->s_type |= XXTRN;
855 		else {
856 			np->s_type &= ~XTYPE;
857 			np->s_type |= XBSS;
858 		}
859 	}
860 	break;
861 
862    case IALIGN: 		/* .align <expr> */
863 	stpt = (struct symtab *)yylval;
864 	shift;
865 	expr(locxp, val);
866 	if ((dotp->e_xtype & XTYPE) == XDATA)
867 		djalign(locxp, stpt);
868 	else
869 		jalign(locxp, stpt);
870 	break;
871 
872    case INST0: 		/* instructions w/o arguments*/
873 	incasetable = 0;
874 	insout(yyopcode, (struct arg *)0, 0);
875 	shift;
876 	break;
877 
878    case INSTn:		/* instructions with arguments*/
879    case IJXXX: 		/* UNIX style jump instructions */
880 	auxval = val;
881 	/*
882 	 *	Code to process an argument list
883 	 */
884 	ap = arglist;
885 	xp = explist;
886 
887 	shift;		/* bring in the first token for the arg list*/
888 
889 	for (argcnt = 1; argcnt <= 6; argcnt++, ap++){
890 		/*
891 		 *	code to process an argument proper
892 		 */
893 	    sawindex  = sawmul = sawsize = 0;
894 	    {
895 		switch(val) {
896 
897 		   default:
898 		     disp:
899 			if( !(INTOKSET(val,
900 				 EBEGOPS
901 				+YUKKYEXPRBEG
902 				+SAFEEXPRBEG)) ) {
903 				ERROR("expression expected");
904 			}
905 			expr(ap->a_xp,val);
906 		     overdisp:
907 			if ( val == LP || sawsize){
908 				shiftover(LP);
909 				findreg(regno);
910 				shiftover(RP);
911 				ap->a_atype = ADISP;
912 				ap->a_areg1 = regno;
913 			} else {
914 				ap->a_atype = AEXP;
915 				ap->a_areg1 = 0;
916 			}
917 			goto index;
918 
919 		   case SIZESPEC:
920 		     sizespec:
921 			sawsize = yylval;
922 			shift;
923 			goto disp;
924 
925 		   case REG:
926 		   case REGOP:
927 			findreg(regno);
928 			ap->a_atype = AREG;
929 			ap->a_areg1 = regno;
930 			break;
931 
932 		   case MUL:
933 			sawmul = 1;
934 			shift;
935 			if (val == LP) goto base;
936 			if (val == LITOP) goto imm;
937 			if (val == SIZESPEC) goto sizespec;
938 			if (INTOKSET(val,
939 				 EBEGOPS
940 				+YUKKYEXPRBEG
941 				+SAFEEXPRBEG)) goto disp;
942 			ERROR("expression, '(' or '$' expected");
943 			break;
944 
945 		   case LP:
946 		     base:
947 			shift;	/*consume the LP*/
948 			/*
949 			 *	hack the ambiguity of
950 			 *	movl (expr) (rn), ...
951 			 *	note that (expr) could also
952 			 *	be (rn) (by special hole in the
953 			 *	grammar), which we ensure
954 			 *	means register indirection, instead
955 			 *	of an expression with value n
956 			 */
957 			if (val != REG && val != REGOP){
958 				droppedLP = 1;
959 				val = exprparse(val, &(ap->a_xp));
960 				droppedLP = 0;
961 				goto overdisp;
962 			}
963 			findreg(regno);
964 			shiftover(RP);
965 			if (val == PLUS){
966 				shift;
967 				ap->a_atype = AINCR;
968 				if (sawmul && regno != 0xE)
969 					yyerror ("Autoincrement deferred register must be SP");
970 				if (!(sawmul || regno == 0xE))
971 					yyerror ("Autoincrement register must be SP");
972 			} else
973 				ap->a_atype = ABASE;
974 			ap->a_areg1 = regno;
975 			goto index;
976 
977 		   case LITOP:
978 		      imm:
979 			shift;
980 			expr(locxp, val);
981 			ap->a_atype = AIMM;
982 			ap->a_areg1 = 0;
983 			ap->a_xp = locxp;
984 			goto index;
985 
986 		   case MP:
987 			shift;	/* -(reg) */
988 			findreg(regno);
989 			if (regno != 0xE)
990 				yyerror ("Autodecrement register must be SP");
991 			shiftover(RP);
992 			ap->a_atype = ADECR;
993 			ap->a_areg1 = regno;
994 	  index:			/*look for [reg] */
995 			if (val == LB){
996 				shift;
997 				findreg(regno);
998 				shiftover(RB);
999 				sawindex = 1;
1000 				ap->a_areg2 = regno;
1001 			}
1002 			break;
1003 
1004 		}	/*end of the switch to process an arg*/
1005 	    }	/*end of processing an argument*/
1006 
1007 	    if (sawmul){
1008 			/*
1009 			 * Make a concession for *(%r)
1010 			 * meaning *0(%r)
1011 			 */
1012 			if (ap->a_atype == ABASE) {
1013 				ap->a_atype = ADISP;
1014 				xp->e_xtype = XABS;
1015 				xp->e_number = Znumber;
1016 				xp->e_number.num_tag = TYPL;
1017 				xp->e_xloc = 0;
1018 				ap->a_xp = xp++;
1019 			}
1020 			ap->a_atype |= ASTAR;
1021 			sawmul = 0;
1022 	    }
1023 	    if (sawindex){
1024 		ap->a_atype |= AINDX;
1025 		sawindex = 0;
1026 	    }
1027 	    ap->a_dispsize = sawsize == 0 ? d124 : sawsize;
1028 		if (val != CM) break;
1029 		shiftover(CM);
1030 	}	/*processing all the arguments*/
1031 
1032 	if (argcnt > 6){
1033 		yyerror("More than 6 arguments");
1034 		goto errorfix;
1035 	}
1036 
1037 	/*
1038 	 *	See if this is a case instruction,
1039 	 *	so we can set up tests on the following
1040 	 *	vector of branch displacements
1041 	 */
1042 	if (yyopcode == 0xfc)	/* 'casel' instruction */
1043 		incasetable++;
1044 	else
1045 		incasetable = 0;
1046 
1047 	insout(yyopcode, arglist,
1048 		auxval == INSTn ? argcnt : - argcnt);
1049 	break;
1050 
1051    case IQUAD:		num_type = TYPQ;	goto bignumlist;
1052    case IFFLOAT:	num_type = TYPF;	goto bignumlist;
1053    case IDFLOAT:	num_type = TYPD;
1054    bignumlist:
1055 	/*
1056 	 *	eat a list of non 32 bit numbers.
1057 	 *	IQUAD can, possibly, return
1058 	 *	INT's, if the numbers are "small".
1059 	 *
1060 	 *	The value of the numbers is coming back
1061 	 *	as an expression, NOT in yybignum.
1062 	 */
1063 	shift;	/* over the opener */
1064 	if ((val == BIGNUM) || (val == INT)){
1065 		do{
1066 			if ((val != BIGNUM) && (val != INT)){
1067 				ERROR(ty_float[num_type]
1068 				   ? "floating number expected"
1069 				   : "integer number expected" );
1070 			}
1071 			dotp->e_xvalue += ty_nbyte[num_type];
1072 			if (passno == 2){
1073 			   switch (num_type) {
1074 				case TYPF:
1075 					bwrite(((struct exp *)yylval)->e_number.num_num.numFf_float.Ff_ulong,
1076 						ty_nbyte[num_type], txtfil);
1077 					if (liston)
1078 					{
1079 				  	 long_out(((struct exp *)yylval)->e_number.num_num.numFf_float.Ff_ulong[0]);
1080 					 *layoutpos++ = ' ';
1081 					}
1082 					break;
1083 				case TYPD:
1084 					bwrite(&((struct exp *)yylval)->e_number.num_num.numFd_float.Fd_ulong[0],
1085 						sizeof (long), txtfil);
1086 					bwrite(&((struct exp *)yylval)->e_number.num_num.numFd_float.Fd_ulong[1],
1087 						sizeof (long), txtfil);
1088 					if (liston)
1089 					{
1090 				  	 long_out(((struct exp *)yylval)->e_number.num_num.numIq_int.Iq_ulong[0]);
1091 				  	 long_out(((struct exp *)yylval)->e_number.num_num.numIq_int.Iq_ulong[1]);
1092 					 *layoutpos++ = ' ';
1093 					}
1094 					break;
1095 				case TYPQ:
1096 					bwrite(&((struct exp *)yylval)->e_number.num_num.numIq_int.Iq_ulong[1],
1097 						sizeof (long), txtfil);
1098 					bwrite(&((struct exp *)yylval)->e_number.num_num.numIq_int.Iq_ulong[0],
1099 						sizeof (long), txtfil);
1100 					if (liston)
1101 					{
1102 				  	 long_out(((struct exp *)yylval)->e_number.num_num.numIq_int.Iq_ulong[1]);
1103 				  	 long_out(((struct exp *)yylval)->e_number.num_num.numIq_int.Iq_ulong[0]);
1104 					 *layoutpos++ = ' ';
1105 					}
1106 					break;
1107 			   }
1108 			}
1109 			xp = explist;
1110 			shift;		/* over this number */
1111 			if (auxval = (val == CM))
1112 				shift;	/* over the comma */
1113 		} while (auxval);	/* as long as there are commas */
1114 	}
1115 	break;
1116 	/* end of the case for initialized big numbers */
1117     }	/*end of the switch for looking at each reserved word*/
1118 
1119 	continue;
1120 
1121    errorfix:
1122 	/*
1123 	 *	got here by either requesting to skip to the
1124 	 *	end of this statement, or by erroring out and
1125 	 *	wanting to apply panic mode recovery
1126 	 */
1127 	while (    (val != NL)
1128 		&& (val != SEMI)
1129 		&& (val != PARSEEOF)
1130 	      ){
1131 		shift;
1132 	}
1133 	if (val == NL)
1134 		lineno++;
1135 	shift;
1136 
1137     }	/*end of the loop to read the entire file, line by line*/
1138 
1139 }	/*end of yyparse*/
1140 
1141 /*
1142  *	Process a register declaration of the form
1143  *	% <expr>
1144  *
1145  *	Note:
1146  *		The scanner has already processed funny registers of the form
1147  *	%dd[+-]*, where dd is a decimal number in the range 00 to 15 (optional
1148  *	preceding zero digit).  If there was any space between the % and
1149  *	the digit, the scanner wouldn't have recognized it, so we
1150  *	hack it out here.
1151  */
1152 inttoktype funnyreg(val, regnoback)	/*what the read head will sit on*/
1153 	inttoktype	val;		/*what the read head is sitting on*/
1154 	int	*regnoback;		/*call by return*/
1155 {
1156 	reg	struct	exp *locxp;
1157 		struct	exp *loc1xp;
1158 		struct	exp **ptrloc1xp = & loc1xp;
1159 
1160 	expr(locxp, val);	/*and leave the current read head with value*/
1161 	if ( (passno == 2) &&
1162 	    (   (locxp->e_xtype & XTYPE) != XABS
1163 	     || (locxp->e_xvalue < 0)
1164 	     || (locxp->e_xvalue >= 16)
1165 	    )
1166 	  ){
1167 		yyerror("Illegal register");
1168 		return(0);
1169 	}
1170 	*regnoback = locxp->e_xvalue;
1171 	return(val);
1172 }
1173 /*
1174  *	Shift over error
1175  */
1176 shiftoerror(token)
1177 	int	token;
1178 {
1179 	char	*tok_to_name();
1180 	yyerror("%s expected", tok_to_name(token));
1181 }
1182 
1183 /*VARARGS1*/
1184 yyerror(s, a1, a2,a3,a4,a5)
1185 	char	*s;
1186 {
1187 
1188 #define	sink stdout
1189 
1190 	if (anyerrs == 0 && anywarnings == 0 && ! silent)
1191 		fprintf(sink, "Assembler:\n");
1192 	anyerrs++;
1193 	if (silent)
1194 		return;
1195 	fprintf(sink, "\"%s\", line %d: ", dotsname, lineno);
1196 	fprintf(sink, s, a1, a2,a3,a4,a5);
1197 	fprintf(sink, "\n");
1198 #undef sink
1199 }
1200 
1201 /*VARARGS1*/
1202 yywarning(s, a1, a2,a3,a4,a5)
1203 	char	*s;
1204 {
1205 #define	sink stdout
1206 	if (anyerrs == 0 && anywarnings == 0 && ! silent)
1207 		fprintf(sink, "Assembler:\n");
1208 	anywarnings++;
1209 	if (silent)
1210 		return;
1211 	fprintf(sink, "\"%s\", line %d: WARNING: ", dotsname, lineno);
1212 	fprintf(sink, s, a1, a2,a3,a4,a5);
1213 	fprintf(sink, "\n");
1214 #undef sink
1215 }
1216