| /* $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); |
| } |
| |