BSD 4 release
[unix-history] / usr / src / cmd / as / asparse.c
CommitLineData
05353f4b 1/* Copyright (c) 1980 Regents of the University of California */
31cef89c 2static char sccsid[] = "@(#)asparse.c 4.7 8/20/80";
05353f4b 3#include <stdio.h>
05353f4b
BJ
4#include "as.h"
5#include "asexpr.h"
6#include "asscan.h"
7#include "assyms.h"
8
9int lgensym[10];
10char genref[10];
11
12long bitfield;
13int bitoff;
14int 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 */
21extern struct symtab *lastnam;/*last name seen by the lexical analyzer*/
22int exprisname; /*last factor in an expression was a name*/
23int droppedLP; /*one is analyzing an expression beginning with*/
24 /*a left parenthesis, which has already been*/
25 /*shifted. (Used to parse (<expr>)(rn)*/
26
27char yytext[NCPS+2]; /*the lexical image*/
28int yylval; /*the lexical value; sloppy typing*/
29/*
30 * Expression and argument managers
31 */
32struct exp *xp; /*next free expression slot, used by expr.c*/
33struct exp explist[NEXP]; /*max of 20 expressions in one opcode*/
34struct arg arglist[NARG]; /*building up operands in instructions*/
35/*
36 * Sets to accelerate token discrimination
37 */
38char tokensets[(LASTTOKEN) - (FIRSTTOKEN) + 1];
39
40static char UDotsname[32]; /*name of the assembly source*/
41
42int 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*/
ae1423d9
RH
74 int fill_rep; /*how many reps for .fill */
75 int fill_size; /*how many bytes for .fill */
05353f4b
BJ
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*/
5b3c350a 81 int reloc_how; /* how to relocate expressions */
05353f4b
BJ
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) {
451260e7 92 int i = ((struct exp *)yylval)->e_xvalue;
05353f4b
BJ
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);
120nocolon:
121 if (val != COLON) {
451260e7 122#ifdef FLEXNAMES
05353f4b 123 yyerror("\"%s\" is not followed by a ':' for a label definition",
451260e7
RH
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);
05353f4b
BJ
129 goto errorfix;
130 }
131restlab:
132 shift;
133 flushfield(NBPW/4);
451260e7
RH
134 if ((np->s_type&XTYPE)!=XUNDEF) {
135 if( (np->s_type&XTYPE)!=dotp->e_xtype
136 || np->s_value!=dotp->e_xvalue
05353f4b 137 || ( (passno==1)
451260e7 138 &&(np->s_index != dotp->e_xloc)
05353f4b
BJ
139 )
140 ){
141#ifndef DEBUG
451260e7 142 if (np->s_name[0] != 'L')
05353f4b
BJ
143#endif not DEBUG
144 {
145 if (passno == 1)
451260e7
RH
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);
05353f4b 153 else
451260e7
RH
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);
05353f4b
BJ
163 }
164 }
165 }
451260e7
RH
166 np->s_type &= ~(XTYPE|XFORW);
167 np->s_type |= dotp->e_xtype;
168 np->s_value = dotp->e_xvalue;
05353f4b 169 if (passno == 1){
451260e7
RH
170 np->s_index = dotp-usedot;
171 if (np->s_name[0] == 'L'){
05353f4b
BJ
172 nlabels++;
173 }
451260e7 174 np->s_tag = LABELID;
05353f4b
BJ
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);
451260e7 216 lineno = locxp->e_xvalue;
05353f4b
BJ
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);
451260e7
RH
225 np->s_type &= (XXTRN|XFORW);
226 np->s_type |= locxp->e_xtype&(XTYPE|XFORW);
227 np->s_value = locxp->e_xvalue;
05353f4b 228 if (passno==1)
451260e7
RH
229 np->s_index = locxp->e_xloc;
230 if ((locxp->e_xtype&XTYPE) == XUNDEF)
05353f4b
BJ
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
451260e7 250 stpt->s_name = np->s_name;
05353f4b 251#else
451260e7 252 movestr(stpt->s_name, np->s_name, NCPS);
05353f4b 253#endif
451260e7 254 np->s_tag = OBSOLETE; /*invalidate original */
05353f4b
BJ
255 nforgotten++;
256 np = stpt;
451260e7 257 if (locxp->e_xtype != XABS)
05353f4b 258 ("Illegal lsym");
451260e7
RH
259 np->s_value=locxp->e_xvalue;
260 np->s_type=XABS;
261 np->s_tag = ILSYM;
05353f4b
BJ
262 }
263 break;
264
265 case IGLOBAL: /*.globl <name> */
266 shift;
267 np = (struct symtab *)yylval;
268 shiftover(NAME);
451260e7 269 np->s_type |= XXTRN;
05353f4b
BJ
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 {
451260e7 285 if (locxp->e_xtype != XABS || (seg_number=locxp->e_xvalue) >= NLOC) {
05353f4b
BJ
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 # */
451260e7 304 plong(vms_obj_ptr,dotp->e_xvalue);/* offset */
05353f4b
BJ
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);
451260e7 351 if (locxp->e_xtype != XABS)
05353f4b 352 yyerror("Width not absolute");
451260e7 353 field_width = locxp->e_xvalue;
05353f4b
BJ
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
451260e7 365 if ((locxp->e_xtype&XTYPE)!=XABS) {
05353f4b
BJ
366 if (bitoff)
367 yyerror("Illegal relocation in field");
5b3c350a
RH
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 }
05353f4b 373 if (passno == 1){
5b3c350a 374 dotp->e_xvalue += ty_nbyte[reloc_how];
05353f4b 375 } else {
5b3c350a 376 outrel(locxp, reloc_how);
05353f4b
BJ
377 }
378 } else {
451260e7 379 field_value = locxp->e_xvalue & ( (1L << field_width)-1);
05353f4b
BJ
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)
451260e7 390 dotp->e_xvalue ++;
05353f4b
BJ
391 break;
392 /*end of case IBYTE, IWORD, ILONG, IINT*/
393
394 case ISPACE: /* .space <expr> */
395 shift;
396 expr(locxp, val);
451260e7 397 if (locxp->e_xtype != XABS)
05353f4b 398 yyerror("Space size not absolute");
451260e7 399 space_value = locxp->e_xvalue;
05353f4b
BJ
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
451260e7 410 dotp->e_xvalue += space_value; /*bump pc*/
05353f4b
BJ
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
ae1423d9
RH
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:
05353f4b
BJ
431 shift;
432 expr(locxp, val);
451260e7 433 if (locxp->e_xtype != XABS)
05353f4b 434 yyerror("Fill repetition count not absolute");
ae1423d9 435 fill_rep = locxp->e_xvalue;
05353f4b
BJ
436 shiftover(CM);
437 expr(locxp, val);
451260e7 438 if (locxp->e_xtype != XABS)
ae1423d9
RH
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");
05353f4b 447 flushfield(NBPW/4);
ae1423d9
RH
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 }
05353f4b
BJ
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)
451260e7 470 dotp->e_xvalue++;
05353f4b
BJ
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++){
451260e7 479 dotp->e_xvalue += 1;
05353f4b
BJ
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 }
451260e7 506 dotp->e_xvalue += 1;
05353f4b
BJ
507#endif VMS
508 }
509 break;
510
511 case IORG: /* .org <expr> */
512 shift;
513 expr(locxp, val);
514
451260e7 515 if (locxp->e_xtype==XABS)
05353f4b 516 orgwarn++;
451260e7 517 else if ((locxp->e_xtype & ~XXTRN) != dotp->e_xtype)
05353f4b 518 yyerror("Illegal expression to set origin");
451260e7 519 space_value = locxp->e_xvalue - dotp->e_xvalue;
05353f4b
BJ
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 *
5b3c350a 549 * .stab{<expr>,}*NCPS,<expr>, <expr>, <expr>, <expr>
05353f4b
BJ
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;
5b3c350a 568 for (argcnt = 0; argcnt < NCPS; argcnt++){
05353f4b 569 expr(locxp, val);
451260e7 570 stpt->s_name[argcnt] = locxp->e_xvalue;
05353f4b
BJ
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);
451260e7 582 if (! (locxp->e_xvalue & STABTYPS)){
05353f4b
BJ
583 yyerror("Invalid type in %s",stabname);
584 goto errorfix;
585 }
451260e7 586 stpt->s_ptype = locxp->e_xvalue;
05353f4b
BJ
587 shiftover(CM);
588 expr(locxp, val);
451260e7 589 stpt->s_other = locxp->e_xvalue;
05353f4b
BJ
590 shiftover(CM);
591 expr(locxp, val);
451260e7 592 stpt->s_desc = locxp->e_xvalue;
05353f4b
BJ
593 shiftover(CM);
594 exprisname = 0;
595 expr(locxp, val);
451260e7 596 p = locxp->e_xname;
05353f4b 597 if (p == NULL) { /*absolute expr to begin with*/
451260e7
RH
598 stpt->s_value = locxp->e_xvalue;
599 stpt->s_index = dotp - usedot;
05353f4b 600 if (exprisname){
451260e7 601 switch(stpt->s_ptype){
05353f4b
BJ
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:
451260e7 611 stpt->s_tag = STABFIXED;
05353f4b
BJ
612 break;
613 default:
451260e7 614 stpt->s_tag = STABFLOATING;
05353f4b
BJ
615 break;
616 }
617 } else
451260e7 618 stpt->s_tag = STABFIXED;
05353f4b
BJ
619 }
620 else { /*really have a name*/
451260e7
RH
621 stpt->s_dest = locxp->e_xname;
622 stpt->s_index = p->s_index;
623 stpt->s_type = p->s_type | STABFLAG;
05353f4b
BJ
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 */
451260e7 631 stpt->s_tag = STABFLOATING;
05353f4b
BJ
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);
451260e7 658 if (! (locxp->e_xvalue & STABTYPS)){
05353f4b
BJ
659 yyerror("Invalid type in .stabd");
660 goto errorfix;
661 }
451260e7 662 stpt->s_ptype = locxp->e_xvalue;
05353f4b
BJ
663 shiftover(CM);
664 expr(locxp, val);
451260e7 665 stpt->s_other = locxp->e_xvalue;
05353f4b
BJ
666 shiftover(CM);
667 expr(locxp, val);
451260e7 668 stpt->s_desc = locxp->e_xvalue;
05353f4b
BJ
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 */
451260e7
RH
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*/
05353f4b
BJ
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
451260e7 716 movestr(stpt->s_name, stringp->str, auxval);
05353f4b 717#else
451260e7 718 stpt->s_name = savestr(stringp->str);
05353f4b
BJ
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
451260e7 732 if (locxp->e_xtype != XABS)
05353f4b 733 yyerror("comm size not absolute");
451260e7
RH
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);
05353f4b 742 if (passno==1) {
451260e7 743 np->s_value = locxp->e_xvalue;
05353f4b 744 if (auxval == ICOMM)
451260e7 745 np->s_type |= XXTRN;
05353f4b 746 else {
451260e7
RH
747 np->s_type &= ~XTYPE;
748 np->s_type |= XBSS;
05353f4b
BJ
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 }
451260e7 793 expr(ap->a_xp,val);
05353f4b
BJ
794 overdisp:
795 if ( val == LP || sawsize){
796 shiftover(LP);
797 findreg(regno);
798 shiftover(RP);
451260e7
RH
799 ap->a_atype = ADISP;
800 ap->a_areg1 = regno;
05353f4b 801 } else {
451260e7
RH
802 ap->a_atype = AEXP;
803 ap->a_areg1 = 0;
05353f4b
BJ
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);
451260e7
RH
816 ap->a_atype = AREG;
817 ap->a_areg1 = regno;
05353f4b
BJ
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;
451260e7 847 val = exprparse(val, &(ap->a_xp));
05353f4b
BJ
848 droppedLP = 0;
849 goto overdisp;
850 }
851 findreg(regno);
852 shiftover(RP);
853 if (val == PLUS){
854 shift;
451260e7 855 ap->a_atype = AINCR;
05353f4b 856 } else
451260e7
RH
857 ap->a_atype = ABASE;
858 ap->a_areg1 = regno;
05353f4b
BJ
859 goto index;
860
861 case LITOP:
862 imm:
863 shift;
864 expr(locxp, val);
451260e7
RH
865 ap->a_atype = AIMM;
866 ap->a_areg1 = 0;
867 ap->a_xp = locxp;
05353f4b
BJ
868 goto index;
869
870 case MP:
871 shift; /* -(reg) */
872 findreg(regno);
873 shiftover(RP);
451260e7
RH
874 ap->a_atype = ADECR;
875 ap->a_areg1 = regno;
05353f4b
BJ
876 index: /*look for [reg] */
877 if (val == LB){
878 shift;
879 findreg(regno);
880 shiftover(RB);
881 sawindex = 1;
451260e7 882 ap->a_areg2 = regno;
05353f4b
BJ
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 */
451260e7
RH
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++;
05353f4b 900 }
451260e7 901 ap->a_atype |= ASTAR;
05353f4b
BJ
902 sawmul = 0;
903 }
904 if (sawindex){
451260e7 905 ap->a_atype |= AINDX;
05353f4b
BJ
906 sawindex = 0;
907 }
451260e7 908 ap->a_dispsize = sawsize == 0 ? d124 : sawsize;
05353f4b
BJ
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;
f2ff9823 923 case IQUAD:
05353f4b
BJ
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 }
451260e7 939 dotp->e_xvalue += curlen;
05353f4b
BJ
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 */
1010int 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) &&
451260e7
RH
1020 ( locxp->e_xtype & XTYPE != XABS
1021 || locxp->e_xvalue < 0
1022 || locxp->e_xvalue >= 16
05353f4b
BJ
1023 )
1024 ){
1025 yyerror("Illegal register");
1026 return(0);
1027 }
451260e7 1028 *regnoback = locxp->e_xvalue;
05353f4b
BJ
1029 return(val);
1030}
1031
1032/*VARARGS1*/
1033yyerror(s, a1, a2,a3,a4,a5)
1034 char *s;
1035{
05353f4b 1036
362ed7a6 1037#define sink stdout
05353f4b
BJ
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}
acd69f82
RH
1048
1049/*VARARGS1*/
1050yywarning(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}