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