X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2FSDCC.y;h=4a7ac6cfc2e3ac0beb8062c66926002ba08a90db;hb=e483295e5a0539ea4cea6a708f37fb94ea557c08;hp=2127c4e6fae0536afe7621a9a3eb4c4859c6e566;hpb=a649277810119397e42c869a7c6bc743c2420809;p=fw%2Fsdcc diff --git a/src/SDCC.y b/src/SDCC.y index 2127c4e6..4a7ac6cf 100644 --- a/src/SDCC.y +++ b/src/SDCC.y @@ -58,6 +58,8 @@ 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 */ @@ -72,7 +74,7 @@ value *cenum = NULL ; /* current enumeration type chain*/ %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 @@ -81,14 +83,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 STRUCT UNION ENUM ELIPSIS RANGE FAR %token CASE DEFAULT IF ELSE SWITCH WHILE DO FOR GOTO CONTINUE BREAK RETURN -%token NAKED +%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 @@ -96,12 +98,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 @@ -126,7 +128,9 @@ file ; external_definition - : function_definition { blockNo=0;} + : function_definition { + blockNo=0; + } | declaration { if ($1 && $1->type && IS_FUNC($1->type)) @@ -165,41 +169,48 @@ function_definition } ; -using_reentrant - : using_reentrant_interrupt - | using_reentrant_interrupt using_reentrant { $$ = mergeSpec($1,$2,"using_reentrant"); } +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); + FUNC_REGBANK($$) = (int) floatFromVal($2); } | REENTRANT { $$ = newLink (); $$->class = SPECIFIER ; - SPEC_RENT($$) = 1; + FUNC_ISREENT($$)=1; } | CRITICAL { $$ = newLink (); $$->class = SPECIFIER ; - SPEC_CRTCL($$) = 1; + FUNC_ISCRITICAL($$) = 1; } | NAKED { $$ = newLink (); $$->class = SPECIFIER ; - SPEC_NAKED($$) = 1; + FUNC_ISNAKED($$)=1; + } + | JAVANATIVE { $$ = newLink (); + $$->class = SPECIFIER ; + FUNC_ISJAVANATIVE($$)=1; + } + | OVERLAY { $$ = newLink (); + $$->class = SPECIFIER ; + FUNC_ISOVERLAY($$)=1; } | NONBANKED {$$ = newLink (); $$->class = SPECIFIER ; - SPEC_NONBANKED($$) = 1; - if (SPEC_BANKED($$)) { + FUNC_NONBANKED($$) = 1; + if (FUNC_BANKED($$)) { werror(W_BANKED_WITH_NONBANKED); } } | BANKED {$$ = newLink (); $$->class = SPECIFIER ; - SPEC_BANKED($$) = 1; - if (SPEC_NONBANKED($$)) { + FUNC_BANKED($$) = 1; + if (FUNC_NONBANKED($$)) { werror(W_BANKED_WITH_NONBANKED); } if (SPEC_STAT($$)) { @@ -210,8 +221,8 @@ using_reentrant_interrupt { $$ = newLink () ; $$->class = SPECIFIER ; - SPEC_INTN($$) = $1 ; - SPEC_INTRTN($$) = 1; + FUNC_INTNO($$) = $1 ; + FUNC_ISISR($$) = 1; } ; @@ -275,6 +286,7 @@ unary_expr | unary_operator cast_expr { $$ = newNode($1,$2,NULL) ; } | SIZEOF unary_expr { $$ = newNode(SIZEOF,NULL,$2); } | SIZEOF '(' type_name ')' { $$ = newAst_VALUE(sizeofOp($3)); } + | TYPEOF unary_expr { $$ = newNode(TYPEOF,NULL,$2); } ; unary_operator @@ -394,34 +406,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; @@ -747,15 +759,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); - /* make sure the type is complete and sane */ - checkTypeSanity(sym->etype, sym->name); } else addDecl (sym,0,cloneSpec($1)); + /* make sure the type is complete and sane */ + checkTypeSanity(sym->etype, sym->name); } $$ = $2; } @@ -771,7 +786,7 @@ struct_declarator_list ; struct_declarator - : declarator + : declarator | ':' constant_expr { $$ = newSymbol (genSymName(NestLevel),NestLevel) ; $$->bitVar = (int) floatFromVal(constExprValue($2,TRUE)); @@ -784,8 +799,8 @@ struct_declarator enum_specifier : ENUM '{' enumerator_list '}' { - addSymChain ($3); - allocVariables(reverseSyms($3)) ; + //addSymChain ($3); + //allocVariables(reverseSyms($3)) ; $$ = copyLinkChain(cenum->type); } | ENUM identifier '{' enumerator_list '}' { @@ -799,8 +814,8 @@ enum_specifier werror(E_DUPLICATE_TYPEDEF,csym->name); addSym ( enumTab,$2,$2->name,$2->level,$2->block, 0); - addSymChain ($4); - allocVariables (reverseSyms($4)); + //addSymChain ($4); + //allocVariables (reverseSyms($4)); $$ = copyLinkChain(cenum->type); SPEC_SCLS(getSpec($$)) = 0 ; } @@ -831,15 +846,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 @@ -862,17 +879,34 @@ opt_assign_expr ; 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 @@ -909,12 +943,24 @@ 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 ')' @@ -928,18 +974,19 @@ declarator2 ; 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) { @@ -961,11 +1008,13 @@ 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 @@ -974,31 +1023,30 @@ pointer } ; -far_near_pointer - : far_near '*' { - if ($1 == NULL) { - $$ = newLink(); - DCL_TYPE($$) = POINTER ; - } - else - $$ = $1 ; +unqualified_pointer + : '*' + { + $$ = newLink(); + 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_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"); + $$ = $2 ; + } + else + $$ = mergeSpec($1,$2, "type_specifier_list"); + } ; parameter_identifier_list @@ -1094,9 +1142,29 @@ abstract_declarator2 } | '(' ')' { $$ = 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(); + DCL_TYPE(p) = FUNCTION; + $1->next=p; + } + | abstract_declarator2 '(' parameter_type_list ')' { + if (!IS_VOID($3->type)) { + // 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(); + DCL_TYPE(p) = FUNCTION; + if (!$1) { + // ((void (code *) (void)) 0) () + $1=newLink(); + DCL_TYPE($1)=CPOINTER; + $$ = $1; + } + $1->next=p; + } + } initializer : assignment_expr { $$ = newiList(INIT_NODE,$1); } @@ -1118,14 +1186,15 @@ statement | jump_statement | INLINEASM ';' { ast *ex = newNode(INLINEASM,NULL,NULL); - ex->values.inlineasm = Safe_calloc(1,strlen($1)+1); + ex->values.inlineasm = malloc(strlen($1)+1); strcpy(ex->values.inlineasm,$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); } ;