?? cdecl.c
字號:
{
struct_t * S;
int n;
S = EiC_getInf(type);
n = S->n;
S->n = 1; /* force initialisation of first member only */
initstruct(type,addr,lev+1);
S->n = n;
}
break;
default:
assign_var(type, *addr,0); break;
}
}
static void initstruct(type_expr * type, void **addr, int lev)
{
if(EiC_lexan() == '{' ) {
do_struct(type,addr,lev);
if(lev > 1 && EiC_lexan() != ',')
retractlexan();
EiC_match('}', " }");
} else {
retractlexan();
if(lev > 0)
do_struct(type,addr,lev);
else /* else intializer must be an expression of the same type */
assign_var(type,*addr,1);
}
}
static void do_struct(type_expr *type, void **addr,int lev)
{
struct_t *S;
int i;
S = EiC_getInf(type);
for(i=0;i<S->n;i++)
if(EiC_lexan() != '}') {
retractlexan();
*addr = (char*)*addr + S->offset[i];
initglobal(S->type[i],addr,lev+1);
*addr = (char*)*addr - S->offset[i];
if(EiC_lexan() != ',' && i != S->n-1)
retractlexan();
} else {
break;
}
retractlexan();
}
static int dostrlit(void ** addr,int ln, int sln, char * str)
{ /*
* parse eg. char a[] = "hello world";
* or char a[5] = "hello world";
*/
xmark(str,eicgstring); /* mark for garbage collector */
if(ln) {
if(sln >= ln)
EiC_warningerror("Array of chars is too long");
} else {
ln = sln+1; /* allow for null at end */
*addr = xrealloc(*addr,ln);
}
if(sln < ln)
memcpy(*addr,str,sln+1);
else
memcpy(*addr,str,ln);
return ln;
}
static int initarray(type_expr * type, void ** addr, int size, int lev)
{
static int INCREMENT;
if(EiC_gettype(type) == t_array) {
int t,tok,s;
if((tok =EiC_lexan()) == '{') {
t = EiC_get_sizeof(type);
if(lev == 0)
INCREMENT = t == 0 ? EiC_get_sizeof(nextType(type)): 0;
s = do_array(nextType(type),addr,t,lev,INCREMENT);
if(t == 0) {
int sz = EiC_get_sizeof(nextType(type));
if(sz)
t = s/sz;
else
EiC_error("Ilegal array domain in initialisation");
setNumElems(type,t);
}
EiC_match('}'," }");
} else if(tok == STR) { /* handle string literals */
if(EiC_gettype(nextType(type)) == t_char) {
size_t sln;
t = EiC_get_sizeof(type);
sln = (char*)token->Val.p.ep - (char*)token->Val.p.p - 1;
s = dostrlit(addr,t,sln,token->Val.p.p);
if(lev == 0 && t == 0)
setNumElems(type,s);
}else
EiC_error("Illegal initialisation");
} else{
retractlexan();
if(lev > 0) /* lev indicates a recusive call */
size = do_array(nextType(type),addr,size,lev,INCREMENT);
else
EiC_error("missing { in initialisation of an array");
}
} else
initglobal(type,addr,lev+1);
return size;
}
static int do_array(type_expr *type, void ** addr, int size, int lev, int inc)
{
int n = 0;
while(EiC_lexan() != '}') {
retractlexan();
if(n >= size) {
if(inc) {
size += inc;
*addr = xrealloc(*addr, size);
memset((char*)*addr + size - inc, 0, inc);
} else {
if(size)
EiC_error("Too many initialisers");
else
EiC_error("Illegal domain for initialisation");
}
}
*addr = (char*)*addr + n;
size = initarray(type,addr, size,lev+1);
*addr = (char*)*addr - n;
n += EiC_get_sizeof(type);
if (EiC_lexan() != ',')
break;
}
retractlexan();
return size;
}
static void assign_var(type_expr *type, void *addr,int allow)
{
int t;
token_t e1,e2;
void *EiC_getaddress(token_t *);
EiC_inittoken(&e2);
EiC_assign_expr(&e2);
#if 0
if(IsTemp(e2.Type))
EiC_clearTempories();
#endif
t = EiC_gettype(type);
if (isconst(e2.Type)) {
e1.Type = type;
EiC_castconst(&e2,&e1,0);
switch(t) {
case t_char:
case t_uchar: *(char*)addr = e2.Val.ival; break;
case t_short:
case t_ushort: *(short*)addr = e2.Val.ival; break;
case t_int:
case t_uint: *(int *)addr = e2.Val.ival; break;
case t_long:
case t_ulong: *(long*)addr = e2.Val.lval; break;
case t_llong: *(eic_llong*)addr = e2.Val.llval; break;
case t_float: *(float*)addr = e2.Val.dval; break;
case t_double: *(double*)addr = e2.Val.dval; break;
case t_pointer:
if(EiC_S_LEVEL == 1 && EiC_gettype(e2.Type) == t_pointer
&& EiC_gettype(nextType(e2.Type)) == t_char
&& !e2.Sym)
/* got string */
if(e2.Val.p.p)
EiC_SaveGlobalString(&e2.Val.p);
if(issafe(type))
*(ptr_t*)addr = e2.Val.p;
else
*(void**)addr = e2.Val.p.p;
break;
default:
EiC_error("Unknown initialiserXXX");
}
} else if(allow) {
val_t h;
token_t e3;
EiC_inittoken(&e3);
e3.Type = type;
EiC_output(&e2);
EiC_castvar(&e2,&e3,0);
if (t == t_struct || t == t_union)
structUnionCode(E1,&e2);
h = E1->Val;
E1->Val = E1->Sym->val;
EiC_concode(&E1->Code,&e2.Code);
EiC_do_stooutput(E1);
E1->Val = h;
} else {
if(EiC_GI(&e2) != 0) /* global or static addresses only are allowed */
EiC_error("Illegal initialization: illegal address operation");
else {
/*e1.Type = type;*/
/*EiC_output(&e2);*/
/*EiC_castvar(&e2,&e1,1);*/
if(EiC_gettype(type) == t_pointer ||
(e2.Sym && EiC_gettype(e2.Sym->type) == t_ref)) {
ptr_t p;
p.sp = p.p = EiC_getaddress(&e2);
p.ep = (char*)p.p + EiC_get_sizeof(e2.Type);
if(!EiC_sametypes(e2.Type,type))
EiC_warningerror("Suspicious pointer conversion");
if(issafe(type))
*(ptr_t*)addr = p;
else
*(void**)addr = p.p;
EiC_freecode(&e2.Code);
} else
EiC_error("Expected constant expression as an"
" initialiser");
}
}
EiC_freetoken(&e2);
}
static void decl(token_t * e1, int t)
{
type_expr *P = NULL;
switch (t) {
case '*':
P = pointer();
dir_decl(e1, EiC_lexan());
if(P)
e1->Type = EiC_catTypes(P,e1->Type);
break;
case ID:
case '(':
dir_decl(e1, t);
break;
default:
EiC_error("Declarator error");
retractlexan();
}
}
static type_expr * pointer(void)
{
type_expr *t = NULL;
do {
t = EiC_addtype(t_pointer,t);
if(EiC_lexan() == constsym || token->Tok == volatilesym) {
if(token->Tok == constsym) {
setConstp(t);
}
/*ignore volatilesym for now*/
EiC_lexan();
}
/* pointer qualifer */
if(token->Tok == safesym) {
unsetPtr(t);
setSafe(t);
EiC_lexan();
} else if(token->Tok == unsafesym) {
unsetPtr(t);
setUnSafe(t);
EiC_lexan();
}
} while (token->Tok == '*');
retractlexan();
return t;
}
static void dir_decl(token_t * e1, int t)
{
switch (t) {
case '(':
decl(e1, EiC_lexan());
EiC_match(')', " )");
f_dir_decl(e1);
break;
case ID:
init_ident(e1, EiC_work_tab);
f_dir_decl(e1);
break;
default:
EiC_error("Direct declarator error");
break;
}
}
static void f_dir_decl(token_t * e1)
{
while (1)
switch (EiC_lexan()) {
case '[':
array_decl(e1);
break;
case '(':
ff_dir_decl(e1);
if(INPARMLIST)
EiC_remlevel(EiC_S_LEVEL+1);
break;
default:
retractlexan();
return;
}
}
static void ff_dir_decl(token_t * e1)
{
int h;
switch ((h=EiC_lexan())) {
TYPEQUAL:
STORECLASS:
TYPESPEC:
EiC_S_LEVEL++;
RESET++;
h = LSP;
LSP = EiC_ENV->lsp;
retractlexan();
EiC_make_func(e1);
/*
* Use INPARMLIST to inform other
* modules that the following declarations
* are function parameters.
*/
INPARMLIST++;
PRAMHANDLE = e1->Type;
parm_type_list(EiC_getInf(e1->Type));
/*
* now pseudo reverse the parameter
* order.
*/
EiC_reset_env_pointers(e1, LSP);
LSP = h;
RESET--;
INPARMLIST--;
EiC_S_LEVEL--;
break;
case ')':
/*
* This should really be made illegal, it allows
* for function declarations with empty
* paramater list, such as:
* int f(); Therefore, force an implied t_var argument.
*/
{
type_expr * type;
EiC_make_func(e1);
type = EiC_addtype(t_var,NULL);
EiC_add_func_parm(EiC_getInf(e1->Type), &type, NULL);
EiC_freetype(type);
}
return;
default:
if(h == ID)
EiC_error("Unknown type '%s': possible "
"old C type declaration", token->Val.sym->id);
else
EiC_error("Syntax error");
}
EiC_match(')', " )");
}
static void UpDateParmSym(type_expr *ty, symentry_t *sym)
{
if(EiC_gettype(ty) == t_pointer && EiC_gettype(nextType(ty)) ==
t_funcdec)
if(EiC_gettype(sym->type) != t_pointer)
sym->type = EiC_addtype(t_pointer,sym->type);
}
static void parm_type_list(func_t * f)
{
extern int Pclash;
char * name = NULL;
token_t e2;
EiC_inittoken(&e2);
parm_decl(&e2);
/*
* Must watch out for void as a parameter.
* The void paramater will have no sym entry.
*/
if(e2.Val.sym) {
new_var(&e2);
#if 1
{
void EiC_adjustParam(type_expr **type);
EiC_adjustParam(&e2.Sym->type);
}
#endif
name = e2.Sym->id;
} else /* still must reverse type if needed */
e2.Type = EiC_revtype(e2.Type);
EiC_add_func_parm(f, &e2.Type,name);
if(!e2.Val.sym)
EiC_freetype(e2.Type);
else
UpDateParmSym(getFPty(f,getFNp(f)-1),e2.Val.sym);
if(Pclash)
Pclash = 0;
if (EiC_lexan() == ',')
f_parm_type_list(f);
else
retractlexan();
}
static void f_parm_type_list(func_t * f)
{
if (EiC_lexan() == '.') {
if (EiC_lexan() == '.')
if (EiC_lexan() == '.') {
type_expr *type;
type = EiC_addtype(t_var, NULL);
EiC_add_func_parm(f, &type,NULL);
EiC_freetype(type);
return;
}
retractlexan();
EiC_error("Expected ...");
} else {
retractlexan();
parm_type_list(f);
}
}
static void fff_parm_decl(token_t *e1);
static void ff_parm_decl(token_t *e1);
static void f_parm_decl(token_t * e1);
static void parm_decl(token_t * e1)
{
switch (EiC_lexan()) {
TYPEQUAL:
STORECLASS:
TYPESPEC:
decl_spec(e1);
f_parm_decl(e1);
break;
default:
if(token->Tok == ID)
EiC_error("Unknown type '%s'",token->Val.sym->id);
else
EiC_error("Parameter declaration error");
}
}
static void f_parm_decl(token_t * e1)
{
if(EiC_lexan() == '*') {
type_expr *P = NULL;
P = pointer();
ff_parm_decl(e1);
if(P)
e1->Type = EiC_catTypes(P,e1->Type);
} else {
retractlexan();
ff_parm_decl(e1);
}
}
static void ff_parm_decl(token_t *e1)
{
switch(EiC_lexan()) {
case ID: init_ident(e1, EiC_work_tab);
f_dir_decl(e1);
break;
case '(': fff_parm_decl(e1);
break;
case '[': retractlexan();
f_dir_decl(e1);
break;
default: /* null */
if(token->Tok != ',' && token->Tok != ')')
EiC_error("Parameter declaration error");
else
retractlexan();
return ;
}
}
static void fff_parm_decl(token_t *e1)
{
switch(EiC_lexan()) {
TYPEQUAL:
STORECLASS:
TYPESPEC:
retractlexan();
ff_dir_decl(e1);
EiC_remlevel(EiC_S_LEVEL+1);
break;
default:
retractlexan();
f_parm_decl(e1);
EiC_match(')', " ) ");
break;
}
f_dir_decl(e1);
}
static void enum_spec(token_t * e1)
{
e1->Type = EiC_addtype(t_enum, NULL);
f_enum_spec(e1);
}
static void f_enum_spec(token_t * e1)
{
int h, t, nxtt;
h = EiC_work_tab;
EiC_work_tab = tag_tab;
switch (EiC_lexan()) {
case ID: /* enumeration tag */
t = EiC_gettype(token->Val.sym->type);
nxtt = EiC_lexan();
retractlexan();
if (nxtt == '{' || t == ID) {
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -