📄 expr.c
字号:
/*
* 68K/386 32-bit C compiler.
*
* copyright (c) 1997, David Lindauer
*
* This compiler is intended for educational use. It may not be used
* for profit without the express written consent of the author.
*
* It may be freely redistributed, as long as this notice remains intact
* and either the original sources or derived sources
* are distributed along with any executables derived from the originals.
*
* The author is not responsible for any damages that may arise from use
* of this software, either idirect or consequential.
*
* v1.35 March 1997
* David Lindauer, gclind01@starbase.spd.louisville.edu
*
* Credits to Mathew Brandt for original K&R C compiler
*
*/
/*
* Evaluate expressions very recursive descent. MAke sure your STACK
* is large enough to parse the expressions you want to parse. a 4K stack
* will handle all but the very extreme cases
*/
#include <stdio.h>
#include "expr.h"
#include "c.h"
#include "errors.h"
#include "list.h"
extern int block_nesting;
extern int global_flag;
extern enum e_sym lastst;
extern char lastid[],laststr[];
extern TABLE gsyms,lsyms;
extern long ival;
extern long double rval;
/* Default types */
extern TYP stdint,stdlongdouble, stduns,stdstring;
TYP stdfloat = { bt_float, 0, UF_DEFINED | UF_USED,0, 0,-1, -1, 8, {0, 0}, 0, 0,0 };
TYP stddouble = { bt_double, 0, 0,0,0, -1, -1, 8, {0, 0}, 0, 0,0 };
TYP stdvoid = { bt_matchall, 0, 0 ,0, 0,-1, -1, 4, {0, 0}, 0, 0,0 };
TYP stdmatch = { bt_matchall, 0, UF_DEFINED | UF_USED,0, 0,-1, -1, 4, {0, 0}, &stdvoid, 0,0 };
TYP stdlong = {bt_long, 0, 0,0,0,-1, -1, 4, {0, 0}, 0, 0,0 };
TYP stdunsigned = {bt_unsigned, 0, 0,0,0,-1, -1, 4, {0, 0}, 0, 0,0 };
TYP stdchar = {bt_char, 0, 0,0,0,-1, -1, 1, {0, 0}, 0, 0,0 };
TYP stdfunc = {bt_func, 1, UF_DEFINED | UF_USED,0,0,-1, -1, 0, {0, 0}, &stdint, 0,0};
extern TYP *head; /* shared with decl */
extern TABLE tagtable;
extern char declid[100];
extern int goodcode;
extern int prm_cplusplus;
extern int regdsize,regasize,regfsize,stackadd,stackmod;
int skm_closepa[] = { closepa, comma, semicolon, end, 0 };
int skm_closebr[] = { closebr, comma, openbr, semicolon, end, 0 };
static SYM *lastsym;
static int globaldref = 0;
static char regname[] = "processor reg" ;
static char *nm = 0;
static TYP *asntyp = 0;
static int dumpos;
static SYM undef;
void exprini(void)
{
globaldref = 0;
asntyp = 0;
dumpos = 0;
undef.value.i = 0;
undef.name = "UNDEFINED";
}
ENODE *makenode(enum e_node nt, char *v1, char *v2)
/*
* build an expression node with a node type of nt and values
* v1 and v2.
*/
{ ENODE *ep;
ep = xalloc(sizeof(ENODE));
ep->nodetype = (char)nt;
ep->cflags = 0;
ep->v.p[0] = v1;
ep->v.p[1] = v2;
return ep;
}
TYP *deref(ENODE **node, TYP *tp)
/*
* build the proper dereference operation for a node using the
* type pointer tp.
*/
{
ENODE *onode = *node;
switch( tp->type ) {
case bt_double:
*node = makenode(en_doubleref,*node,0);
break;
case bt_longdouble:
*node = makenode(en_longdoubleref,*node,0);
break;
case bt_float:
*node = makenode(en_floatref,*node,0);
break;
case bt_unsignedchar:
*node = makenode(en_ub_ref,*node,0);
break;
case bt_unsignedshort:
*node = makenode(en_uw_ref,*node,0);
break;
case bt_char:
*node = makenode(en_b_ref,*node,0);
break;
case bt_short:
case bt_enum:
*node = makenode(en_w_ref,*node,0);
break;
case bt_unsigned:
*node = makenode(en_ul_ref,*node,0);
break;
case bt_long:
case bt_matchall:
case bt_pointer:
case bt_ptrfunc:
case bt_ref:
*node = makenode(en_l_ref,*node,0);
break;
default:
generror(ERR_DEREF,0,0);
break;
}
(*node)->cflags = onode->cflags;
return tp;
}
ENODE *dummyvar(int size, TYP *type)
{
char nm[20];
ENODE *newnode;
SYM *sp = xalloc(sizeof(SYM));
sprintf(nm,"**DUMMY%d",dumpos++);
sp->name = litlate(nm);
sp->defalt = 0;
sp->storage_class = sc_auto;
sp->tp = type;
type->uflags |= UF_USED;
sp->extflag = FALSE;
sp->absflag = FALSE;
sp->intflag = FALSE;
sp->pascaldefn = FALSE;
sp->init = 0;
sp->indecltable = 0;
sp->funcparm = 0;
sp->inreg = 0;
sp->staticlabel = FALSE;
sp->value.i = block_nesting;
insert(sp,&lsyms);
newnode = makenode(en_autocon,sp,0);
return newnode;
}
int isintconst(int type)
{
switch (type) {
case en_icon:
case en_lcon:
case en_lucon:
case en_iucon:
case en_ccon:
return 1;
}
return 0;
}
TYP *nameref(ENODE **node)
/*
* get an identifier. If it is followed by parenthesis gather the
* function parms. If it is an undefined function declare it as external
* for now.
*/
{ SYM *sp;
TYP *tp,*tp1;
ENODE *pnode=0,*qnode = 0;
int fn = FALSE;
char buf[100];
strcpy(buf,lastid);
getsym();
/* Get function args */
if (lastst == openpa) {
fn = TRUE;
getsym();
tp1 = gatherparms(&pnode);
sp = funcovermatch(buf,tp1);
if (sp)
tp1->sname = nm = sp->name;
else
#ifdef CPLUSPLUS
if (prm_cplusplus)
tp1->sname = nm = cppmangle(buf,tp1);
else
#endif
tp1->sname = nm = litlate(buf);
}
else {
nm = litlate(buf);
sp = gsearch(nm);
}
if( sp == 0 ) {
/* No such identifier */
if (fn) {
/* External function, put it in the symbol table */
#ifdef CPLUSPLUS
if (prm_cplusplus)
gensymerror(ERR_NOFUNCMATCH,nm);
else
#endif
gensymerror(ERR_NOPROTO,nm);
++global_flag;
sp = xalloc(sizeof(SYM));
sp->name = litlate(nm);
sp->tp = maketype(bt_func,0);
*(sp->tp) = stdfunc;
sp->storage_class = sc_externalfunc;
sp->extflag = TRUE;
insert(sp,&gsyms);
--global_flag;
*node = makenode(en_napccon,sp,0);
parmlist(&pnode,tp1,0);
*node = makenode(en_void,*node,pnode);
tp = &stdint;
qnode = makenode(en_icon,(char *)-4,0);
*node = makenode(en_fcall,qnode,*node);
goodcode |= GF_ASSIGN;
}
else {
/* External non-function. These also get put in the symbol table so that
* we don't keep spitting errors out but also put an error out
*/
#ifdef CPLUSPLUS
if (prm_cplusplus && asntyp && asntyp->type == bt_ptrfunc) {
sp = funcovermatch(lastid,asntyp);
if (sp)
goto foundsp;
}
#endif
sp = xalloc(sizeof(SYM));
sp->name = nm;
sp->tp = tp = &stdmatch;
sp->storage_class = sc_external;
insert(sp,&lsyms);
*node = makenode(en_nacon,&undef,0);
gensymerror(ERR_UNDEFINED,nm);
tp = deref(node,tp);
}
}
else {
/* If we get here the symbol was already in the table
*/
foundsp:
sp->tp->uflags |= UF_USED;
if( (tp = sp->tp) == 0 ) {
/* This lack of type info should never happen */
tp = &stdmatch;
*node = makenode(en_nacon,&undef,0);
gensymerror(ERR_UNDEFINED,nm);
tp = deref(node,tp);
return tp; /* guard against untyped entries */
}
switch( sp->storage_class ) {
case sc_static:
case sc_global:
case sc_external:
case sc_externalfunc:
case sc_abs:
sp->extflag = TRUE;
if (fn) {
/* make a function node */
if (sp->tp->type == bt_ptrfunc)
*node = makenode(en_nacon,sp,0);
else
*node = makenode(en_napccon,sp,0);
isfunc:
if (sp->tp->type != bt_ptrfunc && sp->tp->type != bt_func && sp->tp->type != bt_ifunc)
generror(ERR_MISMATCH,0,0);
if (sp->tp->type == bt_ptrfunc)
tp = deref(node,tp);
#ifdef CPLUSPLUS
if (prm_cplusplus && !strcmp(buf,"main"))
generror(ERR_NOMAIN,0,0);
#endif
parmlist(&pnode,tp1,sp->tp);
*node = makenode(en_void,*node,pnode);
qnode = makenode(en_icon,(char *)sp->tp->btp->size,0);
tp = tp->btp;
if (sp->intflag)
*node = makenode(en_intcall,qnode,*node);
else
if (tp->type == bt_union || tp->type == bt_struct) {
if (sp->pascaldefn)
*node = makenode(en_pfcallb,qnode,*node);
else
*node = makenode(en_fcallb,qnode,*node);
(*node)->size = tp->size;
}
else
if (sp->pascaldefn)
*node = makenode(en_pfcall,qnode,*node);
else
*node = makenode(en_fcall,qnode,*node);
if (tp)
(*node)->cflags = tp->cflags;
goodcode |= GF_ASSIGN;
}
else
/* otherwise make a node for a regular variable */
if (sp->absflag)
*node = makenode(en_absacon,sp,0);
else
if (sp->tp->type == bt_func || sp->tp->type == bt_ifunc) {
fn = TRUE;
*node = makenode(en_napccon,sp,0);
}
else
if (sp->staticlabel)
*node = makenode(en_nalabcon,(char *)sp->value.i,0);
else
*node = makenode(en_nacon,sp,0);
break;
case sc_const:
/* constants and enums */
*node = makenode(en_icon,(char *)sp->value.i,0);
return &stdint;
default: /* auto and any errors */
if( sp->storage_class != sc_auto && sp->storage_class != sc_autoreg) {
gensymerror(ERR_ILLCLASS2,sp->name);
tp = 0;
}
else {
/* auto variables */
if (sp->storage_class == sc_auto)
*node = makenode(en_autocon,sp,0);
else if (sp->storage_class == sc_autoreg)
*node = makenode(en_autoreg,sp,0);
if (fn)
goto isfunc;
}
break;
}
/* dereference if it isn't an array or structure address */
(*node)->cflags = tp->cflags;
/* deref if not an array or if is function parm */
if(!fn && tp && (tp->val_flag == 0 || (sp->funcparm && tp->type == bt_pointer)))
tp = deref(node,tp);
/* and dereference again if it is a refernece variable */
if (tp->type == bt_ref) {
tp = tp->btp;
tp = deref(node,tp);
}
}
lastsym = sp;
return tp;
}
void promote_type(TYP *typ, ENODE **node)
/*
* Type promotion for casts and function args
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -