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