mirror of
https://github.com/SEPPDROID/Digital-Research-Source-Code.git
synced 2025-10-25 09:24:19 +00:00
Upload
Digital Research
This commit is contained in:
507
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/c/fparser/stmt.c
Normal file
507
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/c/fparser/stmt.c
Normal file
@@ -0,0 +1,507 @@
|
||||
/*
|
||||
Copyright 1982
|
||||
Alcyon Corporation
|
||||
8716 Production Ave.
|
||||
San Diego, Ca. 92121
|
||||
*/
|
||||
|
||||
#include "parser.h"
|
||||
#define labgen(l,sl) sl=l;l=nextlabel++;
|
||||
int swp -1;
|
||||
|
||||
|
||||
/* stmt - process a single statement*/
|
||||
stmt() /* returns - none*/
|
||||
{
|
||||
register int token, lab, i;
|
||||
register struct tnode *tp;
|
||||
register char *p;
|
||||
|
||||
while( 1 ) {
|
||||
switch(token=gettok()) {
|
||||
|
||||
case LCURBR: /*handle { ... }*/
|
||||
while( !next(EOF) ) {
|
||||
if( next(RCURBR) )
|
||||
return;
|
||||
stmt();
|
||||
}
|
||||
case EOF:
|
||||
error("{ not matched by }");
|
||||
case SEMI: /*null statement*/
|
||||
return;
|
||||
|
||||
case RCURBR:
|
||||
pbtok(token);
|
||||
return;
|
||||
|
||||
case SYMBOL: /*symbol: statement*/
|
||||
if( peekc(':') ) {
|
||||
dolabel();
|
||||
continue;
|
||||
}
|
||||
default: /*anything else...*/
|
||||
pbtok(token);
|
||||
outexpr(expr());
|
||||
break;
|
||||
|
||||
case RESWORD:
|
||||
switch(cvalue) {
|
||||
|
||||
case R_BREAK:
|
||||
lab = brklabel();
|
||||
outgoto(lab); /*branch to break label*/
|
||||
break;
|
||||
|
||||
case R_CASE:
|
||||
docase();
|
||||
continue;
|
||||
|
||||
case R_CONTINUE:
|
||||
lab = contlabel(); /*branch to continue label*/
|
||||
outgoto(lab);
|
||||
break;
|
||||
|
||||
case R_DEFAULT:
|
||||
dodefault();
|
||||
continue;
|
||||
|
||||
case R_DO:
|
||||
dodo();
|
||||
break;
|
||||
|
||||
case R_FOR:
|
||||
dofor();
|
||||
return;
|
||||
|
||||
case R_GOTO:
|
||||
lab = gotolabel();
|
||||
outgoto(lab);
|
||||
break;
|
||||
|
||||
case R_IF:
|
||||
doif();
|
||||
return;
|
||||
|
||||
case R_RETURN:
|
||||
doreturn();
|
||||
break;
|
||||
|
||||
case R_SWITCH:
|
||||
doswitch();
|
||||
return;
|
||||
|
||||
case R_WHILE:
|
||||
dowhile();
|
||||
return;
|
||||
|
||||
default:
|
||||
synerr("invalid keyword");
|
||||
return;
|
||||
}
|
||||
}
|
||||
if( !next(SEMI) )
|
||||
synerr("missing semicolon");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* balpar - handle expression within parenthesis for while and if*/
|
||||
/* Merely checks for left and right parens and builds expression.*/
|
||||
char *balpar() /* returns pointer to expression*/
|
||||
{
|
||||
register struct tnode *tp;
|
||||
|
||||
if( next(LPAREN) ) {
|
||||
reducep = 1;
|
||||
tp = expr();
|
||||
reducep = 0;
|
||||
if( next(RPAREN) )
|
||||
return(tp);
|
||||
}
|
||||
synerr("parenthesized expression syntax");
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* synerr - syntax error*/
|
||||
/* Outputs error message and tries to resyncronize input.*/
|
||||
synerr(s,x1,x2,x3,x4,x5,x6) /* returns - none*/
|
||||
char *s; /* printf format string*/
|
||||
int x1, x2, x3, x4, x5, x6; /* printf arguments*/
|
||||
{
|
||||
register int token;
|
||||
|
||||
error(s,x1,x2,x3,x4,x5,x6);
|
||||
while( (token=gettok()) != SEMI && token != EOF && token != LCURBR &&
|
||||
token != RCURBR )
|
||||
;
|
||||
pbtok(token);
|
||||
}
|
||||
|
||||
/* gotolabel - gets label id for goto*/
|
||||
/* This is used for both: goto symbol and if(...)goto symbol*/
|
||||
gotolabel() /* returns 0 if not, else label id*/
|
||||
{
|
||||
register struct symbol *sp;
|
||||
|
||||
if( !next(SYMBOL) )
|
||||
synerr("expected label");
|
||||
else {
|
||||
sp = csp;
|
||||
if( !(sp->s_sc) ) {
|
||||
sp->s_type = LLABEL;
|
||||
if( !sp->s_offset )
|
||||
sp->s_offset = nextlabel++;
|
||||
}
|
||||
if( (!sp->s_sc || sp->s_sc == STATIC ) && sp->s_type == LLABEL )
|
||||
return(sp->s_offset);
|
||||
synerr("invalid label");
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* dolabel - do statement label*/
|
||||
/* Checks current symbol for already being defined, then sets*/
|
||||
/* symbol attributes for label.*/
|
||||
dolabel() /* returns - none*/
|
||||
{
|
||||
register struct symbol *sp;
|
||||
|
||||
sp = csp;
|
||||
if( sp->s_sc )
|
||||
error("label redeclaration: %.8s",sp->s_symbol);
|
||||
else {
|
||||
sp->s_attrib =| SDEFINED;
|
||||
sp->s_sc = STATIC;
|
||||
sp->s_type = LLABEL;
|
||||
if( !sp->s_offset )
|
||||
sp->s_offset = nextlabel++;
|
||||
outlab(sp->s_offset);
|
||||
}
|
||||
}
|
||||
|
||||
/* brklabel - generate break label*/
|
||||
/* Checks if break label is undefined, and if so, generates message*/
|
||||
brklabel() /* returns label number*/
|
||||
{
|
||||
if( !blabel )
|
||||
error("invalid break statement");
|
||||
return(blabel);
|
||||
}
|
||||
|
||||
/* contlabel - generate continue label*/
|
||||
/* Checks if continue label is undefined, and if so, generates message*/
|
||||
contlabel() /* returns label number*/
|
||||
{
|
||||
if( !clabel )
|
||||
error("invalid continue statement");
|
||||
return(clabel);
|
||||
}
|
||||
|
||||
/* docase - handles: case constant : statement*/
|
||||
/* Checks for being in a switch statement, adds entry to switch table*/
|
||||
docase() /* returns - none*/
|
||||
{
|
||||
register int value, lab;
|
||||
|
||||
colonstop++;
|
||||
value = cexpr(); /*get case value*/
|
||||
colonstop--;
|
||||
if( !next(COLON) ) /*check for colon*/
|
||||
synerr("missing colon");
|
||||
if( swp < 0 )
|
||||
error("case not inside a switch block");
|
||||
else if( swp >= (SWSIZE-1) )
|
||||
error("too many cases in switch");
|
||||
else {
|
||||
addswitch(&swtab[cswp],swp-cswp,value,lab=nextlabel++);
|
||||
outlab(lab);
|
||||
swp++;
|
||||
}
|
||||
}
|
||||
|
||||
/* dodefault - handles: default : statement*/
|
||||
/* Checks for colon and being in a switch statement*/
|
||||
dodefault() /* returns - none*/
|
||||
{
|
||||
if( !next(COLON) )
|
||||
error("missing colon");
|
||||
if( swp < 0 )
|
||||
error("default not inside a switch block");
|
||||
else {
|
||||
dlabel = nextlabel++; /*allocate default label*/
|
||||
outlab(dlabel); /*output default label*/
|
||||
}
|
||||
}
|
||||
|
||||
/* dodo - handles: do statement while ( expression )*/
|
||||
dodo() /* returns - none*/
|
||||
{
|
||||
register int lab, saveblab, saveclab;
|
||||
|
||||
labgen(blabel,saveblab);
|
||||
labgen(clabel,saveclab);
|
||||
lab = nextlabel++;
|
||||
outlab(lab); /*branch back to here*/
|
||||
stmt(); /*do statement*/
|
||||
outlab(clabel); /*continue label*/
|
||||
if( !nextrw(R_WHILE) ) {
|
||||
error("missing while"); /*only advisory...*/
|
||||
outgoto(lab);
|
||||
}
|
||||
else
|
||||
outifgoto(balpar(),TRUE,lab); /*while expression*/
|
||||
outlab(blabel); /*break label*/
|
||||
blabel = saveblab; /*restore labels*/
|
||||
clabel = saveclab;
|
||||
}
|
||||
|
||||
/*
|
||||
* dofor - handle: for ( expression ; expression ; expression ) statement
|
||||
* Hard part is handling re-initialization expression, which is
|
||||
* parsed and saved, then the statement is parsed, then the reinit
|
||||
* clause expression tree is output.
|
||||
*/
|
||||
dofor() /* returns - none*/
|
||||
{
|
||||
register int lab, saveblab, saveclab, reinit, clineno;
|
||||
register char *savep;
|
||||
register struct tnode *tp;
|
||||
|
||||
labgen(blabel,saveblab);
|
||||
labgen(clabel,saveclab);
|
||||
if( !next(LPAREN) ) {
|
||||
forerr:
|
||||
synerr("invalid for statement");
|
||||
return;
|
||||
}
|
||||
if( !next(SEMI) ) { /*do init expression*/
|
||||
outexpr(expr());
|
||||
if( !next(SEMI) )
|
||||
goto forerr;
|
||||
}
|
||||
outlab(clabel); /*branch back to here*/
|
||||
if( !next(SEMI) ) { /*do for condition*/
|
||||
outifgoto(expr(),FALSE,blabel);
|
||||
if( !next(SEMI) )
|
||||
goto forerr;
|
||||
}
|
||||
if( next(RPAREN) ) { /*no re-init - easy case*/
|
||||
stmt(); /*output statement*/
|
||||
outgoto(clabel); /*output continue label*/
|
||||
}
|
||||
else { /*there is a re-init clause*/
|
||||
labgen(clabel,lab);
|
||||
savep = exprp;
|
||||
tp = expr(); /*save re-init tree until done*/
|
||||
exprp = opap; /*remember until reinit is output*/
|
||||
reinit = lineno;
|
||||
if( !next(RPAREN) )
|
||||
goto forerr;
|
||||
stmt(); /*do statment*/
|
||||
clineno = lineno;
|
||||
lineno = reinit;
|
||||
outlab(clabel); /*we branch to here for reinit*/
|
||||
outexpr(tp); /*output re-init clause*/
|
||||
exprp = savep;
|
||||
lineno = clineno;
|
||||
outgoto(lab); /*branch back to top of loop*/
|
||||
}
|
||||
outlab(blabel); /*break to here*/
|
||||
blabel = saveblab;
|
||||
clabel = saveclab; /*restore labels*/
|
||||
}
|
||||
|
||||
/* doif - handles: if ( expression ) statement [ else statement ]*/
|
||||
/* Handles special cases for goto, break, continue and return.*/
|
||||
doif() /* returns - none*/
|
||||
{
|
||||
register struct tnode *tp;
|
||||
register int elselab, exitlab;
|
||||
|
||||
tp = balpar(); /*if( expr )...*/
|
||||
exitlab = 0;
|
||||
if( nextrw(R_GOTO) )
|
||||
exitlab = gotolabel();
|
||||
else if( nextrw(R_BREAK) )
|
||||
exitlab = brklabel();
|
||||
else if( nextrw(R_CONTINUE) )
|
||||
exitlab = contlabel();
|
||||
else if( nextrw(R_RETURN) ) {
|
||||
if( peekc(';') ) {
|
||||
exitlab = rlabel;
|
||||
putback(';');
|
||||
}
|
||||
else
|
||||
pbtok(RESWORD);
|
||||
}
|
||||
if( exitlab ) { /*easy goto, do branch if true*/
|
||||
outifgoto(tp,TRUE,exitlab);
|
||||
if( !next(SEMI) )
|
||||
synerr("missing semicolon");
|
||||
if( nextrw(R_ELSE) ) /*else clause, just output it*/
|
||||
stmt();
|
||||
}
|
||||
else { /*hard goto, branch over statement*/
|
||||
elselab = nextlabel++;
|
||||
outifgoto(tp,FALSE,elselab);
|
||||
stmt();
|
||||
if( nextrw(R_ELSE) ) {
|
||||
exitlab = nextlabel++; /*branches over else clause*/
|
||||
outgoto(exitlab); /*branch out of then clause*/
|
||||
outlab(elselab); /*label to start else clause*/
|
||||
stmt(); /*else statement*/
|
||||
outlab(exitlab);
|
||||
}
|
||||
else
|
||||
outlab(elselab); /*no else, just branch out*/
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* doreturn - handles: return [ expression ] ;
|
||||
* Expression is the hard part, must create an assignment expression
|
||||
* to assign expression to the type of the function, then get it
|
||||
* loaded into a specific register.
|
||||
*/
|
||||
doreturn() /* returns - none*/
|
||||
{
|
||||
register struct tnode *tp;
|
||||
|
||||
if( !peekc(';') ) /*need to compute return?*/
|
||||
outforreg(FRETURN,frp,expr());
|
||||
else
|
||||
putback(';');
|
||||
outgoto(rlabel); /*branch to the return label*/
|
||||
}
|
||||
|
||||
/*
|
||||
* doswitch - handles: switch ( expression ) statement
|
||||
* Evaluates the expression, forces the result into a known register
|
||||
* collects the case statements in swtab, then outputs the switch
|
||||
* operator and switch cases.
|
||||
*/
|
||||
doswitch() /* returns - none*/
|
||||
{
|
||||
register int saveblab, swlab, savedlab, saveswp, i;
|
||||
register struct tnode *tp;
|
||||
|
||||
labgen(blabel,saveblab);
|
||||
tp = balpar();
|
||||
integral(tp,-1); /*must be integral type result*/
|
||||
outforreg(ASSIGN,snalloc(INT,AUTO,0,0,0),tp);
|
||||
saveswp = swp; /*remember old switch pointer*/
|
||||
if( saveswp < 0 )
|
||||
swp++;
|
||||
i = cswp;
|
||||
cswp = swp; /*remember real first entry*/
|
||||
swlab = nextlabel++;
|
||||
outgoto(swlab); /*branch to switch code*/
|
||||
savedlab = dlabel;
|
||||
dlabel = 0;
|
||||
stmt(); /*do switch statement*/
|
||||
outgoto(blabel); /*output branch just in case*/
|
||||
outlab(swlab); /*here we now do the switch code*/
|
||||
if( !dlabel )
|
||||
dlabel = blabel;
|
||||
outswitch(swp-cswp,dlabel,&swtab[cswp]);
|
||||
outlab(blabel); /*break to here*/
|
||||
cswp = i;
|
||||
swp = saveswp;
|
||||
blabel = saveblab;
|
||||
dlabel = savedlab;
|
||||
}
|
||||
|
||||
/* dowhile - handles: while ( expression ) statement*/
|
||||
/* This is fairly straight-forward.*/
|
||||
dowhile() /* returns - none*/
|
||||
{
|
||||
register int saveclab, saveblab;
|
||||
|
||||
labgen(blabel,saveblab);
|
||||
labgen(clabel,saveclab);
|
||||
outlab(clabel); /*continue label*/
|
||||
outifgoto(balpar(),FALSE,blabel); /*condition clause*/
|
||||
stmt(); /*statement*/
|
||||
outgoto(clabel); /*branch back to top of loop*/
|
||||
outlab(blabel); /*break to here*/
|
||||
blabel = saveblab;
|
||||
clabel = saveclab; /*restore labels*/
|
||||
}
|
||||
|
||||
/* nextrw - is next token the specified reserved word?*/
|
||||
nextrw(rw) /* returns 1 if match, 0 otherwise*/
|
||||
int rw; /* reserved word to match*/
|
||||
{
|
||||
register int token;
|
||||
|
||||
if( (token=gettok()) != RESWORD || cvalue != rw ) {
|
||||
pbtok(token);
|
||||
return(0);
|
||||
}
|
||||
return(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* addswitch - add an entry into current switch table, bubble sorting
|
||||
* This makes it easier on the code generator and also checks for
|
||||
* duplicate labels at the "right" time.
|
||||
*/
|
||||
addswitch(sp,ncases,nval,nlab) /* returns - none*/
|
||||
struct swtch *sp; /* switch table pointer*/
|
||||
int ncases; /* number of cases in switch*/
|
||||
int nval; /* new value*/
|
||||
int nlab; /* new label*/
|
||||
{
|
||||
register struct swtch *nswp, *s;
|
||||
register int temp, i;
|
||||
|
||||
nswp = &sp[ncases];
|
||||
nswp->sw_value = nval;
|
||||
nswp->sw_label = nlab;
|
||||
s = nswp--;
|
||||
for( ; --ncases >= 0; s--, nswp-- ) {
|
||||
if( s->sw_value == nswp->sw_value )
|
||||
error("duplicate case value");
|
||||
if( s->sw_value < nswp->sw_value ) {
|
||||
temp = s->sw_value;
|
||||
s->sw_value = nswp->sw_value;
|
||||
nswp->sw_value = temp;
|
||||
temp = s->sw_label;
|
||||
s->sw_label = nswp->sw_label;
|
||||
nswp->sw_label = temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* outforreg - generate assignment for switch and return*/
|
||||
outforreg(op,ltp,rtp) /*returns - none*/
|
||||
int op; /*operator for build tree*/
|
||||
struct tnode *ltp; /*left expression tree*/
|
||||
struct tnode *rtp; /*right expression tree*/
|
||||
{
|
||||
register struct tnode *tp;
|
||||
|
||||
opp = opstack;
|
||||
opdp = opdstack;
|
||||
pushopd(ltp);
|
||||
pushopd(rtp);
|
||||
maketree(op);
|
||||
if( tp = popopd() )
|
||||
outcforreg(tp->t_right);
|
||||
opp = opdp = 0;
|
||||
}
|
||||
|
||||
/* outassign - generate assignment for function args*/
|
||||
outassign(ltp,rtp) /*returns - none*/
|
||||
struct tnode *ltp; /*left expression tree*/
|
||||
struct tnode *rtp; /*right expression tree*/
|
||||
{
|
||||
opp = opstack;
|
||||
opdp = opdstack;
|
||||
pushopd(ltp);
|
||||
pushopd(rtp);
|
||||
maketree(ASSIGN);
|
||||
outexpr(popopd());
|
||||
opp = opdp = 0;
|
||||
}
|
||||
Reference in New Issue
Block a user