blob: 5669c07c390b88db342289531cc5bb84774be991 [file] [log] [blame]
/* $VER: vbcc (parse_expr.c) $Revision: 1.22 $ */
#include "vbcc_cpp.h"
#include "vbc.h"
static char FILE_[]=__FILE__;
np new_node(void)
{
np p=mymalloc(NODES);
p->flags=0;
p->lvalue=0;
p->sidefx=0;
p->ntyp=0;
p->left=0;
p->right=0;
p->alist=0;
p->identifier=0;
p->o.flags=0;
return p;
}
np expression(void)
/* Komma-Ausdruecke */
{
np left,right,new;
left=assignment_expression();
if(!left->flags) return 0;
killsp();
while(ctok->type==COMMA){
#ifdef HAVE_MISRA
/* removed */
#endif
next_token();
killsp();
right=assignment_expression();
new=new_node();
new->left=left;
new->right=right;
new->ntyp=0;
new->flags=KOMMA;
left=new;
killsp();
}
return left;
}
np assignment_expression(void)
/* Zuweisungsausdruecke */
{
np left,new;int c=ASSIGNOP,op;
left=conditional_expression();
killsp();
switch(ctok->type){
case ASGN: c=ASSIGN;break;
case ASSTAR: op=MULT;break;
case ASSLASH: op=DIV;break;
case ASPCT: op=MOD;break;
case ASPLUS: op=ADD;break;
case ASMINUS: op=SUB;break;
case ASAND: op=AND;break;
case ASCIRC: op=XOR;break;
case ASOR: op=OR;break;
case ASLSH: op=LSHIFT;break;
case ASRSH: op=RSHIFT;break;
default:
return left;
}
next_token();
new=new_node();
new->left=left;
new->ntyp=0;
if(c==ASSIGN){
new->right=assignment_expression();
new->flags=ASSIGN;
}else{
/* ASSIGNOP(a,b)->ASSIGN(a,OP(a,b)) */
new->flags=ASSIGNOP; /* nur um zum Merken, dass nur einmal */
/* ausgewertet werden darf */
new->right=new_node();
new->right->left=left;
new->right->right=assignment_expression();
new->right->ntyp=0;
new->right->flags=op;
}
return new;
}
np conditional_expression(void)
/* Erledigt ? : */
{
np left,new;
left=logical_or_expression();
killsp();
if(ctok->type==QUEST){
next_token();killsp();
new=new_node();
new->flags=COND;
new->ntyp=0;
new->left=left;
new->right=new_node();
new->right->flags=COLON;
new->right->ntyp=0;
new->right->left=expression();
killsp();
if(ctok->type==T_COLON){next_token();killsp();} else error(70);
new->right->right=conditional_expression();
left=new;
killsp();
}
return left;
}
np logical_or_expression(void)
/* Erledigt || */
{
np left,right,new;int bra;
if(ctok->type==LPAR) bra=1; else bra=0;
left=logical_and_expression();
killsp();
while(ctok->type==T_LOR){
#ifdef HAVE_MISRA
/* removed */
#endif
next_token();
killsp();
if(ctok->type==LPAR) bra=1; else bra=0;
right=logical_and_expression();
#ifdef HAVE_MISRA
/* removed */
#endif
new=new_node();
new->left=left;
new->right=right;
new->flags=LOR;
new->ntyp=0;
left=new;
killsp();
if(ctok->type==T_LAND) error(222);
}
return left;
}
np logical_and_expression(void)
/* Erledigt && */
{
np left,right,new;int bra;
if(ctok->type==LPAR) bra=1; else bra=0;
left=inclusive_or_expression();
killsp();
while(ctok->type==T_LAND){
#ifdef HAVE_MISRA
/* removed */
#endif
next_token();
killsp();
if(ctok->type==LPAR) bra=1; else bra=0;
right=inclusive_or_expression();
#ifdef HAVE_MISRA
/* removed */
#endif
new=new_node();
new->left=left;
new->right=right;
new->flags=LAND;
new->ntyp=0;
left=new;
killsp();
if(ctok->type==T_LOR) error(222);
}
return left;
}
np inclusive_or_expression(void)
/* Erledigt | */
{
np left,right,new;
left=exclusive_or_expression();
killsp();
while(ctok->type==T_OR){
next_token();
killsp();
right=exclusive_or_expression();
new=new_node();
new->left=left;
new->right=right;
new->flags=OR;
new->ntyp=0;
left=new;
killsp();
}
return left;
}
np exclusive_or_expression(void)
/* Erledigt ^ */
{
np left,right,new;
left=and_expression();
killsp();
while(ctok->type==CIRC){
next_token();
killsp();
right=and_expression();
new=new_node();
new->left=left;
new->right=right;
new->flags=XOR;
new->ntyp=0;
left=new;
killsp();
}
return left;
}
np and_expression(void)
/* Erledigt & */
{
np left,right,new;
left=equality_expression();
killsp();
while(ctok->type==T_AND){
next_token();
killsp();
right=equality_expression();
new=new_node();
new->left=left;
new->right=right;
new->flags=AND;
new->ntyp=0;
left=new;
killsp();
}
return left;
}
np equality_expression(void)
/* Erledigt == und != */
{
np left,right,new;int c;
left=relational_expression();
killsp();
while(ctok->type==SAME||ctok->type==NEQ){
if(ctok->type==NEQ) c=INEQUAL; else c=EQUAL;
next_token();
killsp();
right=relational_expression();
new=new_node();
new->left=left;
new->right=right;
new->flags=c;
new->ntyp=0;
left=new;
killsp();
}
return left;
}
np relational_expression(void)
/* Erledigt <,>,<=,>= */
{
np left,right,new;int c;
left=shift_expression();
killsp();
while(ctok->type==LT||ctok->type==GT||ctok->type==LEQ||ctok->type==GEQ){
if(ctok->type==LT) c=LESS;
else if(ctok->type==GT) c=GREATER;
else if(ctok->type==LEQ) c=LESSEQ;
else c=GREATEREQ;
next_token();
killsp();
right=shift_expression();
new=new_node();
new->left=left;
new->right=right;
new->flags=c;
new->ntyp=0;
left=new;
killsp();
}
return left;
}
np shift_expression(void)
/* Erledigt <<,>> */
{
np left,right,new;int c;
left=additive_expression();
killsp();
while(ctok->type==LSH||ctok->type==RSH){
if(ctok->type==LSH)
c=LSHIFT;
else
c=RSHIFT;
next_token();
killsp();
right=additive_expression();
new=new_node();
new->left=left;
new->right=right;
new->flags=c;
new->ntyp=0;
left=new;
killsp();
}
return left;
}
np additive_expression(void)
/* Erledigt +,- */
{
np left,right,new;int c;
left=multiplicative_expression();
killsp();
while(ctok->type==PLUS||ctok->type==T_MINUS){
if(ctok->type==PLUS) c=ADD; else c=SUB;
next_token();killsp();
right=multiplicative_expression();
new=new_node();
new->left=left;
new->right=right;
new->flags=c;
new->ntyp=0;
left=new;
killsp();
}
return left;
}
np multiplicative_expression(void)
/* Erledigt *,/,% */
{
np left,right,new;int c;
left=cast_expression();
killsp();
while(ctok->type==STAR||ctok->type==SLASH||ctok->type==PCT){
if(ctok->type==STAR) c=MULT;
else if(ctok->type==SLASH) c=DIV;
else c=MOD;
next_token();killsp();
right=cast_expression();
new=new_node();
new->left=left;
new->right=right;
new->flags=c;
new->ntyp=0;
left=new;
killsp();
}
return left;
}
np cast_expression(void)
/* Erledigt (typ) */
{
np new;char *imerk,buff[MAXI];
killsp();
if(ctok->type!=LPAR||!declaration(1)) return unary_expression();
next_token();killsp();
new=new_node();
new->right=0;
buff[0]=0;
imerk=ident;ident=buff;
new->ntyp=declarator(declaration_specifiers());
ident=imerk;
if(buff[0]) error(356);
killsp();
if(ctok->type!=RPAR) error(59); else next_token();
killsp();
if(c99&&ctok->type==LBRA){
/* compund literals */
init_dyn_cnt=0;
new->cl=initialization(new->ntyp,nesting!=0,0,0,0,0);
killsp();
if(new->cl){
if(ISARRAY(new->ntyp->flags)&&zmeqto(new->ntyp->size,l2zm(0L))){
const_list *p=new->cl;
while(p){new->ntyp->size=zmadd(p->idx,l2zm(1L));p=p->next;}
}
}
new->flags=LITERAL;
new->left=0;
new->val.vmax=l2zm((long)init_dyn_cnt);
}else{
new->flags=CAST;
new->left=cast_expression();
}
return new;
}
np unary_expression(void)
/* Erledigt !,~,++,--,+,-,*,&,sizeof,__typeof */
{
np new;char *merk;
killsp();
if(ctok->type!=NAME&&ctok->type!=PLUS&&ctok->type!=PPLUS&&ctok->type!=T_MINUS&&ctok->type!=MMINUS&&ctok->type!=T_AND&&ctok->type!=STAR&&ctok->type!=NOT&&ctok->type!=LNOT)
return postfix_expression();
if(ctok->type==NAME){
enum {SIZEOF,TYPEOF,ALIGNOF,OFFSETOF} op;
if(strcmp("sizeof",ctok->name)&&strcmp("__typeof",ctok->name)&&strcmp("__alignof",ctok->name)&&strcmp("__offsetof",ctok->name)){
return postfix_expression();
}else{
if(*ctok->name=='s')
op=SIZEOF;
else if(ctok->name[2]=='a')
op=ALIGNOF;
else if(ctok->name[2]=='t')
op=TYPEOF;
else
op=OFFSETOF;
next_token();
killsp();
new=new_node();
new->flags=CEXPR;
new->ntyp=new_typ();
if(op==SIZEOF||op==OFFSETOF){
if(HAVE_INT_SIZET)
new->ntyp->flags=(UNSIGNED|INT);
else
new->ntyp->flags=(UNSIGNED|LONG);
}else
new->ntyp->flags=INT;
new->right=0;
new->left=0;
if(ctok->type==LPAR&&declaration(1)){
type *t;
next_token();killsp();
buff[0]=0;
merk=ident;ident=buff;
t=declarator(declaration_specifiers());
if(type_uncomplete(t)) error(176);
ident=merk;
if(buff[0]) error(356);
if(op==OFFSETOF){
if(ctok->type==COMMA)
next_token();
else
error(57);
if(ctok->type!=NAME) error(76);
if(t->flags!=STRUCT){
error(310);
vumax=ul2zum(0UL);
}else
vumax=zm2zum(struct_offset(t->exact,ctok->name));
next_token();
if(HAVE_INT_SIZET)
new->val.vuint=zum2zui(vumax);
else
new->val.vulong=zum2zul(vumax);
}else if(op==SIZEOF){
if(is_vlength(t)){
new->dsize=vlength_szof(t);
new->flags=IDENTIFIER;
new->val.vmax=l2zm(0L);
new->sidefx=0;
new->identifier=empty;
}else{
if(HAVE_INT_SIZET)
new->val.vuint=zum2zui(zm2zum(szof(t)));
else
new->val.vulong=zum2zul(zm2zum(szof(t)));
}
}else if(op==ALIGNOF){
new->val.vint=zm2zi(falign(t));
}else if(op==TYPEOF){
new->val.vint=zm2zi(l2zm(t->flags));
}
freetyp(t);
killsp();
if(ctok->type!=RPAR) error(59); else next_token();
}else{
np tree;
if(op==OFFSETOF) error(0);
killsp();
tree=unary_expression();
if(!tree||!type_expression(tree,0)){
if(op==SIZEOF){
if(HAVE_INT_SIZET)
new->val.vuint=zum2zui(ul2zum(0UL));
else
new->val.vulong=zum2zul(ul2zum(0UL));
error(73);
}else{
new->val.vint=zm2zi(l2zm(-1L));
}
}else{
if(op==SIZEOF){
#ifdef HAVE_MISRA
/* removed */
#endif
if(type_uncomplete(tree->ntyp)) error(176);
if(is_vlength(tree->ntyp)){
new->dsize=vlength_szof(tree->ntyp);
new->flags=IDENTIFIER;
new->val.vmax=l2zm(0L);
new->sidefx=0;
new->identifier=empty;
}else{
if(HAVE_INT_SIZET)
new->val.vuint=zum2zui(zm2zum(szof(tree->ntyp)));
else
new->val.vulong=zum2zul(zm2zum(szof(tree->ntyp)));
}
}else{
if(op==ALIGNOF)
new->val.vint=zm2zi(falign(tree->ntyp));
else
new->val.vint=zm2zi(l2zm(tree->ntyp->flags));
}
}
if(tree) free_expression(tree);killsp();
}
return new;
}
}
new=new_node();
new->right=0;
new->ntyp=0;
if(ctok->type==PLUS){
next_token();
free(new);
return cast_expression();
}else if(ctok->type==T_MINUS){
next_token();
new->left=cast_expression();
new->flags=MINUS;
}else if(ctok->type==PPLUS){
next_token();
new->left=unary_expression();
new->flags=PREINC;
}else if(ctok->type==MMINUS){
next_token();
new->left=unary_expression();
new->flags=PREDEC;
}else if(ctok->type==T_AND){
next_token();
new->left=cast_expression();
new->flags=ADDRESS;
}else if(ctok->type==STAR){
next_token();
new->left=cast_expression();
new->flags=CONTENT;
}else if(ctok->type==NOT){
next_token();
new->left=cast_expression();
new->flags=KOMPLEMENT;
}else if(ctok->type==LNOT){
next_token();
new->left=cast_expression();
new->flags=NEGATION;
}
new->right=0;
new->ntyp=0;
return new;
}
np postfix_expression(void)
/* Erledigt [],(),.,->,++,-- */
{
np new,left;
left=primary_expression();
killsp();
while(ctok->type==LBRK||ctok->type==LPAR||ctok->type==DOT||ctok->type==ARROW||ctok->type==PPLUS||ctok->type==MMINUS){
new=new_node();
new->ntyp=0;
new->right=0;
new->left=left;
if(ctok->type==MMINUS){
next_token();
new->flags=POSTDEC;
}else if(ctok->type==ARROW){
next_token(); killsp();
new->flags=DSTRUCT;
new->right=identifier_expression();
new->right->flags=MEMBER;
new->left=new_node();
new->left->ntyp=0;
new->left->left=left;
new->left->right=0;
new->left->flags=CONTENT;
}else if(ctok->type==LBRK){
next_token(); killsp();
new->flags=CONTENT;
new->left=new_node();
new->left->flags=ADD;
new->left->ntyp=0;
new->left->left=left;
new->left->right=expression();
killsp();
if(ctok->type!=RBRK) error(62); else next_token();
}else if(ctok->type==PPLUS){
next_token();
new->flags=POSTINC;
}else if(ctok->type==DOT){
next_token();killsp();
new->right=identifier_expression();
new->flags=DSTRUCT;
new->right->flags=MEMBER;
}else if(ctok->type==LPAR){
argument_list *al,*first_alist=0,*last_alist=0;np n;
#ifdef HAVE_MISRA
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
#endif
new->left=left;
new->flags=CALL;
new->right=0;
new->alist=argument_list_expression();
}
left=new;
killsp();
}
return left;
}
argument_list *argument_list_expression(void)
/* returns CALL node with alist attached, but without identifier */
{
argument_list *al,*first_alist=0,*last_alist=0;np n;
if(ctok->type!=LPAR)ierror(0);
next_token();killsp();
while(ctok->type!=RPAR){
n=assignment_expression();
al=mymalloc(sizeof(argument_list));
al->arg=n;al->next=0;
if(last_alist){
last_alist->next=al;
last_alist=al;
}else{
last_alist=first_alist=al;
}
killsp();
if(ctok->type==COMMA){
next_token();killsp();
if(ctok->type==RPAR) error(59);
}else if(ctok->type!=RPAR) error(57);
}
if(ctok->type!=RPAR) error(59); else next_token();
return first_alist;
}
np primary_expression(void)
/* primary-expressions (Konstanten,Strings,(expr),Identifier) */
{
np new;token mtok;
if(ctok->type==NUMBER) return constant_expression();
if(ctok->type==T_STRING||ctok->type==T_CHAR) return string_expression();
if(ctok->type==LPAR){
next_token();killsp();
new=expression();
killsp();
if(ctok->type!=RPAR) error(59); else next_token();
return new;
}
return identifier_expression();
}
const_list *cl_from_string(char *start, char *end)
{
const_list *r,*cl,**prev;int i;
prev=&r;
for(i=0;i<end-start+1;i++){
cl=mymalloc(CLS);
cl->next=0;
cl->tree=0;
cl->idx=l2zm((long)i);
cl->val.vmax=l2zm(0L);
cl->other=mymalloc(CLS);
cl->other->next=cl->other->other=0;
cl->other->tree=0;
cl->other->idx=l2zm(0L);
cl->other->val.vchar=zm2zc(l2zm((long)start[i]));
*prev=cl;
prev=&cl->next;
}
return r;
}
np string_expression(void)
/* Gibt Zeiger auf string oder Zeichenkonstante zurueck */
{
np new; char f,*s,*p;int flag,val;
zmax zm;zumax zum;
static char *string;
static size_t slen;
p=string;
while(1){
s=ctok->name;
if(*s=='L') {
#ifdef HAVE_MISRA
/* removed */
#endif
s++;} /* Noch keine erweiterten Zeichen */
if(ctok->type==T_STRING&&*s!='\"') ierror(0);
if(ctok->type==T_CHAR&&*s!='\'') ierror(0);
f=*s++;
while(*s!=f&&*s!=0){
size_t pos=p-string;
if(slen<=pos+1){
slen+=128;
string=myrealloc(string,slen);
p=string+pos;
}
if(*s=='\\'){
s++;
if(*s=='\\'){*p++=CHARCONV('\\');s++;continue;}
if(*s=='n'){*p++=CHARCONV('\n');s++;continue;}
if(*s=='t'){*p++=CHARCONV('\t');s++;continue;}
if(*s=='r'){*p++=CHARCONV('\r');s++;continue;}
if(*s=='v'){*p++=CHARCONV('\v');s++;continue;}
if(*s=='b'){*p++=CHARCONV('\b');s++;continue;}
if(*s=='f'){*p++=CHARCONV('\f');s++;continue;}
if(*s=='a'){*p++=CHARCONV('\a');s++;continue;}
if(*s=='\?'){*p++=CHARCONV('\?');s++;continue;}
if(*s=='\''){*p++=CHARCONV('\'');s++;continue;}
if(*s=='\"'){*p++=CHARCONV('\"');s++;continue;}
flag=val=0;
while(*s>='0'&&*s<='7'&&flag<3){
val=val*8+*s-'0';
s++;flag++;
}
if(flag){*p++=val;continue;}
if(*s=='x'){
int warned=0;
s++;val=0;
while((*s>='0'&&*s<='9')||(*s>='a'&&*s<='f')||(*s>='A'&&*s<='F')){
val=val*16;
if(*s>='0'&&*s<='9') val+=*s-'0';
if(*s>='a'&&*s<='f') val+=*s-'a'+10;
if(*s>='A'&&*s<='F') val+=*s-'A'+10;
if(!warned&&((unsigned long)val)>zum2ul(tu_max[CHAR])){
error(364);
warned=1;
}
s++;
}
*p++=val;continue;
}
error(71);
#ifdef HAVE_MISRA
/* removed */
#endif
}
*p++=CHARCONV(*s);
s++;
}
if(*s!=f) error(74);
next_token();
killsp();
if(f!='\"'||ctok->type!=T_STRING) break;
}
if(!string){
slen+=128;
string=myrealloc(string,slen);
p=string;
}
*p=0;
new=new_node();
new->ntyp=new_typ();
if(f=='\"'){
new->ntyp->flags=ARRAY;
new->ntyp->size=l2zm((long)(p-string)+1);
new->ntyp->next=new_typ();
new->ntyp->next->flags=STRINGCONST|CHAR;
new->ntyp->next->next=0;
new->flags=STRING;
new->cl=cl_from_string(string,p);
/* new->identifier=add_identifier(string,p-string);*/
new->val.vmax=l2zm(0L);
}else{
char *l;
if(ecpp)new->ntyp->flags=CONST|CHAR;
else new->ntyp->flags=CONST|INT;
new->ntyp->next=0;
new->flags=CEXPR;
/* TODO: Hier eventuell was mitspeichern das char */
zm=l2zm(0L);zum=ul2zum(0UL);
p--;
if(p>string){ error(72);
#ifdef HAVE_MISRA
/* removed */
#endif
}
for(BIGENDIAN?(l=string):(l=p);BIGENDIAN?(l<=p):(l>=string);BIGENDIAN?(l++):(l--)){
/* zm=zm<<CHAR_BIT+*p */
if(default_unsigned){
zum=zumlshift(zum,char_bit);
zum=zmadd(zum,ul2zum(*(unsigned char *)l));
new->val.vint=zm2zi(zum2zm(zum));
}else{
zm=zmlshift(zm,char_bit);
zm=zmadd(zm,l2zm((long)*l));
new->val.vint=zm2zi(zm);
}
}
}
new->left=new->right=0;
return new;
}
np constant_expression(void)
/* Gibt Zeiger auf erzeugt Struktur fuer Konstante zurueck */
{
np new; zldouble db;
zumax value,zbase,digit;unsigned long base=10,t;
char *s,*merk;int warned=0,tm=0;
merk=s=ctok->name;
value=ul2zum(0L);
new=new_node();
new->ntyp=new_typ();
new->ntyp->flags=0;
new->flags=CEXPR;
new->left=new->right=0;
new->sidefx=0;
if(*s=='0'){
s++;
if(*s=='x'||*s=='X'){s++;base=16;} else base=8;
}
zbase=ul2zum(base);
if(*s>='0'&&*s<='9') t=*s-'0';
else if(*s>='a'&&*s<='f') t=*s-'a'+10;
else if(*s>='A'&&*s<='F') t=*s-'A'+10;
else t=20;
while(t<base){
digit=ul2zum(t);
if(!warned){
if(!c99&&!zumleq(value,zumdiv(zumsub(t_max(UNSIGNED|LONG),digit),zbase)))
warned=1;
if(c99&&!zumleq(value,zumdiv(zumsub(t_max(UNSIGNED|LLONG),digit),zbase)))
warned=1;
}
value=zumadd(zummult(value,zbase),digit);
s++;
if(*s>='0'&&*s<='9') t=*s-'0';
else if(*s>='a'&&*s<='f') t=*s-'a'+10;
else if(*s>='A'&&*s<='F') t=*s-'A'+10;
else t=20;
}
while((!(tm&UNSIGNED)&&(*s=='u'||*s=='U'))||((tm&NQ)==0&&(*s=='l'||*s=='L'))){
#ifdef HAVE_MISRA
/* removed */
#endif
if(!(tm&UNSIGNED)&&(*s=='u'||*s=='U')){
if((tm&NQ)==LONG){
if(!c99||zumleq(value,t_max(UNSIGNED|LONG)))
new->ntyp->flags=(UNSIGNED|LONG);
else
new->ntyp->flags=(UNSIGNED|LLONG);
}else if((tm&NQ)==LLONG)
new->ntyp->flags=(UNSIGNED|LLONG);
else if(zumleq(value,t_max(UNSIGNED|INT)))
new->ntyp->flags=UNSIGNED|INT;
else if(!c99||zumleq(value,t_max(UNSIGNED|LONG)))
new->ntyp->flags=UNSIGNED|LONG;
else
new->ntyp->flags=UNSIGNED|LLONG;
tm|=UNSIGNED;
}else{
if(c99&&s[1]==s[0]){
s++;
if(tm&UNSIGNED)
new->ntyp->flags=(UNSIGNED|LLONG);
else if(base==10||zumleq(value,t_max(LLONG)))
new->ntyp->flags=LLONG;
else
new->ntyp->flags=UNSIGNED|LLONG;
tm|=LLONG;
}else{
if(tm&UNSIGNED){
if(!c99||zumleq(value,t_max(UNSIGNED|LONG)))
new->ntyp->flags=(UNSIGNED|LONG);
else
new->ntyp->flags=(UNSIGNED|LLONG);
}else{
if(!c99){
if(base==10||zumleq(value,t_max(LONG)))
new->ntyp->flags=LONG;
else
new->ntyp->flags=UNSIGNED|LONG;
}else{
if(zumleq(value,t_max(LONG)))
new->ntyp->flags=LONG;
else if(base!=10&&zumleq(value,t_max(UNSIGNED|LONG)))
new->ntyp->flags=UNSIGNED|LONG;
else if(base==10||zumleq(value,t_max(LLONG)))
new->ntyp->flags=LLONG;
else
new->ntyp->flags=UNSIGNED|LLONG;
}
}
tm|=LONG;
}
}
s++;
}
if(*s=='.'||*s=='e'||*s=='E'){
/* Fliesskommakonstante, ignoriert vorher berechneten Wert, falls er */
/* nicht dezimal und nicht 0 war (da er dann oktal war) */
if(*merk=='0'&&!zumeqto(value,ul2zum(0UL))){
value=ul2zum(0UL);zbase=ul2zum(10UL);
while(*merk>='0'&&*merk<='9'){
digit=ul2zum((unsigned long)(*merk-'0'));
value=zumadd(zummult(value,zbase),digit);
merk++;
}
if(merk!=s) error(75);
}
db=zum2zld(value);
if(*s=='.'){
/* Teil hinter Kommastellen */
zldouble zdiv,zbased,zsum,digit;
int cnt=0;
s++;
zbased=d2zld(10.0);zdiv=d2zld(1.0);zsum=d2zld(0.0);
while(*s>='0'&&*s<='9'){
if (cnt<35){
cnt++;
digit=d2zld((double)(*s-'0'));
zsum=zldadd(zldmult(zsum,zbased),digit);
zdiv=zldmult(zdiv,zbased);
}
s++;
}
db=zldadd(db,zlddiv(zsum,zdiv));
}
if(*s=='e'||*s=='E'){
/* Exponentialdarstellung */
int exp,vorz,i;zldouble zbased;
zbased=d2zld((double)10);
s++;
if(*s=='-'){
s++;vorz=-1;
}else{
vorz=1;if(*s=='+') s++;
}
exp=0;
while(*s>='0'&&*s<='9') exp=exp*10+*s++-'0';
for(i=0;i<exp;i++){
if(vorz>0) db=zldmult(db,zbased);
else db=zlddiv(db,zbased);
}
}
new->ntyp->flags=DOUBLE;
if(*s=='f'||*s=='F'){
new->ntyp->flags=FLOAT;s++;
}else if(*s=='l'||*s=='L'){
new->ntyp->flags=LDOUBLE;s++;
}
}else{
if(warned) error(211);
if(new->ntyp->flags==0){
if(base==10){
if(zumleq(value,t_max(INT)))
new->ntyp->flags=INT;
else if(!c99||zumleq(value,t_max(LONG)))
new->ntyp->flags=LONG;
else
new->ntyp->flags=LLONG;
}else{
#ifdef HAVE_MISRA
/* removed */
#endif
if(zumleq(value,t_max(INT)))
new->ntyp->flags=INT;
else
if(zumleq(value,t_max(UNSIGNED|INT)))
new->ntyp->flags=UNSIGNED|INT;
else if(zumleq(value,t_max(LONG)))
new->ntyp->flags=LONG;
else if(!c99||zumleq(value,t_max(UNSIGNED|LONG))){
new->ntyp->flags=UNSIGNED|LONG;error(212);
}else if(zumleq(value,t_max(LLONG)))
new->ntyp->flags=LLONG;
else
new->ntyp->flags=UNSIGNED|LLONG;
}
}
}
if(*s) error(232);
if(new->ntyp->flags==FLOAT) new->val.vfloat=zld2zf(db);
else if(new->ntyp->flags==DOUBLE) new->val.vdouble=zld2zd(db);
else if(new->ntyp->flags==LDOUBLE) new->val.vldouble=db;
else if(new->ntyp->flags==INT) new->val.vint=zm2zi(zum2zm(value));
else if(new->ntyp->flags==(UNSIGNED|INT)) new->val.vuint=zum2zui(value);
else if(new->ntyp->flags==LONG) new->val.vlong=zm2zl(zum2zm(value));
else if(new->ntyp->flags==(UNSIGNED|LONG)) new->val.vulong=zum2zul(value);
else if(new->ntyp->flags==LLONG) new->val.vllong=zm2zll(zum2zm(value));
else if(new->ntyp->flags==(UNSIGNED|LLONG)) new->val.vullong=zum2zull(value);
else ierror(0);
next_token();
return new;
}
np identifier_expression(void)
/* Erzeugt Identifier mit Knoten */
{
np new;char buff[MAXI];
killsp();
if(ctok->type==NAME){
if(is_keyword(ctok->name)) error(216,ctok->name);
#ifdef HAVE_MISRA
/* removed */
#endif
new=new_node();
new->flags=IDENTIFIER;
new->left=new->right=0;
new->identifier=add_identifier(ctok->name,strlen(ctok->name));
if(!strncmp(ctok->name,"__maskm_",8)){
unsigned long mask;
if(sscanf(ctok->name,"__maskm_%lu_%s",&mask,new->identifier)!=2) ierror(0);
sprintf(new->identifier+strlen(new->identifier),".%lu",mask);
}
new->ntyp=0;
new->sidefx=0;
new->val.vmax=l2zm(0L);
new->o.v=0;
next_token();
}else{
error(76);
new=0;
}
return new;
}
void free_alist(argument_list *p)
/* Gibt argument_list inkl. expressions frei */
{
argument_list *merk;
while(p){
merk=p->next;
if(p->arg) free_expression(p->arg);
free(p);
p=merk;
}
}
void free_expression(np p)
/* Gibt expression mit allen Typen etc. frei */
{
if(!p) return;
if(p->flags==ASSIGNOP){
if(!p->right){ierror(0);return;}
if(p->right->left==p->left) p->left=0;
if(p->right->right==p->left) p->left=0;
}
if(p->flags==CALL&&p->alist) free_alist(p->alist);
if(p->ntyp) freetyp(p->ntyp);
if(p->left) free_expression(p->left);
if(p->right) free_expression(p->right);
free(p);
}