home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Crawly Crypt Collection 1
/
crawlyvol1.bin
/
program
/
compiler
/
sozobon
/
scsrc20
/
hcc
/
fun.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-02-22
|
12KB
|
766 lines
/* Copyright (c) 1988,1991 by Sozobon, Limited. Author: Johann Ruegg
*
* Permission is granted to anyone to use this software for any purpose
* on any computer system, and to redistribute it freely, with the
* following restrictions:
* 1) No charge may be made other than reasonable charges for reproduction.
* 2) Modified versions must be clearly marked as such.
* 3) The authors are not responsible for any harmful consequences
* of using this software, even if they result from defects in it.
*
* fun.c
*
* Handle function entry, exit, etc.
* Parse statements.
* Also, general syntax error recovery strategy.
*/
#include <stdio.h>
#include "param.h"
#include "tok.h"
#include "nodes.h"
#include "cookie.h"
#if MMCC
overlay "pass2"
#endif
extern NODE *cur;
int level;
NODE *blktab;
NODE *labels;
struct swittbl {
NODEP caselist;
int deflbl;
} *curswit;
int curbrk, curcont;
int funtopl, funbotl, funretl, funstrl;
NODEP funtyp;
int maxregs;
long maxlocs;
int skipon;
NODEP glb_decls();
extern int oflags[];
#define debugl oflags['l'-'a']
#define debugs oflags['s'-'a']
#define debugv oflags['v'-'a']
findtok(x)
{
while (cur->e_token != EOFTOK && cur->e_token != x)
fadvnode();
if (cur->e_token == EOFTOK)
exit(1);
}
program()
{
extern NODEP symtab[];
NODEP last;
skipon = 0;
more:
last = glb_decls();
if (cur->e_token == EOFTOK)
return;
if (last) skipon = 0; /* saw something valid */
if (last && last->n_tptr && last->n_tptr->t_token == '(') {
/* possible function definition */
if (debugs) {
printf("FUN ");
put_nnm(last);
}
out_fstart(last);
#ifdef OUT_AZ
last->e_sc = HERE_SC;
#else
last->e_sc = K_EXTERN;
#endif
fun_start(last->n_tptr);
args_blk(last->n_tptr->n_right);
sub_block();
fun_end();
clr_lvl(); /* for args block */
goto more;
}
/* error if get to here */
if (last) {
error("missing ;");
goto more;
} else {
skip();
goto more;
}
}
fun_start(np)
NODEP np;
{
NODEP functy();
funtyp = functy(np);
curbrk = curcont = -1;
funtopl = new_lbl();
funbotl = new_lbl();
funretl = new_lbl();
switch (funtyp->t_token) {
case K_STRUCT:
case K_UNION:
funstrl = new_lbl();
break;
default:
funstrl = 0;
}
maxregs = 0;
maxlocs = 0;
out_br(funbotl);
def_lbl(funtopl);
}
fun_end()
{
NODEP np;
if (labels) {
for (np = labels; np; np = np->n_next)
if (np->c_defined == 0)
errorn("undefined label", np);
freenode(labels);
labels = NULL;
}
def_lbl(funretl);
out_fret(maxregs, funstrl);
def_lbl(funbotl);
out_fend(maxregs, maxlocs);
out_br(funtopl);
if (funstrl)
out_fs(funstrl, funtyp->t_size);
}
skip()
{
if (skipon == 0) {
error("syntax (try skipping...)");
skipon = 1;
}
fadvnode();
}
block()
{
int some;
int sawsome;
some = loc_decls();
if (cur->e_token == EOFTOK)
return;
if (some) skipon = 0;
more:
sawsome = stmts();
if (sawsome) skipon = 0;
if (cur->e_token == '}') {
maxregs |= blktab->b_regs;
if (blktab->b_size + blktab->b_tsize > maxlocs)
maxlocs = blktab->b_size + blktab->b_tsize;
return;
}
/* error if get to here */
if (cur->e_token == EOFTOK || is_tykw(cur->e_token))
/* get out of block */
return;
else {
skip();
goto more;
}
}
clr_lvl()
{
NODE *bp;
level--;
bp = blktab;
blktab = bp->n_next;
bp->n_next = NULL;
if (debugl && bp->b_syms) {
printf("local syms %d", level);
printlist(bp->b_syms);
}
#ifdef OUT_AZ
xrefl(bp->b_syms);
#endif
freenode(bp->b_syms);
if (debugl && bp->b_tags) {
printf("local tags %d", level);
printlist(bp->b_tags);
}
freenode(bp->b_tags);
freenode(bp);
}
eat(c)
{
char *p = "assume X";
if (cur->e_token == c)
fadvnode();
else {
p[strlen(p) - 1] = c;
error(p);
}
}
sub_block()
{
register NODE *new;
if (debugs)
printf("{ ");
eat('{');
level++;
new = allocnode();
new->n_next = blktab;
sprintf(new->n_name, "sub{");
blktab = new;
block();
clr_lvl();
eat('}');
if (debugs)
printf("}\n");
}
args_blk(np)
NODEP np;
{
register NODE *p;
register NODE *new;
NODE *tp;
NODEP llook();
long size;
int rmask;
size = 0;
rmask = 0;
new = allocnode();
new->n_next = blktab;
sprintf(new->n_name, "arg{");
blktab = new;
level++;
loc_decls();
/* make sure all decls were in arg list */
for (p=new->b_syms; p != NULL; p = p->n_next)
if (llook(np, p) == NULL)
errorn("ID not param", p);
/* now make any names not mentioned INT */
/* and generate offsets and alloc regs */
for (p=np; p != NULL; p = p->n_next) {
if ((tp=llook(new->b_syms, p)) == NULL) {
def_arg(&new->b_syms, p);
tp = new->b_syms;
}
lc_size(&size, &rmask, tp);
if (tp->e_sc == K_REGISTER)
reg_arg(&rmask, tp);
if (debugv) {
printf("final o%ld r%d ", tp->e_offs, tp->e_rno);
put_nnm(tp);
putchar('\n');
}
out_advice(tp);
}
new->b_regs = rmask;
}
reg_arg(rp, xp)
int *rp;
NODEP xp;
{
if (lc_reg(rp, xp) == 0) { /* out of regs? */
xp->e_sc = K_AUTO;
return;
}
out_argreg(xp);
}
stmts()
{
int didsome;
didsome = 0;
while (stmt())
didsome++;
return didsome;
}
stmt_bc(brk,cont)
{
int svb, svc;
svb = curbrk;
svc = curcont;
curbrk = brk;
curcont = cont;
stmt();
curbrk = svb;
curcont = svc;
}
stmt_b(brk)
{
int svb;
svb = curbrk;
curbrk = brk;
stmt();
curbrk = svb;
}
/* do a single statement */
stmt()
{
register tok;
NODEP np;
NODEP getexpr();
int i;
more:
tok = cur->e_token;
if (is_stkw(tok)) {
if (is_blkst(tok)) {
i = blk_stmt();
} else if (is_brast(tok)) {
i = bra_stmt();
} else if (is_lblst(tok)) {
i = lbl_stmt();
} else {
asm_stmt();
return 1;
}
if (i == 0)
goto more;
return 1;
}
else if (tok == '{') {
sub_block();
return 1;
} else if (tok == ';') {
fadvnode();
return 1;
}
np = getexpr();
if (np) {
if (cur->e_token == ':') {
fadvnode();
label(np);
goto more;
}
expr_stmt(np);
if (cur->e_token != ';')
error("missing ;");
else
fadvnode();
return 1;
}
return 0;
}
expr_stmt(np)
NODEP np;
{
if (debugs) {
printf("E_STMT ");
if (debugs > 1)
printnode(np);
}
do_expr(np, FORSIDE);
}
label(np)
NODEP np;
{
register NODEP tp;
NODEP llook();
if (debugs) {
printf("LABEL ");
if (debugs > 1)
printnode(np);
}
if (np->e_token != ID) {
error("weird label");
return;
}
tp = llook(labels, np);
if (tp) {
freenode(np);
if (tp->c_defined) {
error("duplicate label");
return;
}
} else {
putlist(&labels, np);
tp = np;
tp->c_casel = new_lbl();
}
tp->c_defined = 1;
def_lbl(tp->c_casel);
}
blk_stmt()
{
register tok;
int l1, l2, l3;
NODEP e1, e2, e3;
NODEP opt_expr(), paren_expr(), def_type();
struct swittbl locswit, *oldp;
extern int lineno;
int svline, svline2;
tok = cur->e_token;
fadvnode();
switch (tok) {
case K_IF:
if (debugs)
printf("IF ");
l1 = new_lbl();
e1 = paren_expr();
gen_brf(e1, l1);
eat(')');
stmt();
opt_else(l1);
return 1;
case K_WHILE:
if (debugs)
printf("WHILE ");
e1 = paren_expr();
l1 = new_lbl();
l2 = new_lbl();
def_lbl(l1);
gen_brf(e1,l2);
eat(')');
stmt_bc(l2,l1);
out_br(l1);
def_lbl(l2);
return 1;
case K_DO:
if (debugs)
printf("DO ");
l1 = new_lbl();
l2 = new_lbl();
l3 = new_lbl();
def_lbl(l1);
stmt_bc(l3,l2);
def_lbl(l2);
eat(K_WHILE);
e1 = paren_expr();
gen_brt(e1, l1);
eat(')');
eat(';');
def_lbl(l3);
return 1;
case K_FOR:
if (debugs)
printf("FOR ");
l1 = new_lbl();
l2 = new_lbl();
l3 = new_lbl();
eat('(');
e1 = opt_expr();
expr_stmt(e1);
eat(';');
def_lbl(l1);
e2 = opt_expr();
if (e2)
gen_brf(e2,l3);
eat(';');
e3 = opt_expr(); /* save for later */
svline = lineno;
eat(')');
stmt_bc(l3,l2);
def_lbl(l2);
svline2 = lineno;
lineno = svline;
expr_stmt(e3);
lineno = svline2;
out_br(l1);
def_lbl(l3);
return 1;
case K_SWITCH:
if (debugs)
printf("SWITCH ");
e1 = paren_expr();
l1 = new_lbl();
l2 = new_lbl();
to_d0(e1, def_type());
eat(')');
out_br(l2);
oldp = curswit;
curswit = &locswit;
locswit.caselist = NULL;
locswit.deflbl = -1;
stmt_b(l1);
out_br(l1);
def_lbl(l2);
gen_switch(locswit.caselist, locswit.deflbl);
curswit = oldp;
def_lbl(l1);
return 1;
case K_ELSE:
error("unexpected 'else'");
fadvnode();
return 0;
}
}
NODEP
paren_expr()
{
NODEP np;
NODEP need_expr();
eat('(');
np = need_expr();
return np;
}
bra_stmt()
{
register tok;
NODEP np, tp;
NODEP opt_expr(), llook();
tok = cur->e_token;
fadvnode();
switch (tok) {
case K_BREAK:
if (debugs)
printf("BRK");
eat(';');
out_br(curbrk);
return 1;
case K_CONTINUE:
if (debugs)
printf("CONT ");
eat(';');
out_br(curcont);
return 1;
case K_RETURN:
if (debugs)
printf("RETURN ");
np = opt_expr();
if (np) {
if (funstrl)
ret_stru(np);
else
to_d0(np, funtyp);
}
out_br(funretl);
eat(';');
return 1;
case K_GOTO:
if (debugs)
printf("GOTO ");
np = cur; advnode();
if (np->e_token != ID)
error("bad goto");
else {
tp = llook(labels, np);
if (tp) {
freenode(np);
} else {
tp = np;
putlist(&labels, tp);
tp->c_casel = new_lbl();
}
out_br(tp->c_casel);
}
eat(';');
return 1;
}
}
lbl_stmt()
{
register tok;
NODEP need_expr(), np;
int l1, i;
l1 = new_lbl();
tok = cur->e_token;
again:
fadvnode();
switch (tok) {
case K_CASE:
if (debugs)
printf("CASE ");
np = need_expr();
i = conxval(np);
if (curswit)
add_case(i,l1);
else
error("'case' outside switch");
eat(':');
break;
case K_DEFAULT:
if (debugs)
printf("DEFAULT ");
if (curswit) {
if (curswit->deflbl >= 0)
error("multiple 'default'");
curswit->deflbl = l1;
} else
error("'default' outside switch");
eat(':');
}
tok = cur->e_token; /* lookahead for more cases */
if (tok == K_CASE || tok == K_DEFAULT)
goto again;
def_lbl(l1);
return 0;
}
asm_stmt()
{
NODEP np, getexpr();
fadvnode();
np = getexpr();
if (np == NULL || np->e_token != SCON) {
error("bad asm() func");
} else {
out_asm(np);
freenode(np);
}
eat(';');
}
NODEP
opt_expr()
{
NODE *np, *getexpr();
np = getexpr();
if (np) {
if (debugs) {
printf("OXPR ");
if (debugs > 1)
printnode(np);
}
}
return np;
}
NODEP
need_expr()
{
NODE *np, *getexpr();
np = getexpr();
if (np) {
if (debugs) {
printf("NXPR ");
if (debugs > 1)
printnode(np);
}
} else
error("need expr");
return np;
}
opt_else(l1)
{
int l2;
if (cur->e_token == K_ELSE) {
if (debugs)
printf("ELSE ");
fadvnode();
l2 = new_lbl();
out_br(l2);
def_lbl(l1);
stmt();
def_lbl(l2);
} else
def_lbl(l1);
}
add_case(val, lbl)
{
NODEP np, last, p;
np = allocnode();
np->c_casev = val;
np->c_casel = lbl;
sprintf(np->n_name, "%d:%d", val, lbl);
last = NULL;
for (p = curswit->caselist; p; last=p, p=p->n_next)
if (p->c_casev == val) {
error("duplicate case");
return;
} else if (p->c_casev > val)
break;
if (last) {
last->n_next = np;
np->n_next = p;
} else {
curswit->caselist = np;
np->n_next = p;
}
if (debugs) {
printf("CASELIST\n");
printnode(curswit->caselist);
}
}
to_d0(np, typ)
NODEP np, typ;
{
NODEP tp;
tp = allocnode();
tp->e_token = TCONV;
tp->n_tptr = typ;
tp->n_flags |= N_COPYT;
tp->n_left = np;
tp->e_type = E_UNARY;
strcpy(tp->n_name, "r cast");
do_expr(tp, IND0);
}
ret_stru(np)
NODEP np;
{
p2_expr(&np);
if (same_type(np->n_tptr, funtyp) == 0) {
error("bad struct return type");
return;
}
genx(np, RETSTRU);
}