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