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