home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
messroms.de
/
2007-01-13_www.messroms.de.zip
/
VZ200
/
TOOLS
/
ZCCSRC.ZIP
/
scc
/
stmt.c
< prev
next >
Wrap
C/C++ Source or Header
|
2000-03-06
|
7KB
|
497 lines
/* File stmt.c: 2.1 (83/03/20,16:02:17) */
/*% cc -O -c %
*
*/
#include <stdio.h>
#include "defs.h"
#include "data.h"
#include "proto.h"
/*
* statement parser
*
* called whenever syntax requires a statement. this routine
* performs that statement and returns a number telling which one
*
* 'func' is true if we require a "function_statement", which
* must be compound, and must contain "statement_list" (even if
* "declaration_list" is omitted)
*/
int statement(int func)
{
if ((ch() == 0) & feof(input))
return (0);
lastst = 0;
if (func)
{
if (match("{"))
{
compound(YES);
return (lastst);
}
else
error("function requires compound statement");
}
if (match("{"))
compound(NO);
else
stst();
return (lastst);
}
/*
* declaration
*/
int stdecl(void)
{
if (amatch("register", 8))
doldcls(DEFAUTO);
else
if (amatch("auto", 4))
doldcls(DEFAUTO);
else
if (amatch("static", 6))
doldcls(LSTATIC);
else
if (doldcls(AUTO))
;
else
return (NO);
return (YES);
}
int doldcls(int stclass)
{
blanks();
if (amatch("char", 4))
declloc(CCHAR, stclass);
else
if (amatch("int", 3))
declloc(CINT, stclass);
else
if (stclass == LSTATIC || stclass == DEFAUTO)
declloc(CINT, stclass);
else
return (0);
ns();
return (1);
}
/*
* non-declaration statement
*/
void stst(void)
{
if (amatch("if", 2))
{
doif();
lastst = STIF;
}
else
if (amatch("while", 5))
{
dowhile();
lastst = STWHILE;
}
else
if (amatch("switch", 6))
{
doswitch();
lastst = STSWITCH;
}
else
if (amatch("do", 2))
{
dodo();
ns();
lastst = STDO;
}
else
if (amatch("for", 3))
{
dofor();
lastst = STFOR;
}
else
if (amatch("return", 6))
{
doreturn();
ns();
lastst = STRETURN;
}
else
if (amatch("break", 5))
{
dobreak();
ns();
lastst = STBREAK;
}
else
if (amatch("continue", 8))
{
docont();
ns();
lastst = STCONT;
}
else
if (match(";"))
;
else
if (amatch("case", 4))
{
docase();
lastst = statement(NO);
}
else
if (amatch("default", 7))
{
dodefault();
lastst = statement(NO);
}
else
if (match("#asm"))
{
doasm();
lastst = STASM;
}
else
if (match("asm"))
asmfunc();
else
if (match("#line") | match("#"))
kill();
else
if (match("{"))
compound(NO);
else
{
expression(YES);
/*
if (match (":"))
{
dolabel();
lastst = statement (NO);
}
else
{
*/
ns();
lastst = STEXP;
/*
}
*/
}
}
/*
* compound statement
*
* allow any number of statements to fall between "{" and "}"
*
* 'func' is true if we are in a "function_statement", which
* must contain "statement_list"
*/
void compound(int func)
{
int decls;
decls = YES;
ncmp++;
while (!match("}"))
{
if (feof(input))
return;
if (decls)
{
if (!stdecl())
decls = NO;
}
else
stst();
}
ncmp--;
}
/*
* "if" statement
*/
void doif(void)
{
int fstkp, flab1, flab2;
char *flev;
flev = locptr;
fstkp = stkp;
flab1 = getlabel();
test(flab1, FALSE);
statement(NO);
stkp = modstk(fstkp);
locptr = flev;
if (!amatch("else", 4))
{
gnlabel(flab1);
return;
}
jump(flab2 = getlabel());
gnlabel(flab1);
statement(NO);
stkp = modstk(fstkp);
locptr = flev;
gnlabel(flab2);
}
/*
* "while" statement
*/
void dowhile(void)
{
int ws[7];
ws[WSSYM] = (int)locptr;
ws[WSSP] = stkp;
ws[WSTYP] = WSWHILE;
ws[WSTEST] = getlabel();
ws[WSEXIT] = getlabel();
addwhile(ws);
gnlabel(ws[WSTEST]);
test(ws[WSEXIT], FALSE);
statement(NO);
jump(ws[WSTEST]);
gnlabel(ws[WSEXIT]);
locptr = (char *)ws[WSSYM];
stkp = modstk(ws[WSSP]);
delwhile();
}
/*
* "do" statement
*/
void dodo(void)
{
int ws[7];
ws[WSSYM] = (int)locptr;
ws[WSSP] = stkp;
ws[WSTYP] = WSDO;
ws[WSBODY] = getlabel();
ws[WSTEST] = getlabel();
ws[WSEXIT] = getlabel();
addwhile(ws);
gnlabel(ws[WSBODY]);
statement(NO);
if (!match("while"))
{
error("missing while");
return;
}
gnlabel(ws[WSTEST]);
test(ws[WSBODY], TRUE);
gnlabel(ws[WSEXIT]);
locptr = (char *)ws[WSSYM];
stkp = modstk(ws[WSSP]);
delwhile();
}
/*
* "for" statement
*/
void dofor(void)
{
int ws[7], *pws;
ws[WSSYM] = (int)locptr;
ws[WSSP] = stkp;
ws[WSTYP] = WSFOR;
ws[WSTEST] = getlabel();
ws[WSINCR] = getlabel();
ws[WSBODY] = getlabel();
ws[WSEXIT] = getlabel();
addwhile(ws);
pws = readwhile();
needbrack("(");
if (!match(";"))
{
expression(YES);
ns();
}
gnlabel(pws[WSTEST]);
if (!match(";"))
{
expression(YES);
testjump(pws[WSBODY], TRUE);
jump(pws[WSEXIT]);
ns();
}
else
pws[WSTEST] = pws[WSBODY];
gnlabel(pws[WSINCR]);
if (!match(")"))
{
expression(YES);
needbrack(")");
jump(pws[WSTEST]);
}
else
pws[WSINCR] = pws[WSTEST];
gnlabel(pws[WSBODY]);
statement(NO);
jump(pws[WSINCR]);
gnlabel(pws[WSEXIT]);
locptr = (char *)pws[WSSYM];
stkp = modstk(pws[WSSP]);
delwhile();
}
/*
* "switch" statement
*/
void doswitch(void)
{
int ws[7];
int *ptr;
ws[WSSYM] = (int)locptr;
ws[WSSP] = stkp;
ws[WSTYP] = WSSWITCH;
ws[WSCASEP] = swstp;
ws[WSTAB] = getlabel();
ws[WSDEF] = ws[WSEXIT] = getlabel();
addwhile(ws);
immed();
printlabel(ws[WSTAB]);
nl();
gpush();
needbrack("(");
expression(YES);
needbrack(")");
stkp = stkp + intsize(); /* '?case' will adjust the stack */
gjcase();
statement(NO);
ptr = readswitch();
jump(ptr[WSEXIT]);
dumpsw(ptr);
gnlabel(ptr[WSEXIT]);
locptr = (char *)ptr[WSSYM];
stkp = modstk(ptr[WSSP]);
swstp = ptr[WSCASEP];
delwhile();
}
/*
* "case" label
*/
void docase(void)
{
int val;
val = 0;
if (readswitch())
{
if (!cexpr(&val))
if (!pstr(&val))
error("bad case label");
addcase(val);
if (!match(":"))
error("missing colon");
}
else
error("no active switch");
}
/*
* "default" label
*/
void dodefault(void)
{
int *ptr, lab;
if (NULL!=(ptr = readswitch()))
{
ptr[WSDEF] = lab = getlabel();
gnlabel(lab);
if (!match(":"))
error("missing colon");
}
else
error("no active switch");
}
/*
* "return" statement
*/
void doreturn(void)
{
if (endst() == 0)
expression(YES);
jump(fexitlab);
}
/*
* "break" statement
*/
void dobreak(void)
{
int *ptr;
if ((ptr = readwhile()) == 0)
return;
modstk(ptr[WSSP]);
jump(ptr[WSEXIT]);
}
/*
* "continue" statement
*/
void docont(void)
{
int *ptr;
if ((ptr = findwhile()) == 0)
return;
modstk(ptr[WSSP]);
if (ptr[WSTYP] == WSFOR)
jump(ptr[WSINCR]);
else
jump(ptr[WSTEST]);
}
/*
* dump switch table
*/
void dumpsw(int ws[])
{
int i, j;
gdata();
gnlabel(ws[WSTAB]);
if (ws[WSCASEP] != swstp)
{
j = ws[WSCASEP];
while (j < swstp)
{
defword();
i = 4;
while (i--)
{
onum(swstcase[j]);
outbyte(',');
printlabel(swstlab[j++]);
if (i == 0 || j >= swstp)
{
nl();
break;
}
outbyte(',');
}
}
}
defword();
printlabel(ws[WSDEF]);
outstr(",0");
nl();
gtext();
}