if(dclcontext != PEXTERN)
fatal("funchdr: dclcontext");
dclcontext = PAUTO;
+ markdcl("func");
funcargs(n->type);
if(n->type->thistuple > 0) {
if(dclcontext != PAUTO)
fatal("funcbody: dclcontext");
dclcontext = PEXTERN;
+ popdcl("func");
}
/*
}
void
-popdcl(void)
+popdcl(char *why)
{
Sym *d, *s;
if(debug['d'])
print("\t%ld pop %S\n", curio.lineno, s);
}
- if(d != S)
- d = d->link;
- dclstack = d;
+ if(d == S)
+ fatal("popdcl: no mark");
+ if(strcmp(why, d->package) != 0)
+ fatal("popdcl: pushed as %s poped as %s", d->package, why);
+ dclstack = d->link;
}
void
-markdcl(void)
+poptodcl(void)
+{
+ Sym *d, *s;
+
+ for(d=dclstack; d!=S; d=d->link) {
+ if(d->name == nil)
+ break;
+ s = pkglookup(d->name, d->package);
+ dcopy(s, d);
+ if(debug['d'])
+ print("\t%ld pop %S\n", curio.lineno, s);
+ }
+ if(d == S)
+ fatal("poptodcl: no mark");
+}
+
+void
+markdcl(char *why)
{
Sym *d;
d = push();
d->name = nil; // used as a mark in fifo
+ d->package = why; // diagnostic for unmatched
// if(debug['d'])
// print("markdcl\n");
}
{
Sym *d, *s;
- markdcl();
+ markdcl("fnlit");
// copy the entire pop of the stack
// all the way back to block0.
}
}
+void
+testdclstack(void)
+{
+ Sym *d;
+
+ for(d=dclstack; d!=S; d=d->link) {
+ if(d->name == nil) {
+ yyerror("mark left on the stack");
+ continue;
+ }
+ }
+}
+
void
addvar(Node *n, Node *t, int ctxt)
{
Node* dostruct(Node*, int);
Node** stotype(Node*, Node**, Node*);
Node* sortinter(Node*);
-void markdcl(void);
-void popdcl(void);
+void markdcl(char*);
+void popdcl(char*);
+void poptodcl(void);
void markdclstack(void);
+void testdclstack(void);
Sym* pushdcl(Sym*);
void addvar(Node*, Node*, int);
void addtyp(Node*, Node*, int);
{
if(debug['f'])
frame(1);
+ testdclstack();
}
package:
LFOR for_stmt
{
/* FOR and WHILE are the same keyword */
- popdcl();
+ popdcl("for/while");
$$ = $2;
}
| LSWITCH if_stmt
{
- popdcl();
+ popdcl("if/switch");
if(!casebody($2->nbody))
yyerror("switch statement must have case labels");
$$ = $2;
}
| LIF if_stmt
{
- popdcl();
+ popdcl("if/switch");
$$ = $2;
}
| LIF if_stmt LELSE else_stmt
{
- popdcl();
+ popdcl("if/switch");
$$ = $2;
$$->nelse = $4;
}
| LRANGE range_stmt
{
- popdcl();
+ popdcl("range");
$$ = $2;
}
| LRETURN oexpr_list ';'
// will be converted to OCASE
// right will point to next case
// done in casebody()
- popdcl();
- markdcl();
+ poptodcl();
$$ = nod(OXCASE, $2, N);
}
| LDEFAULT ':'
{
- popdcl();
- markdcl();
+ poptodcl();
$$ = nod(OXCASE, N, N);
}
| LFALL ';'
compound_stmt:
'{'
{
- markdcl();
+ markdcl("compound");
} ostmt_list '}'
{
$$ = $3;
if($$ == N)
$$ = nod(OEMPTY, N, N);
- popdcl();
+ popdcl("compound");
}
for_header:
}
for_stmt:
- { markdcl(); } for_body
+ {
+ markdcl("for/while");
+ } for_body
{
$$ = $2;
}
}
if_stmt:
- { markdcl(); } if_body
+ {
+ markdcl("if/switch");
+ } if_body
{
$$ = $2;
}
}
range_stmt:
- { markdcl(); } range_body
+ {
+ markdcl("range");
+ } range_body
{
$$ = $2;
}
fnliteral:
fnlitdcl '{' ostmt_list '}'
{
- popdcl();
+ popdcl("fnlit");
vargen++;
snprint(namebuf, sizeof(namebuf), "_f%.3ld", vargen);