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