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