* Process a single external definition
register struct hshtab
*ds
;
if(((o
=symbol())==EOF
) || o
==SEMI
)
if ((elsize
= getkeywords(&sclass
, &type
)) == -1 && peeksym
!=NAME
)
decl1(EXTERN
, type
, 0, elsize
);
outcode("BS", SYMDEF
, ds
->name
);
if ((ds
->type
&XTYPE
)==FUNC
) {
if ((peeksym
=symbol())==LBRACE
|| peeksym
==KEYW
) {
funcblk
.type
= decref(ds
->type
);
} while ((o
=symbol())==COMMA
);
error("External definition syntax");
* Process a function definition.
outcode("BBS", PROG
, RLABEL
, cs
);
if ((peeksym
= symbol()) != LBRACE
)
error("Compound statement required");
outcode("BNB", LABEL
, retlab
, RETRN
);
* Process the initializers for an external definition.
register basetype
, nel
, ninit
;
* If it's an array, find the number of elements.
* "basetype" is the type of thing it's an array of.
while ((basetype
&XTYPE
)==ARRAY
) {
if ((nel
= dimtab
[ds
->ssp
&0377])==0)
basetype
= decref(basetype
);
realwidth
= width
= length(ds
) / nel
;
* Pretend a structure is kind of an array of integers.
if ((peeksym
=symbol())==COMMA
|| peeksym
==SEMI
) {
outcode("BSN",CSPACE
,ds
->name
,(nel
*width
+ALIGN
)&~ALIGN
);
outcode("BBS", DATA
, NLABEL
, ds
->name
);
if ((o
=symbol())==LBRACE
) {
ninit
= cinit1(ds
, basetype
, width
, ninit
, nel
);
while ((o
=symbol())==COMMA
);
ninit
= cinit1(ds
, basetype
, width
, 0, nel
);
* Above we pretended that a structure was a bunch of integers.
* Readjust in accordance with reality.
* First round up partial initializations.
if (o
= 2*ninit
% realwidth
)
outcode("BN", SSPACE
, realwidth
-o
);
ninit
= (2*ninit
+realwidth
-2) / realwidth
;
* If there are too few initializers, allocate
* If there are too many initializers, extend
* the declared size for benefit of "sizeof"
outcode("BN", SSPACE
, (nel
-ninit
)*realwidth
);
if ((ds
->type
&XTYPE
)==ARRAY
)
dimtab
[ds
->ssp
&0377] = ninit
;
* If it's not an array, only one initializer is allowed.
if (ninit
>1 && (ds
->type
&XTYPE
)!=ARRAY
)
error("Too many initializers");
* Process a single expression in a sequence of initializers
* for an external. Mainly, it's for checking
cinit1(ds
, type
, awidth
, aninit
, nel
)
register struct tnode
*s
;
if ((peeksym
=symbol())==STRING
&& type
==CHAR
) {
outcode("BN", SSPACE
, nel
-nchstr
);
outcode("B1N0", BDATA
, s
->value
);
outcode("B1N0", WDATA
, s
->value
);
if (s
->op
==FCON
|| s
->op
==SFCON
) {
rcexpr(block(1,INIT
,0,0,s
));
outcode("B1N1N0", WDATA
, sf
);
outcode("B1N1N1N1N0", WDATA
, fcval
);
if (s
->op
==FCON
|| s
->op
==SFCON
)
error("Inconsistent external initialization");
* Process one statement in a function.
outcode("BN", PROFIL
, isn
++);
outcode("BN", SAVE
, blkhed());
if ((o
=symbol())==RBRACE
)
if ((o1
=symbol())==KEYW
) switch (cval
) {
cbranch(np
, o2
=isn
++, 0);
cbranch(np
, o1
=isn
++, 0);
if ((o1
=symbol())==KEYW
&& cval
==ELSE
)
cbranch(np
, o1
=isn
++, 0);
if ((o
=symbol())==KEYW
&& cval
==ELSE
) {
cbranch(pexpr(), brklab
=isn
++, 0);
if ((o
=symbol())==KEYW
&& cval
==WHILE
) {
error("Case not in switch");
error("Switch table overflow");
rcexpr(block(1,RFORCE
,0,0,np
));
error("Default not in switch");
error("Unknown keyword");
error("Statement syntax");
* Process a for statement.
register int l
, o
, sline
;
if ((o
=symbol()) != LPARN
)
if ((o
=symbol()) != SEMI
) { /* init part */
if ((o
=symbol()) != SEMI
)
if ((o
=symbol()) != SEMI
) { /* test part */
rcexpr(block(1,CBRANCH
,tree(),brklab
,0));
if ((o
=symbol()) != SEMI
)
if ((peeksym
=symbol()) == RPARN
) { /* incr part */
if ((o
=symbol()) != RPARN
)
* A parenthesized expression,
error("Statement syntax");
* The switch stateent, which involves collecting the
* constants and labels for the cases.
register struct swtab
*cswp
, *sswp
;
outcode("BNN", SWIT
, deflab
, line
);
for (; cswp
< swp
; cswp
++)
outcode("NN", cswp
->swlab
, cswp
->swval
);
* blkhed is called at the start of each function.
* It reads the declarations at the start;
* then assigns storage locations for the
* parameters (which have been linked into a list,
* in order of appearance).
* This list is necessary because in
* f(a, b) float b; int a; ...
* the names are seen before the types.
* Also, the routine adjusts structures involved
* in some kind of forward-referencing.
register struct hshtab
*cs
;
paraml
= paraml
->hoffset
;
if ((cs
->htype
&XTYPE
) == ARRAY
) {
cs
->htype
=- (ARRAY
-PTR
); /* set ptr */
cs
->ssp
++; /* pop dims */
for (cs
=hshtab
; cs
<hshtab
+hshsiz
; cs
++) {
/* check tagged structure */
if (cs
->hclass
>KEYWC
&& (cs
->htype
&TYPE
)==RSTRUCT
) {
cs
->lenp
= dimtab
[cs
->lenp
&0377]->lenp
;
cs
->htype
= cs
->htype
&~TYPE
| STRUCT
;
if (cs
->hclass
== STRTAG
&& dimtab
[cs
->lenp
&0377]==0)
error("Undefined structure: %.8s", cs
->name
);
error("Not an argument: %.8s", cs
->name
);
outcode("BN", SETREG
, regvar
);
* After a function definition, delete local
* Also complain about undefineds.
register struct hshtab
*cs
;
for (cs
=hshtab
; cs
<hshtab
+hshsiz
; cs
++) {
if (cs
->hclass
==0 && (cs
->hflag
&FNUND
)==0) {
error("%.8s undefined", cs
->name
);
if((cs
->hflag
&FNDEL
)==0) {
cs
->hflag
=& ~(FNUND
|FFIELD
);
* write out special definitions of local symbols for
* benefit of the debugger. None of these are used
* by the assembler except to save them.
register struct hshtab
*cs
;
outcode("BSN", nkind
, cs
->name
, cs
->hoffset
);
* In case of error, skip to the next
while(o
>RBRACE
) /* ; { } */