X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2FSDCC.y;h=644ecc5196dce307a181e688905d42c00e4498a2;hb=b6e650674687c1d2b5ab9d6d467cd9252a5d22ae;hp=1d8fb62ed1ecbc74f708b3ef41093266d38b17a5;hpb=c819b1e06a731b497ea9e0bfbb6b3b753306a190;p=fw%2Fsdcc diff --git a/src/SDCC.y b/src/SDCC.y index 1d8fb62e..644ecc51 100644 --- a/src/SDCC.y +++ b/src/SDCC.y @@ -31,6 +31,10 @@ #include "SDCCval.h" #include "SDCCmem.h" #include "SDCCast.h" +#include "port.h" +#include "newalloc.h" +#include "SDCCerr.h" +#include "SDCCutil.h" extern int yyerror (char *); extern FILE *yyin; @@ -55,21 +59,23 @@ STACK_DCL(blockNum,int,MAX_NEST_LEVEL*3) value *cenum = NULL ; /* current enumeration type chain*/ %} +%expect 6 + %union { symbol *sym ; /* symbol table pointer */ structdef *sdef; /* structure definition */ char yychar[SDCC_NAME_MAX+1]; - link *lnk ; /* declarator or specifier */ + sym_link *lnk ; /* declarator or specifier */ int yyint; /* integer value returned */ value *val ; /* for integer constant */ initList *ilist; /* initial list */ - char yyinline[MAX_INLINEASM]; /* inlined assembler code */ + char *yyinline; /* inlined assembler code */ ast *asts; /* expression tree */ } %token IDENTIFIER TYPE_NAME %token CONSTANT STRING_LITERAL -%token SIZEOF +%token SIZEOF TYPEOF %token PTR_OP INC_OP DEC_OP LEFT_OP RIGHT_OP LE_OP GE_OP EQ_OP NE_OP %token AND_OP OR_OP %token MUL_ASSIGN DIV_ASSIGN MOD_ASSIGN ADD_ASSIGN @@ -78,13 +84,14 @@ value *cenum = NULL ; /* current enumeration type chain*/ %token TYPEDEF EXTERN STATIC AUTO REGISTER CODE EEPROM INTERRUPT SFR AT SBIT %token REENTRANT USING XDATA DATA IDATA PDATA VAR_ARGS CRITICAL NONBANKED BANKED %token CHAR SHORT INT LONG SIGNED UNSIGNED FLOAT DOUBLE CONST VOLATILE VOID BIT -%token STRUCT UNION ENUM ELIPSIS RANGE FAR _XDATA _CODE _GENERIC _NEAR _PDATA _IDATA _EEPROM -%token CASE DEFAULT IF ELSE SWITCH WHILE DO FOR GOTO CONTINUE BREAK RETURN +%token STRUCT UNION ENUM ELIPSIS RANGE FAR +%token CASE DEFAULT IF ELSE SWITCH WHILE DO FOR GOTO CONTINUE BREAK RETURN +%token NAKED JAVANATIVE OVERLAY %token INLINEASM %token IFX ADDRESS_OF GET_VALUE_AT_ADDRESS SPIL UNSPIL GETHBIT %token BITWISEAND UNARYMINUS IPUSH IPOP PCALL ENDFUNCTION JUMPTABLE %token RRC RLC -%token CAST CALL PARAM NULLOP BLOCK LABEL RECEIVE SEND +%token CAST CALL PARAM NULLOP BLOCK LABEL RECEIVE SEND ARRAYINIT %type Interrupt_storage %type identifier declarator declarator2 enumerator_list enumerator @@ -92,12 +99,12 @@ value *cenum = NULL ; /* current enumeration type chain*/ %type struct_declarator_list struct_declaration struct_declaration_list %type declaration init_declarator_list init_declarator %type declaration_list identifier_list parameter_identifier_list -%type declarator2_using_reentrant while do for +%type declarator2_function_attributes while do for %type pointer type_specifier_list type_specifier type_name %type storage_class_specifier struct_or_union_specifier %type declaration_specifiers sfr_reg_bit type_specifier2 -%type using_reentrant using_reentrant_interrupt enum_specifier -%type abstract_declarator abstract_declarator2 far_near_pointer far_near +%type function_attribute function_attributes enum_specifier +%type abstract_declarator abstract_declarator2 unqualified_pointer %type parameter_type_list parameter_list parameter_declaration opt_assign_expr %type stag opt_stag %type primary_expr @@ -122,8 +129,27 @@ file ; external_definition - : function_definition { blockNo=0;} + : function_definition { + blockNo=0; + } | declaration { + if ($1 && $1->type + && IS_FUNC($1->type)) + { + /* The only legal storage classes for + * a function prototype (declaration) + * are extern and static. extern is the + * default. Thus, if this function isn't + * explicitly marked static, mark it + * extern. + */ + if ($1->etype + && IS_SPEC($1->etype) + && !SPEC_STAT($1->etype)) + { + SPEC_EXTR($1->etype) = 1; + } + } addSymChain ($1); allocVariables ($1) ; cleanUpLevel (SymbolTab,1); @@ -144,37 +170,40 @@ function_definition } ; -using_reentrant - : using_reentrant_interrupt - | using_reentrant_interrupt using_reentrant { $$ = mergeSpec($1,$2); } +function_attribute + : function_attributes + | function_attributes function_attribute { $$ = mergeSpec($1,$2,"function_attribute"); } ; -using_reentrant_interrupt +function_attributes : USING CONSTANT { - $$ = newLink() ; - $$->class = SPECIFIER ; - SPEC_BNKF($$) = 1; - SPEC_BANK($$) = (int) floatFromVal($2); + $$ = newLink(SPECIFIER) ; + FUNC_REGBANK($$) = (int) floatFromVal($2); + } + | REENTRANT { $$ = newLink (SPECIFIER); + FUNC_ISREENT($$)=1; + } + | CRITICAL { $$ = newLink (SPECIFIER); + FUNC_ISCRITICAL($$) = 1; + } + | NAKED { $$ = newLink (SPECIFIER); + FUNC_ISNAKED($$)=1; } - | REENTRANT { $$ = newLink (); - $$->class = SPECIFIER ; - SPEC_RENT($$) = 1; + | JAVANATIVE { $$ = newLink (SPECIFIER); + FUNC_ISJAVANATIVE($$)=1; } - | CRITICAL { $$ = newLink (); - $$->class = SPECIFIER ; - SPEC_CRTCL($$) = 1; + | OVERLAY { $$ = newLink (SPECIFIER); + FUNC_ISOVERLAY($$)=1; } - | NONBANKED {$$ = newLink (); - $$->class = SPECIFIER ; - SPEC_NONBANKED($$) = 1; - if (SPEC_BANKED($$)) { + | NONBANKED {$$ = newLink (SPECIFIER); + FUNC_NONBANKED($$) = 1; + if (FUNC_BANKED($$)) { werror(W_BANKED_WITH_NONBANKED); } } - | BANKED {$$ = newLink (); - $$->class = SPECIFIER ; - SPEC_BANKED($$) = 1; - if (SPEC_NONBANKED($$)) { + | BANKED {$$ = newLink (SPECIFIER); + FUNC_BANKED($$) = 1; + if (FUNC_NONBANKED($$)) { werror(W_BANKED_WITH_NONBANKED); } if (SPEC_STAT($$)) { @@ -183,10 +212,9 @@ using_reentrant_interrupt } | Interrupt_storage { - $$ = newLink () ; - $$->class = SPECIFIER ; - SPEC_INTN($$) = $1 ; - SPEC_INTRTN($$) = 1; + $$ = newLink (SPECIFIER) ; + FUNC_INTNO($$) = $1 ; + FUNC_ISISR($$) = 1; } ; @@ -200,14 +228,14 @@ function_body ; primary_expr - : identifier { $$ = newAst(EX_VALUE,symbolVal($1)); } - | CONSTANT { $$ = newAst(EX_VALUE,$1); } + : identifier { $$ = newAst_VALUE(symbolVal($1)); } + | CONSTANT { $$ = newAst_VALUE($1); } | string_literal | '(' expr ')' { $$ = $2 ; } ; string_literal - : STRING_LITERAL { $$ = newAst(EX_VALUE,$1); } + : STRING_LITERAL { $$ = newAst_VALUE($1); } ; postfix_expr @@ -223,14 +251,14 @@ postfix_expr { $3 = newSymbol($3->name,NestLevel); $3->implicit = 1; - $$ = newNode(PTR_OP,newNode('&',$1,NULL),newAst(EX_VALUE,symbolVal($3))); + $$ = newNode(PTR_OP,newNode('&',$1,NULL),newAst_VALUE(symbolVal($3))); /* $$ = newNode('.',$1,newAst(EX_VALUE,symbolVal($3))) ; */ } | postfix_expr PTR_OP identifier { $3 = newSymbol($3->name,NestLevel); $3->implicit = 1; - $$ = newNode(PTR_OP,$1,newAst(EX_VALUE,symbolVal($3))); + $$ = newNode(PTR_OP,$1,newAst_VALUE(symbolVal($3))); } | postfix_expr INC_OP { $$ = newNode(INC_OP,$1,NULL);} @@ -249,7 +277,8 @@ unary_expr | DEC_OP unary_expr { $$ = newNode(DEC_OP,NULL,$2); } | unary_operator cast_expr { $$ = newNode($1,$2,NULL) ; } | SIZEOF unary_expr { $$ = newNode(SIZEOF,NULL,$2); } - | SIZEOF '(' type_name ')' { $$ = newAst(EX_VALUE,sizeofOp($3)); } + | SIZEOF '(' type_name ')' { $$ = newAst_VALUE(sizeofOp($3)); } + | TYPEOF unary_expr { $$ = newNode(TYPEOF,NULL,$2); } ; unary_operator @@ -263,7 +292,7 @@ unary_operator cast_expr : unary_expr - | '(' type_name ')' cast_expr { $$ = newNode(CAST,newAst(EX_LINK,$2),$4); } + | '(' type_name ')' cast_expr { $$ = newNode(CAST,newAst_LINK($2),$4); } ; multiplicative_expr @@ -287,41 +316,40 @@ shift_expr relational_expr : shift_expr - | relational_expr '<' shift_expr { $$ = newNode('<',$1,$3); } - | relational_expr '>' shift_expr { $$ = newNode('>',$1,$3); } + | relational_expr '<' shift_expr { + $$ = (port->lt_nge ? + newNode('!',newNode(GE_OP,$1,$3),NULL) : + newNode('<', $1,$3)); + } + | relational_expr '>' shift_expr { + $$ = (port->gt_nle ? + newNode('!',newNode(LE_OP,$1,$3),NULL) : + newNode('>',$1,$3)); + } | relational_expr LE_OP shift_expr { - /* $$ = newNode(LE_OP,$1,$3); */ - /* getting 8051 specific here : will change - LE_OP operation to "not greater than" i.e. - ( a <= b ) === ( ! ( a > b )) */ - $$ = newNode('!', - newNode('>', $1 , $3 ), - NULL); + $$ = (port->le_ngt ? + newNode('!', newNode('>', $1 , $3 ), NULL) : + newNode(LE_OP,$1,$3)); } | relational_expr GE_OP shift_expr { - /* $$ = newNode(GE_OP,$1,$3) ; */ - /* getting 8051 specific here : will change - GE_OP operation to "not less than" i.e. - ( a >= b ) === ( ! ( a < b )) */ - $$ = newNode('!', - newNode('<', $1 , $3 ), - NULL); + $$ = (port->ge_nlt ? + newNode('!', newNode('<', $1 , $3 ), NULL) : + newNode(GE_OP,$1,$3)); } ; equality_expr : relational_expr - | equality_expr EQ_OP relational_expr { $$ = newNode(EQ_OP,$1,$3);} - | equality_expr NE_OP relational_expr - { - /* $$ = newNode(NE_OP,$1,$3); */ - /* NE_OP changed : - expr1 != expr2 is equivalent to - (! expr1 == expr2) */ - $$ = newNode('!', - newNode(EQ_OP,$1,$3), - NULL); - } + | equality_expr EQ_OP relational_expr { + $$ = (port->eq_nne ? + newNode('!',newNode(NE_OP,$1,$3),NULL) : + newNode(EQ_OP,$1,$3)); + } + | equality_expr NE_OP relational_expr { + $$ = (port->ne_neq ? + newNode('!', newNode(EQ_OP,$1,$3), NULL) : + newNode(NE_OP,$1,$3)); + } ; and_expr @@ -370,34 +398,34 @@ assignment_expr $$ = newNode($2,$1,$3); break; case MUL_ASSIGN: - $$ = newNode('=',$1,newNode('*',copyAst($1),$3)); + $$ = newNode('=',$1,newNode('*',removeIncDecOps(copyAst($1)),$3)); break; case DIV_ASSIGN: - $$ = newNode('=',$1,newNode('/',copyAst($1),$3)); + $$ = newNode('=',$1,newNode('/',removeIncDecOps(copyAst($1)),$3)); break; case MOD_ASSIGN: - $$ = newNode('=',$1,newNode('%',copyAst($1),$3)); + $$ = newNode('=',$1,newNode('%',removeIncDecOps(copyAst($1)),$3)); break; case ADD_ASSIGN: - $$ = newNode('=',$1,newNode('+',copyAst($1),$3)); + $$ = newNode('=',$1,newNode('+',removeIncDecOps(copyAst($1)),$3)); break; case SUB_ASSIGN: - $$ = newNode('=',$1,newNode('-',copyAst($1),$3)); + $$ = newNode('=',$1,newNode('-',removeIncDecOps(copyAst($1)),$3)); break; case LEFT_ASSIGN: - $$ = newNode('=',$1,newNode(LEFT_OP,copyAst($1),$3)); + $$ = newNode('=',$1,newNode(LEFT_OP,removeIncDecOps(copyAst($1)),$3)); break; case RIGHT_ASSIGN: - $$ = newNode('=',$1,newNode(RIGHT_OP,copyAst($1),$3)); + $$ = newNode('=',$1,newNode(RIGHT_OP,removeIncDecOps(copyAst($1)),$3)); break; case AND_ASSIGN: - $$ = newNode('=',$1,newNode('&',copyAst($1),$3)); + $$ = newNode('=',$1,newNode('&',removeIncDecOps(copyAst($1)),$3)); break; case XOR_ASSIGN: - $$ = newNode('=',$1,newNode('^',copyAst($1),$3)); + $$ = newNode('=',$1,newNode('^',removeIncDecOps(copyAst($1)),$3)); break; case OR_ASSIGN: - $$ = newNode('=',$1,newNode('|',copyAst($1),$3)); + $$ = newNode('=',$1,newNode('|',removeIncDecOps(copyAst($1)),$3)); break; default : $$ = NULL; @@ -437,7 +465,7 @@ declaration symbol *sym , *sym1; for (sym1 = sym = reverseSyms($2);sym != NULL;sym = sym->next) { - link *lnk = copyLinkChain($1); + sym_link *lnk = copyLinkChain($1); /* do the pointer stuff */ pointerTypes(sym->type,lnk); addDecl (sym,0,lnk) ; @@ -453,28 +481,28 @@ declaration_specifiers /* if the decl $2 is not a specifier */ /* find the spec and replace it */ if ( !IS_SPEC($2)) { - link *lnk = $2 ; + sym_link *lnk = $2 ; while (lnk && !IS_SPEC(lnk->next)) lnk = lnk->next; - lnk->next = mergeSpec($1,lnk->next); + lnk->next = mergeSpec($1,lnk->next, "storage_class_specifier declaration_specifiers - skipped"); $$ = $2 ; } else - $$ = mergeSpec($1,$2); + $$ = mergeSpec($1,$2, "storage_class_specifier declaration_specifiers"); } | type_specifier { $$ = $1; } | type_specifier declaration_specifiers { /* if the decl $2 is not a specifier */ /* find the spec and replace it */ if ( !IS_SPEC($2)) { - link *lnk = $2 ; + sym_link *lnk = $2 ; while (lnk && !IS_SPEC(lnk->next)) lnk = lnk->next; - lnk->next = mergeSpec($1,lnk->next); + lnk->next = mergeSpec($1,lnk->next, "type_specifier declaration_specifiers - skipped"); $$ = $2 ; } else - $$ = mergeSpec($1,$2); + $$ = mergeSpec($1,$2, "type_specifier declaration_specifiers"); } ; @@ -491,28 +519,23 @@ init_declarator storage_class_specifier : TYPEDEF { - $$ = newLink () ; - $$->class = SPECIFIER ; + $$ = newLink (SPECIFIER) ; SPEC_TYPEDEF($$) = 1 ; } | EXTERN { - $$ = newLink(); - $$->class = SPECIFIER ; + $$ = newLink(SPECIFIER); SPEC_EXTR($$) = 1 ; } | STATIC { - $$ = newLink (); - $$->class = SPECIFIER ; + $$ = newLink (SPECIFIER); SPEC_STAT($$) = 1 ; } | AUTO { - $$ = newLink () ; - $$->class = SPECIFIER ; + $$ = newLink (SPECIFIER) ; SPEC_SCLS($$) = S_AUTO ; } | REGISTER { - $$ = newLink (); - $$->class = SPECIFIER ; + $$ = newLink (SPECIFIER); SPEC_SCLS($$) = S_REGISTER ; } ; @@ -523,102 +546,82 @@ Interrupt_storage type_specifier : type_specifier2 - | type_specifier2 AT CONSTANT + | type_specifier2 AT constant_expr { /* add this to the storage class specifier */ SPEC_ABSA($1) = 1; /* set the absolute addr flag */ /* now get the abs addr from value */ - SPEC_ADDR($1) = (int) floatFromVal ($3) ; + SPEC_ADDR($1) = (int) floatFromVal(constExprValue($3,TRUE)) ; } ; type_specifier2 : CHAR { - $$=newLink(); - $$->class = SPECIFIER ; + $$=newLink(SPECIFIER); SPEC_NOUN($$) = V_CHAR ; } | SHORT { - $$=newLink(); - $$->class = SPECIFIER ; - SPEC_LONG($$) = 0 ; - SPEC_SHORT($$) = 1 ; + $$=newLink(SPECIFIER); + $$->select.s._short = 1 ; } | INT { - $$=newLink(); - $$->class = SPECIFIER ; + $$=newLink(SPECIFIER); SPEC_NOUN($$) = V_INT ; } | LONG { - $$=newLink(); - $$->class = SPECIFIER ; - SPEC_LONG($$) = 1 ; - SPEC_SHORT($$) = 0; + $$=newLink(SPECIFIER); + SPEC_LONG($$) = 1 ; } | SIGNED { - $$=newLink(); - $$->class = SPECIFIER ; - SPEC_USIGN($$) = 0 ; + $$=newLink(SPECIFIER); + $$->select.s._signed = 1; } | UNSIGNED { - $$=newLink(); - $$->class = SPECIFIER ; - SPEC_USIGN($$) = 1 ; + $$=newLink(SPECIFIER); + SPEC_USIGN($$) = 1 ; } | VOID { - $$=newLink(); - $$->class = SPECIFIER ; + $$=newLink(SPECIFIER); SPEC_NOUN($$) = V_VOID ; } | CONST { - $$=newLink(); - $$->class = SPECIFIER ; - SPEC_SCLS($$) = S_CONSTANT ; + $$=newLink(SPECIFIER); SPEC_CONST($$) = 1; } | VOLATILE { - $$=newLink(); - $$->class = SPECIFIER ; + $$=newLink(SPECIFIER); SPEC_VOLATILE($$) = 1 ; } | FLOAT { - $$=newLink(); + $$=newLink(SPECIFIER); SPEC_NOUN($$) = V_FLOAT; - $$->class = SPECIFIER ; } | XDATA { - $$ = newLink (); - $$->class = SPECIFIER ; + $$ = newLink (SPECIFIER); SPEC_SCLS($$) = S_XDATA ; } | CODE { - $$ = newLink () ; - $$->class = SPECIFIER ; + $$ = newLink (SPECIFIER) ; SPEC_SCLS($$) = S_CODE ; } | EEPROM { - $$ = newLink () ; - $$->class = SPECIFIER ; + $$ = newLink (SPECIFIER) ; SPEC_SCLS($$) = S_EEPROM ; } | DATA { - $$ = newLink (); - $$->class = SPECIFIER ; + $$ = newLink (SPECIFIER); SPEC_SCLS($$) = S_DATA ; } | IDATA { - $$ = newLink (); - $$->class = SPECIFIER ; + $$ = newLink (SPECIFIER); SPEC_SCLS($$) = S_IDATA ; } | PDATA { - $$ = newLink (); - $$->class = SPECIFIER ; + $$ = newLink (SPECIFIER); SPEC_SCLS($$) = S_PDATA ; } | BIT { - $$=newLink(); - $$->class = SPECIFIER ; + $$=newLink(SPECIFIER); SPEC_NOUN($$) = V_BIT ; SPEC_SCLS($$) = S_BIT ; SPEC_BLEN($$) = 1; @@ -633,8 +636,7 @@ type_specifier2 | TYPE_NAME { symbol *sym; - link *p ; - + sym_link *p ; sym = findSym(TypedefTab,NULL,$1) ; $$ = p = copyLinkChain(sym->type); SPEC_TYPEDEF(getSpec(p)) = 0; @@ -644,14 +646,12 @@ type_specifier2 sfr_reg_bit : SBIT { - $$ = newLink() ; - $$->class = SPECIFIER ; + $$ = newLink(SPECIFIER) ; SPEC_NOUN($$) = V_SBIT; SPEC_SCLS($$) = S_SBIT; } | SFR { - $$ = newLink() ; - $$->class = SPECIFIER ; + $$ = newLink(SPECIFIER) ; SPEC_NOUN($$) = V_CHAR; SPEC_SCLS($$) = S_SFR ; SPEC_USIGN($$) = 1 ; @@ -662,22 +662,31 @@ struct_or_union_specifier : struct_or_union opt_stag '{' struct_declaration_list '}' { structdef *sdef ; + symbol *sym, *dsym; + + // check for duplicate structure members + for (sym=$4; sym; sym=sym->next) { + for (dsym=sym->next; dsym; dsym=dsym->next) { + if (strcmp(sym->name, dsym->name)==0) { + werror(E_DUPLICATE_MEMBER, + $1==STRUCT ? "struct" : "union", sym->name); + } + } + } - /* Create a structdef */ + /* Create a structdef */ sdef = $2 ; sdef->fields = reverseSyms($4) ; /* link the fields */ sdef->size = compStructSize($1,sdef); /* update size of */ /* Create the specifier */ - $$ = newLink () ; - $$->class = SPECIFIER ; + $$ = newLink (SPECIFIER) ; SPEC_NOUN($$) = V_STRUCT; SPEC_STRUCT($$)= sdef ; } | struct_or_union stag { - $$ = newLink() ; - $$->class = SPECIFIER ; + $$ = newLink(SPECIFIER) ; SPEC_NOUN($$) = V_STRUCT; SPEC_STRUCT($$) = $2 ; } @@ -689,34 +698,34 @@ struct_or_union ; opt_stag - : stag - | { /* synthesize a name add to structtable */ - $$ = newStruct(genSymName(NestLevel)) ; - $$->level = NestLevel ; - addSym (StructTab, $$, $$->tag,$$->level,currBlockno) ; - } - ; +: stag +| { /* synthesize a name add to structtable */ + $$ = newStruct(genSymName(NestLevel)) ; + $$->level = NestLevel ; + addSym (StructTab, $$, $$->tag,$$->level,currBlockno, 0); +}; stag - : identifier { /* add name to structure table */ - $$ = findSymWithBlock (StructTab,$1,currBlockno); - if (! $$ ) { - $$ = newStruct($1->name) ; - $$->level = NestLevel ; - addSym (StructTab, $$, $$->tag,$$->level,currBlockno) ; - } - } - ; +: identifier { /* add name to structure table */ + $$ = findSymWithBlock (StructTab,$1,currBlockno); + if (! $$ ) { + $$ = newStruct($1->name) ; + $$->level = NestLevel ; + addSym (StructTab, $$, $$->tag,$$->level,currBlockno,0); + } +}; + struct_declaration_list : struct_declaration | struct_declaration_list struct_declaration { - symbol *sym = $2; - /* go to the end of the chain */ - while (sym->next) sym = sym->next; + symbol *sym=$2; + /* go to the end of the chain */ + while (sym->next) sym=sym->next; sym->next = $1 ; + $$ = $2; } ; @@ -728,14 +737,18 @@ struct_declaration symbol *sym ; for ( sym = $2 ; sym != NULL ; sym = sym->next ) { + /* make the symbol one level up */ + sym->level-- ; + pointerTypes(sym->type,copyLinkChain($1)); if (!sym->type) { sym->type = copyLinkChain($1); sym->etype = getSpec(sym->type); } else - addDecl (sym,0,cloneSpec($1)); - + addDecl (sym,0,copyLinkChain($1)); + /* make sure the type is complete and sane */ + checkTypeSanity(sym->etype, sym->name); } $$ = $2; } @@ -751,7 +764,7 @@ struct_declarator_list ; struct_declarator - : declarator + : declarator | ':' constant_expr { $$ = newSymbol (genSymName(NestLevel),NestLevel) ; $$->bitVar = (int) floatFromVal(constExprValue($2,TRUE)); @@ -764,44 +777,61 @@ struct_declarator enum_specifier : ENUM '{' enumerator_list '}' { - addSymChain ($3); - allocVariables(reverseSyms($3)) ; - $$ = copyLinkChain(cenum->type); - } + symbol *sym, *dsym; + char _error=0; + + // check for duplicate enums + for (sym=$3; sym; sym=sym->next) { + for (dsym=sym->next; dsym; dsym=dsym->next) { + if (strcmp(sym->name, dsym->name)==0) { + werror(E_DUPLICATE_MEMBER, "enum", sym->name); + _error++; + } + } + } + if (_error==0) { + $$ = copyLinkChain(cenum->type); + } else { + $$ = newIntLink(); + SPEC_NOUN($$)=0; + } + } + | ENUM identifier '{' enumerator_list '}' { - symbol *csym ; - - $2->type = copyLinkChain(cenum->type); - $2->etype = getSpec($2->type); - /* add this to the enumerator table */ - if (!(csym=findSym(enumTab,$2,$2->name)) && - (csym && csym->level == $2->level)) - werror(E_DUPLICATE_TYPEDEF,csym->name); - - addSym ( enumTab,$2,$2->name,$2->level,$2->block); - addSymChain ($4); - allocVariables (reverseSyms($4)); - $$ = copyLinkChain(cenum->type); - SPEC_SCLS(getSpec($$)) = 0 ; - } + symbol *csym ; + + $2->type = copyLinkChain(cenum->type); + $2->etype = getSpec($2->type); + /* add this to the enumerator table */ + if (!(csym=findSym(enumTab,$2,$2->name)) && + (csym && csym->level == $2->level)) + werror(E_DUPLICATE_TYPEDEF,csym->name); + + addSym ( enumTab,$2,$2->name,$2->level,$2->block, 0); + //addSymChain ($4); + //allocVariables (reverseSyms($4)); + $$ = copyLinkChain(cenum->type); + SPEC_SCLS(getSpec($$)) = 0 ; + } | ENUM identifier { - symbol *csym ; - - /* check the enumerator table */ - if ((csym = findSym(enumTab,$2,$2->name))) - $$ = copyLinkChain(csym->type); - else { - $$ = newLink() ; - $$->class = SPECIFIER ; - SPEC_NOUN($$) = V_INT ; - } - - SPEC_SCLS(getSpec($$)) = 0 ; - } + symbol *csym ; + + /* check the enumerator table */ + if ((csym = findSym(enumTab,$2,$2->name))) + $$ = copyLinkChain(csym->type); + else { + $$ = newLink(SPECIFIER) ; + SPEC_NOUN($$) = V_INT ; + } + + SPEC_SCLS(getSpec($$)) = 0 ; + } ; enumerator_list : enumerator + | enumerator_list ',' { + } | enumerator_list ',' enumerator { $3->next = $1 ; $$ = $3 ; @@ -809,15 +839,17 @@ enumerator_list ; enumerator - : identifier opt_assign_expr { - /* make the symbol one level up */ - $1->level-- ; - $1->type = copyLinkChain($2->type); - $1->etype= getSpec($1->type); - SPEC_ENUM($1->etype) = 1; - $$ = $1 ; - - } + : identifier opt_assign_expr + { + /* make the symbol one level up */ + $1->level-- ; + $1->type = copyLinkChain($2->type); + $1->etype= getSpec($1->type); + SPEC_ENUM($1->etype) = 1; + $$ = $1 ; + // do this now, so we can use it for the next enums in the list + addSymChain($1); + } ; opt_assign_expr @@ -829,28 +861,47 @@ opt_assign_expr } | { if (cenum) { - sprintf(lbuff,"%d",(int) floatFromVal(cenum)+1); + SNPRINTF(lbuff, sizeof(lbuff), + "%d",(int) floatFromVal(cenum)+1); $$ = cenum = constVal(lbuff); } else { - sprintf(lbuff,"%d",0); + SNPRINTF(lbuff, sizeof(lbuff), + "%d",0); $$ = cenum = constVal(lbuff); } } ; declarator - : declarator2_using_reentrant { $$ = $1; } - | pointer declarator2_using_reentrant + : declarator2_function_attributes { $$ = $1; } + | pointer declarator2_function_attributes { addDecl ($2,0,reverseLink($1)); $$ = $2 ; } ; -declarator2_using_reentrant +declarator2_function_attributes : declarator2 { $$ = $1 ; } - | declarator2 using_reentrant { addDecl ($1,0,$2); } + | declarator2 function_attribute { + // copy the functionAttributes (not the args and hasVargs !!) + sym_link *funcType=$1->etype; + struct value *args=FUNC_ARGS(funcType); + unsigned hasVargs=FUNC_HASVARARGS(funcType); + + memcpy (&funcType->funcAttrs, &$2->funcAttrs, + sizeof($2->funcAttrs)); + + FUNC_ARGS(funcType)=args; + FUNC_HASVARARGS(funcType)=hasVargs; + + // just to be sure + memset (&$2->funcAttrs, 0, + sizeof($2->funcAttrs)); + + addDecl ($1,0,$2); + } ; declarator2 @@ -858,16 +909,16 @@ declarator2 | '(' declarator ')' { $$ = $2; } | declarator2 '[' ']' { - link *p; + sym_link *p; - p = newLink (); + p = newLink (DECLARATOR); DCL_TYPE(p) = ARRAY ; DCL_ELEM(p) = 0 ; addDecl($1,0,p); } | declarator2 '[' constant_expr ']' { - link *p ; + sym_link *p ; value *tval; p = (tval = constExprValue($3,TRUE))->etype; @@ -875,7 +926,7 @@ declarator2 if ( SPEC_SCLS(p) != S_LITERAL) werror(E_CONST_EXPECTED) ; else { - p = newLink (); + p = newLink (DECLARATOR); DCL_TYPE(p) = ARRAY ; DCL_ELEM(p) = (int) floatFromVal(tval) ; addDecl($1,0,p); @@ -887,37 +938,50 @@ declarator2 addDecl ($1,FUNCTION,NULL) ; - $1->hasVargs = IS_VARG($4); - $1->args = reverseVal($4) ; + FUNC_HASVARARGS($1->type) = IS_VARG($4); + FUNC_ARGS($1->type) = reverseVal($4); /* nest level was incremented to take care of the parms */ NestLevel-- ; currBlockno--; + + // if this was a pointer (to a function) + if (IS_PTR($1->type)) { + // move the args and hasVargs to the function + FUNC_ARGS($1->etype)=FUNC_ARGS($1->type); + FUNC_HASVARARGS($1->etype)=FUNC_HASVARARGS($1->type); + memset (&$1->type->funcAttrs, 0, + sizeof($1->type->funcAttrs)); + // remove the symbol args (if any) + cleanUpLevel(SymbolTab,NestLevel+1); + } + $$ = $1; } | declarator2 '(' parameter_identifier_list ')' { werror(E_OLD_STYLE,$1->name) ; - /* assume it returns an it */ + /* assume it returns an int */ $1->type = $1->etype = newIntLink(); $$ = $1 ; } ; pointer - : far_near_pointer { $$ = $1 ;} - | far_near_pointer type_specifier_list + : unqualified_pointer { $$ = $1 ;} + | unqualified_pointer type_specifier_list { $$ = $1 ; DCL_TSPEC($1) = $2; } - | far_near_pointer pointer + | unqualified_pointer pointer { $$ = $1 ; $$->next = $2 ; + DCL_TYPE($2)=port->unqualified_pointer; } - | far_near_pointer type_specifier_list pointer + | unqualified_pointer type_specifier_list pointer { $$ = $1 ; if (IS_SPEC($2) && DCL_TYPE($3) == UPOINTER) { @@ -939,11 +1003,14 @@ pointer case S_CODE: DCL_PTR_CONST($3) = 1; DCL_TYPE($3) = CPOINTER ; + break; case S_EEPROM: DCL_TYPE($3) = EEPPOINTER; break; default: - werror(W_PTR_TYPE_INVALID); + // this could be just "constant" + // werror(W_PTR_TYPE_INVALID); + ; } } else @@ -952,31 +1019,30 @@ pointer } ; -far_near_pointer - : far_near '*' { - if ($1 == NULL) { - $$ = newLink(); - DCL_TYPE($$) = POINTER ; - } - else - $$ = $1 ; +unqualified_pointer + : '*' + { + $$ = newLink(DECLARATOR); + DCL_TYPE($$)=UPOINTER; } ; -far_near - : _XDATA { $$ = newLink() ; DCL_TYPE($$) = FPOINTER ; } - | _CODE { $$ = newLink() ; DCL_TYPE($$) = CPOINTER ; DCL_PTR_CONST($$) = 1;} - | _PDATA { $$ = newLink() ; DCL_TYPE($$) = PPOINTER ; } - | _IDATA { $$ = newLink() ; DCL_TYPE($$) = IPOINTER ; } - | _NEAR { $$ = NULL ; } - | _GENERIC { $$ = newLink() ; DCL_TYPE($$) = GPOINTER ; } - | _EEPROM { $$ = newLink() ; DCL_TYPE($$) = EEPPOINTER ;} - | { $$ = newLink() ; DCL_TYPE($$) = UPOINTER ; } - ; - type_specifier_list : type_specifier - | type_specifier_list type_specifier { $$ = mergeSpec ($1,$2); } + //| type_specifier_list type_specifier { $$ = mergeSpec ($1,$2, "type_specifier_list"); } + | type_specifier_list type_specifier { + /* if the decl $2 is not a specifier */ + /* find the spec and replace it */ + if ( !IS_SPEC($2)) { + sym_link *lnk = $2 ; + while (lnk && !IS_SPEC(lnk->next)) + lnk = lnk->next; + lnk->next = mergeSpec($1,lnk->next, "type_specifier_list type_specifier skipped"); + $$ = $2 ; + } + else + $$ = mergeSpec($1,$2, "type_specifier_list type_specifier"); + } ; parameter_identifier_list @@ -1029,11 +1095,15 @@ type_name | type_specifier_list abstract_declarator { /* go to the end of the list */ - link *p; + sym_link *p; pointerTypes($2,$1); - for ( p = $2 ; p->next ; p=p->next); - p->next = $1 ; - $$ = $2 ; + for ( p = $2 ; p && p->next ; p=p->next); + if (!p) { + werror(E_SYNTAX_ERROR, yytext); + } else { + p->next = $1 ; + } + $$ = $2 ; } ; @@ -1046,18 +1116,18 @@ abstract_declarator abstract_declarator2 : '(' abstract_declarator ')' { $$ = $2 ; } | '[' ']' { - $$ = newLink (); + $$ = newLink (DECLARATOR); DCL_TYPE($$) = ARRAY ; DCL_ELEM($$) = 0 ; } | '[' constant_expr ']' { value *val ; - $$ = newLink (); + $$ = newLink (DECLARATOR); DCL_TYPE($$) = ARRAY ; DCL_ELEM($$) = (int) floatFromVal(val = constExprValue($2,TRUE)); } | abstract_declarator2 '[' ']' { - $$ = newLink (); + $$ = newLink (DECLARATOR); DCL_TYPE($$) = ARRAY ; DCL_ELEM($$) = 0 ; $$->next = $1 ; @@ -1065,15 +1135,42 @@ abstract_declarator2 | abstract_declarator2 '[' constant_expr ']' { value *val ; - $$ = newLink (); + $$ = newLink (DECLARATOR); DCL_TYPE($$) = ARRAY ; DCL_ELEM($$) = (int) floatFromVal(val = constExprValue($3,TRUE)); $$->next = $1 ; } | '(' ')' { $$ = NULL;} | '(' parameter_type_list ')' { $$ = NULL;} - | abstract_declarator2 '(' ')' - | abstract_declarator2 '(' parameter_type_list ')' + | abstract_declarator2 '(' ')' { + // $1 must be a pointer to a function + sym_link *p=newLink(DECLARATOR); + DCL_TYPE(p) = FUNCTION; + if (!$1) { + // ((void (code *) ()) 0) () + $1=newLink(DECLARATOR); + DCL_TYPE($1)=CPOINTER; + $$ = $1; + } + $1->next=p; + } + | abstract_declarator2 '(' parameter_type_list ')' { + if (!IS_VOID($3->etype)) { + // this is nonsense, so let's just burp something + werror(E_TOO_FEW_PARMS); + } else { + // $1 must be a pointer to a function + sym_link *p=newLink(DECLARATOR); + DCL_TYPE(p) = FUNCTION; + if (!$1) { + // ((void (code *) (void)) 0) () + $1=newLink(DECLARATOR); + DCL_TYPE($1)=CPOINTER; + $$ = $1; + } + $1->next=p; + } + } ; initializer @@ -1096,14 +1193,14 @@ statement | jump_statement | INLINEASM ';' { ast *ex = newNode(INLINEASM,NULL,NULL); - ALLOC_ATOMIC(ex->values.inlineasm,strlen($1)); - strcpy(ex->values.inlineasm,$1); + ex->values.inlineasm = strdup($1); $$ = ex; - } + } ; labeled_statement - : identifier ':' statement { $$ = createLabel($1,$3); } +// : identifier ':' statement { $$ = createLabel($1,$3); } + : identifier ':' { $$ = createLabel($1,NULL); } | CASE constant_expr ':' statement { $$ = createCase(STACK_PEEK(swStk),$2,$4); } | DEFAULT ':' statement { $$ = createDefault(STACK_PEEK(swStk),$3); } ; @@ -1190,7 +1287,8 @@ selection_statement ex->values.switchVals.swNum = swLabel ; /* now create the label */ - sprintf(lbuff,"_swBrk_%d",swLabel++); + SNPRINTF(lbuff, sizeof(lbuff), + "_swBrk_%d",swLabel++); $$ = newSymbol(lbuff,NestLevel); /* put label in the break stack */ STACK_PUSH(breakStack,$$); @@ -1206,45 +1304,49 @@ selection_statement while : WHILE { /* create and push the continue , break & body labels */ static int Lblnum = 0 ; /* continue */ - sprintf (lbuff,"_whilecontinue_%d",Lblnum); + SNPRINTF (lbuff, sizeof(lbuff), "_whilecontinue_%d",Lblnum); STACK_PUSH(continueStack,newSymbol(lbuff,NestLevel)); /* break */ - sprintf (lbuff,"_whilebreak_%d",Lblnum); + SNPRINTF (lbuff, sizeof(lbuff), "_whilebreak_%d",Lblnum); STACK_PUSH(breakStack,newSymbol(lbuff,NestLevel)); /* body */ - sprintf (lbuff,"_whilebody_%d",Lblnum++); + SNPRINTF (lbuff, sizeof(lbuff), "_whilebody_%d",Lblnum++); $$ = newSymbol(lbuff,NestLevel); } + ; do : DO { /* create and push the continue , break & body Labels */ static int Lblnum = 0 ; /* continue */ - sprintf(lbuff,"_docontinue_%d",Lblnum); + SNPRINTF(lbuff, sizeof(lbuff), "_docontinue_%d",Lblnum); STACK_PUSH(continueStack,newSymbol(lbuff,NestLevel)); /* break */ - sprintf (lbuff,"_dobreak_%d",Lblnum); + SNPRINTF(lbuff, sizeof(lbuff), "_dobreak_%d",Lblnum); STACK_PUSH(breakStack,newSymbol(lbuff,NestLevel)); /* do body */ - sprintf (lbuff,"_dobody_%d",Lblnum++); + SNPRINTF(lbuff, sizeof(lbuff), "_dobody_%d",Lblnum++); $$ = newSymbol (lbuff,NestLevel); } + ; + for : FOR { /* create & push continue, break & body labels */ static int Lblnum = 0 ; /* continue */ - sprintf (lbuff,"_forcontinue_%d",Lblnum); + SNPRINTF(lbuff, sizeof(lbuff), "_forcontinue_%d",Lblnum); STACK_PUSH(continueStack,newSymbol(lbuff,NestLevel)); /* break */ - sprintf (lbuff,"_forbreak_%d",Lblnum); + SNPRINTF(lbuff, sizeof(lbuff), "_forbreak_%d",Lblnum); STACK_PUSH(breakStack,newSymbol(lbuff,NestLevel)); /* body */ - sprintf (lbuff,"_forbody_%d",Lblnum); + SNPRINTF(lbuff, sizeof(lbuff), "_forbody_%d",Lblnum); $$ = newSymbol(lbuff,NestLevel); /* condition */ - sprintf (lbuff,"_forcond_%d",Lblnum++); + SNPRINTF(lbuff, sizeof(lbuff), "_forcond_%d",Lblnum++); STACK_PUSH(forStack,newSymbol(lbuff,NestLevel)); } + ; iteration_statement : while '(' expr ')' statement @@ -1298,7 +1400,7 @@ expr_opt jump_statement : GOTO identifier ';' { $2->islbl = 1; - $$ = newAst(EX_VALUE,symbolVal($2)); + $$ = newAst_VALUE(symbolVal($2)); $$ = newNode(GOTO,$$,NULL); } | CONTINUE ';' { @@ -1308,7 +1410,7 @@ jump_statement $$ = NULL; } else { - $$ = newAst(EX_VALUE,symbolVal(STACK_PEEK(continueStack))); + $$ = newAst_VALUE(symbolVal(STACK_PEEK(continueStack))); $$ = newNode(GOTO,$$,NULL); /* mark the continue label as referenced */ STACK_PEEK(continueStack)->isref = 1; @@ -1319,7 +1421,7 @@ jump_statement werror(E_BREAK_CONTEXT); $$ = NULL; } else { - $$ = newAst(EX_VALUE,symbolVal(STACK_PEEK(breakStack))); + $$ = newAst_VALUE(symbolVal(STACK_PEEK(breakStack))); $$ = newNode(GOTO,$$,NULL); STACK_PEEK(breakStack)->isref = 1; }