/* Copyright (c) 1980 Regents of the University of California */
static char sccsid
[] = "@(#)asparse.c 4.7 8/20/80";
int curlen
; /* current length of literals */
* The following three variables are communication between various
* modules to special case a number of things. They are properly
extern struct symtab
*lastnam
;/*last name seen by the lexical analyzer*/
int exprisname
; /*last factor in an expression was a name*/
int droppedLP
; /*one is analyzing an expression beginning with*/
/*a left parenthesis, which has already been*/
/*shifted. (Used to parse (<expr>)(rn)*/
char yytext
[NCPS
+2]; /*the lexical image*/
int yylval
; /*the lexical value; sloppy typing*/
* Expression and argument managers
struct exp
*xp
; /*next free expression slot, used by expr.c*/
struct exp explist
[NEXP
]; /*max of 20 expressions in one opcode*/
struct arg arglist
[NARG
]; /*building up operands in instructions*/
* Sets to accelerate token discrimination
char tokensets
[(LASTTOKEN
) - (FIRSTTOKEN
) + 1];
static char UDotsname
[32]; /*name of the assembly source*/
register struct exp
*locxp
;
* loc1xp and ptrloc1xp are used in the
struct exp
*loc1xp
; /*must be non register*/
struct exp
**ptrloc1xp
= & loc1xp
;
struct exp
*pval
; /*hacking expr:expr*/
register struct symtab
*np
;
register int val
; /*what yylex gives*/
register int auxval
; /*saves val*/
register struct arg
*ap
; /*first free argument*/
register struct symtab
*stpt
;
struct strdesc
*stringp
; /*handles string lists*/
int regno
; /*handles arguments*/
int sawindex
; /*saw [rn]*/
int seg_type
; /*the kind of segment: data or text*/
int seg_number
; /*the segment number*/
int space_value
; /*how much .space needs*/
int fill_rep
; /*how many reps for .fill */
int fill_size
; /*how many bytes for .fill */
int field_width
; /*how wide a field is to be*/
int field_value
; /*the value to stuff in a field*/
char *stabname
; /*name of stab dealing with*/
ptrall stabstart
; /*where the stab starts in the buffer*/
int reloc_how
; /* how to relocate expressions */
while (val
!= PARSEEOF
){ /* primary loop */
while (INTOKSET(val
, LINSTBEGIN
)){
int i
= ((struct exp
*)yylval
)->e_xvalue
;
yyerror("Local labels are 0-9");
sprintf(yytext
, "L%d\001%d", i
, lgensym
[i
]);
yylval
= (int)*lookup(passno
== 1);
np
= (struct symtab
*)yylval
;
else { /*its a name, so we have a label or def */
ERROR("Name expected for a label");
np
= (struct symtab
*)yylval
;
yyerror("\"%s\" is not followed by a ':' for a label definition",
yyerror("\"%.*s\" is not followed by a ':' for a label definition",
if ((np
->s_type
&XTYPE
)!=XUNDEF
) {
if( (np
->s_type
&XTYPE
)!=dotp
->e_xtype
|| np
->s_value
!=dotp
->e_xvalue
&&(np
->s_index
!= dotp
->e_xloc
)
if (np
->s_name
[0] != 'L')
yyerror("%.*s redefined",
yyerror("%s redefined: PHASE ERROR, 1st: %d, 2nd: %d",
yyerror("%.*s redefined: PHASE ERROR, 1st: %d, 2nd: %d",
np
->s_type
&= ~(XTYPE
|XFORW
);
np
->s_type
|= dotp
->e_xtype
;
np
->s_value
= dotp
->e_xvalue
;
np
->s_index
= dotp
-usedot
;
if (np
->s_name
[0] == 'L'){
} /*end of this being a label*/
} /*end of to consuming all labels, NLs and SEMIS */
* process the INSTRUCTION body
ERROR("Unrecognized instruction or directive");
tokptr
-= sizeof(toktype
);
stringp
= (struct strdesc
*)yylval
;
dotsname
= &UDotsname
[0];
movestr(dotsname
, stringp
->str
,
stringp
->str_lg
>= 32? 32 :stringp
->str_lg
);
dotsname
[stringp
->str_lg
] = '\0';
shift
; /*over the ILINENO*/
lineno
= locxp
->e_xvalue
;
case ISET
: /* .set <name> , <expr> */
np
= (struct symtab
*)yylval
;
np
->s_type
&= (XXTRN
|XFORW
);
np
->s_type
|= locxp
->e_xtype
&(XTYPE
|XFORW
);
np
->s_value
= locxp
->e_xvalue
;
np
->s_index
= locxp
->e_xloc
;
if ((locxp
->e_xtype
&XTYPE
) == XUNDEF
)
case ILSYM
: /*.lsym name , expr */
np
= (struct symtab
*)yylval
;
* Build the unique occurance of the
* The character scanner will have
* already entered it into the symbol
* table, but we should remove it
stpt
= (struct symtab
*)symalloc();
stpt
->s_name
= np
->s_name
;
movestr(stpt
->s_name
, np
->s_name
, NCPS
);
np
->s_tag
= OBSOLETE
; /*invalidate original */
if (locxp
->e_xtype
!= XABS
)
np
->s_value
=locxp
->e_xvalue
;
case IGLOBAL
: /*.globl <name> */
np
= (struct symtab
*)yylval
;
case IDATA
: /*.data [ <expr> ] */
case ITEXT
: /*.text [ <expr> ] */
if (INTOKSET(val
, EBEGOPS
+YUKKYEXPRBEG
+SAFEEXPRBEG
)){
seg_type
= -seg_type
; /*now, it is positive*/
if (seg_type
< 0) { /*there wasn't an associated expr*/
if (locxp
->e_xtype
!= XABS
|| (seg_number
=locxp
->e_xvalue
) >= NLOC
) {
yyerror("illegal location counter");
dotp
= &usedot
[seg_number
];
if (passno
==2) { /* go salt away in pass 2*/
txtfil
= usefile
[seg_number
];
relfil
= rusefile
[seg_number
];
puchar(vms_obj_ptr
,6); /* setpl */
puchar(vms_obj_ptr
,seg_number
); /* psect # */
plong(vms_obj_ptr
,dotp
->e_xvalue
);/* offset */
puchar(vms_obj_ptr
,80); /* setrb */
if((vms_obj_ptr
-sobuf
) > 400){
write(objfil
,sobuf
,vms_obj_ptr
-sobuf
);
vms_obj_ptr
=sobuf
+1; /*flush buf*/
* Storage filler directives:
* exprlist: empty | exprlist outexpr
* outexpr: <expr> | <expr> : <expr>
case IBYTE
: curlen
= NBPW
/4; goto elist
;
case ILONG
: curlen
= NBPW
; goto elist
;
* Expression List processing
if (INTOKSET(val
, EBEGOPS
+YUKKYEXPRBEG
+SAFEEXPRBEG
)){
* expression list consists of a list of :
* (pack expr2 into expr1 bits
* now, pointing at the next token
if (locxp
->e_xtype
!= XABS
)
yyerror("Width not absolute");
field_width
= locxp
->e_xvalue
;
if (bitoff
+ field_width
>
if (field_width
> curlen
)
yyerror("Expression crosses field boundary");
if ((locxp
->e_xtype
&XTYPE
)!=XABS
) {
yyerror("Illegal relocation in field");
case NBPW
/4: reloc_how
= TYPB
; break;
case NBPW
/2: reloc_how
= TYPW
; break;
case NBPW
: reloc_how
= TYPL
; break;
dotp
->e_xvalue
+= ty_nbyte
[reloc_how
];
outrel(locxp
, reloc_how
);
field_value
= locxp
->e_xvalue
& ( (1L << field_width
)-1);
bitfield
|= field_value
<< bitoff
;
if ( auxval
= (val
== CM
)) shift
;
} /*existed an expression at all*/
if ( ( curlen
== NBPW
/4) && bitoff
)
/*end of case IBYTE, IWORD, ILONG, IINT*/
case ISPACE
: /* .space <expr> */
if (locxp
->e_xtype
!= XABS
)
yyerror("Space size not absolute");
space_value
= locxp
->e_xvalue
;
while (space_value
> 96){
outs(strbuf
[2].str
, space_value
);
dotp
->e_xvalue
+= space_value
; /*bump pc*/
if(*(strbuf
[2].str
)==0) {
puchar(vms_obj_ptr
,81); /* AUGR */
pulong(vms_obj_ptr
,space_value
);/* incr */
} else yyerror("VMS, encountered non-0 .space");
if ((vms_obj_ptr
-sobuf
) > 400) {
write(objfil
,sobuf
,vms_obj_ptr
-sobuf
);
vms_obj_ptr
=sobuf
+1; /*pur buf*/
* repeat rep times: fill size bytes with (truncated) value
* size must be between 1 and 8
if (locxp
->e_xtype
!= XABS
)
yyerror("Fill repetition count not absolute");
fill_rep
= locxp
->e_xvalue
;
if (locxp
->e_xtype
!= XABS
)
yyerror("Fill size not absolute");
fill_size
= locxp
->e_xvalue
;
if (fill_size
<= 0 || fill_size
> 8)
yyerror("Fill count not in in 1..8");
if (passno
== 2 && locxp
->e_xtype
!= XABS
)
yyerror("Fill value not absolute");
locxp
->e_xvalue
+= fill_rep
* fill_size
;
bwrite(&locxp
->e_xvalue
, fill_size
, txtfil
);
case IASCII
: /* .ascii [ <stringlist> ] */
case IASCIZ
: /* .asciz [ <stringlist> ] */
* Code to consume a string list
* stringlist: empty | STRING | stringlist STRING
stringp
= (struct strdesc
*)yylval
;
outs(stringp
->str
, stringp
->str_lg
);
for (i
=0; i
< stringp
->str_lg
; i
++){
puchar(vms_obj_ptr
,stringp
->str
[i
]);
if (vms_obj_ptr
-sobuf
> 400) {
write(objfil
,sobuf
,vms_obj_ptr
-sobuf
);
shift
; /*over the STRING*/
if (val
== CM
) /*could be a split string*/
case IORG
: /* .org <expr> */
if (locxp
->e_xtype
==XABS
)
else if ((locxp
->e_xtype
& ~XXTRN
) != dotp
->e_xtype
)
yyerror("Illegal expression to set origin");
space_value
= locxp
->e_xvalue
- dotp
->e_xvalue
;
yyerror("Backwards 'org'");
* Process stabs. Stabs are created only by the f77
* and the C compiler with the -g flag set.
* We only look at the stab ONCE, during pass 1, and
* virtually remove the stab from the intermediate file
* so it isn't seen during pass2. This makes for some
* hairy processing to handle labels occuring in
* stab entries, but since most expressions in the
* stab are integral we save lots of time in the second
* pass by not looking at the stabs.
* A stab that is tagged floating will be bumped during
* the jxxx resolution phase. A stab tagged fixed will
* .stab: Old fashioned stabs
* .stabn: For stabs without names
* .stabs: For stabs with string names
* .stabd: For stabs for line numbers or bracketing,
* without a string name, without
* a final expression. The value of the
* final expression is taken to be the current
* location counter, and is patched by the 2nd pass
* .stab{<expr>,}*NCPS,<expr>, <expr>, <expr>, <expr>
* .stabn <expr>, <expr>, <expr>, <expr>
* .stabs STRING, <expr>, <expr>, <expr>, <expr>
* .stabd <expr>, <expr>, <expr> # .
if (passno
== 2) goto errorfix
;
stpt
= (struct symtab
*)yylval
;
* Make a pointer to the .stab slot.
* There is a pointer in the way (stpt), and
* tokptr points to the next token.
(char *)stabstart
-= sizeof(struct symtab
*);
(char *)stabstart
-= sizeof(toktype
);
for (argcnt
= 0; argcnt
< NCPS
; argcnt
++){
stpt
->s_name
[argcnt
] = locxp
->e_xvalue
;
yyerror(".stab directive not supported in; report this compiler bug to system administrator");
if (! (locxp
->e_xvalue
& STABTYPS
)){
yyerror("Invalid type in %s",stabname
);
stpt
->s_ptype
= locxp
->e_xvalue
;
stpt
->s_other
= locxp
->e_xvalue
;
stpt
->s_desc
= locxp
->e_xvalue
;
if (p
== NULL
) { /*absolute expr to begin with*/
stpt
->s_value
= locxp
->e_xvalue
;
stpt
->s_index
= dotp
- usedot
;
stpt
->s_tag
= STABFLOATING
;
else { /*really have a name*/
stpt
->s_dest
= locxp
->e_xname
;
stpt
->s_index
= p
->s_index
;
stpt
->s_type
= p
->s_type
| STABFLAG
;
* We will assign a more accruate
* guess of locxp's location when
* we sort the symbol table
* The final value of value is
stpt
->s_tag
= STABFLOATING
;
* tokptr now points at one token beyond
* the current token stored in val and yylval,
* which are the next tokens after the end of
* this .stab directive. This next token must
* be either a SEMI or NL, so is of width just
* one. Therefore, to point to the next token
* after the end of this stab, just back up one..
buildskip(stabstart
, (char *)tokptr
- sizeof(toktype
));
break; /*end of the .stab*/
stpt
= (struct symtab
*)yylval
;
* We clobber everything after the
* .stabd and its pointer... we MUST
* be able to get back to this .stabd
* so that we can resolve its final value
shift
; /*over the ISTABDOT*/
if (! (locxp
->e_xvalue
& STABTYPS
)){
yyerror("Invalid type in .stabd");
stpt
->s_ptype
= locxp
->e_xvalue
;
stpt
->s_other
= locxp
->e_xvalue
;
stpt
->s_desc
= locxp
->e_xvalue
;
* Now, clobber everything but the
* .stabd pseudo and the pointer
* to its symbol table entry
* tokptr points to the next token,
* build the skip up to this
buildskip(stabstart
, (toktype
*)tokptr
- sizeof(toktype
));
* pass 1: Assign a good guess for its position
* (ensures they are sorted into right place)/
* pass 2: Fix the actual value
stpt
->s_value
= dotp
->e_xvalue
;
stpt
->s_index
= dotp
- usedot
;
stpt
->s_tag
= STABFLOATING
; /*although it has no effect in pass 2*/
case ISTABNONE
: stabname
= ".stabn"; goto shortstab
;
case ISTABSTR
: stabname
= ".stabs";
if (passno
== 2) goto errorfix
;
stpt
= (struct symtab
*)yylval
;
(char *)stabstart
-= sizeof(struct symtab
*);
(char *)stabstart
-= sizeof(toktype
);
stringp
= (struct strdesc
*)yylval
;
auxval
= stringp
->str_lg
> NCPS
? NCPS
: stringp
->str_lg
;
stringp
->str
[stringp
->str_lg
] = 0;
movestr(stpt
->s_name
, stringp
->str
, auxval
);
stpt
->s_name
= savestr(stringp
->str
);
case ICOMM
: /* .comm <name> , <expr> */
case ILCOMM
: /* .lcomm <name> , <expr> */
np
= (struct symtab
*)yylval
;
if (locxp
->e_xtype
!= XABS
)
yyerror("comm size not absolute");
if (passno
==1 && (np
->s_type
&XTYPE
)!=XUNDEF
)
yyerror("Redefinition of %s",
yyerror("Redefinition of %.*s",
np
->s_value
= locxp
->e_xvalue
;
case IALIGN
: /* .align <expr> */
stpt
= (struct symtab
*)yylval
;
case INST0
: /* instructions w/o arguments*/
insout(yylval
, (struct arg
*)0, 0);
case INSTn
: /* instructions with arguments*/
case IJXXX
: /* UNIX style jump instructions */
* Code to process an argument list
shift
; /* bring in the first token for the arg list*/
for (argcnt
= 1; argcnt
<= 6; argcnt
++, ap
++){
* code to process an argument proper
sawindex
= sawmul
= sawsize
= 0;
ERROR("expression expected");
if ( val
== LP
|| sawsize
){
if (val
== LP
) goto base
;
if (val
== LITOP
) goto imm
;
if (val
== SIZESPEC
) goto sizespec
;
+SAFEEXPRBEG
)) goto disp
;
ERROR("expression, '(' or '$' expected");
shift
; /*consume the LP*/
* note that (expr) could also
* be (rn) (by special hole in the
* grammar), which we ensure
* means register indirection, instead
* of an expression with value n
if (val
!= REG
&& val
!= REGOP
){
val
= exprparse(val
, &(ap
->a_xp
));
index
: /*look for [reg] */
} /*end of the switch to process an arg*/
} /*end of processing an argument*/
* Make a concession for *(%r)
if (ap
->a_atype
== ABASE
) {
ap
->a_dispsize
= sawsize
== 0 ? d124
: sawsize
;
} /*processing all the arguments*/
yyerror("More than 6 arguments");
insout(seg_type
, arglist
,
auxval
== INSTn
? argcnt
: - argcnt
);
case IFLOAT
: curlen
= 4; goto floatlist
;
* eat a list of floating point numbers
ERROR("floating number expected");
dotp
->e_xvalue
+= curlen
;
bwrite((char *)&(((union Double
*)yylval
)->dvalue
),
flocal
= ((union Double
*)yylval
)->dvalue
;
bwrite((char *)&flocal
, curlen
, txtfil
);
if((vms_obj_ptr
-sobuf
) > 400) {
write(objfil
,sobuf
,vms_obj_ptr
-sobuf
);
} /*end of the switch for looking at each reserved word*/
* got here by either requesting to skip to the
* end of this statement, or by erroring out and
* wanting to apply panic mode recovery
} /*end of the loop to read the entire file, line by line*/
* Process a register declaration of the form
* The scanner has already processed funny registers of the form
* %dd[+-]*, where dd is a decimal number in the range 00 to 15 (optional
* preceding zero digit). If there was any space between the % and
* the digit, the scanner wouldn't have recognized it, so we
int funnyreg(val
, regnoback
) /*what the read head will sit on*/
int val
; /*what the read head is sitting on*/
int *regnoback
; /*call by return*/
register struct exp
*locxp
;
struct exp
**ptrloc1xp
= & loc1xp
;
expr(locxp
, val
); /*and leave the current read head with value*/
( locxp
->e_xtype
& XTYPE
!= XABS
yyerror("Illegal register");
*regnoback
= locxp
->e_xvalue
;
yyerror(s
, a1
, a2
,a3
,a4
,a5
)
if (anyerrs
== 0 && ! silent
)
fprintf(sink
, "Assembler:\n");
fprintf(sink
, "\"%s\", line %d: ", dotsname
, lineno
);
fprintf(sink
, s
, a1
, a2
,a3
,a4
,a5
);
yywarning(s
, a1
, a2
,a3
,a4
,a5
)
if (anyerrs
== 0 && ! silent
)
fprintf(sink
, "Assembler:\n");
fprintf(sink
, "\"%s\", line %d: WARNING: ", dotsname
, lineno
);
fprintf(sink
, s
, a1
, a2
,a3
,a4
,a5
);