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