* support/Util/NewAlloc.c (freeTrace): Changed free for the gc case to not free...
[fw/sdcc] / src / SDCC.y
index 59c7b982685838b7e7c3a3664448225ba2db899b..954010939580ec2aaf9efb5c8d1a4e636cd3cfa4 100644 (file)
@@ -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       */
@@ -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 <yyinline> 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 <yyint>  Interrupt_storage
 %type <sym> identifier  declarator  declarator2 enumerator_list enumerator
@@ -101,7 +103,7 @@ value *cenum = NULL  ;  /* current enumeration  type chain*/
 %type <lnk> storage_class_specifier struct_or_union_specifier
 %type <lnk> declaration_specifiers  sfr_reg_bit type_specifier2
 %type <lnk> using_reentrant using_reentrant_interrupt enum_specifier
-%type <lnk> abstract_declarator abstract_declarator2 far_near_pointer far_near
+%type <lnk> abstract_declarator abstract_declarator2 unqualified_pointer
 %type <val> parameter_type_list parameter_list parameter_declaration opt_assign_expr
 %type <sdef> stag opt_stag
 %type <asts> primary_expr
@@ -167,7 +169,7 @@ function_definition
 
 using_reentrant
    : using_reentrant_interrupt
-   | using_reentrant_interrupt using_reentrant { $$ = mergeSpec($1,$2); }
+   | using_reentrant_interrupt using_reentrant { $$ = mergeSpec($1,$2,"using_reentrant"); }
    ;
 
 using_reentrant_interrupt
@@ -480,11 +482,11 @@ declaration_specifiers
        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, yytext);
        $$ = $2 ;
      }
      else
-       $$ = mergeSpec($1,$2); 
+       $$ = mergeSpec($1,$2, yytext);
    }
    | type_specifier                                { $$ = $1; }
    | type_specifier declaration_specifiers          { 
@@ -494,11 +496,11 @@ declaration_specifiers
        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, yytext);
        $$ = $2 ;
      }
      else
-       $$ = mergeSpec($1,$2); 
+       $$ = mergeSpec($1,$2, yytext);
    }
    ;
 
@@ -565,8 +567,7 @@ type_specifier2
    | SHORT  {
                $$=newLink();
                $$->class = SPECIFIER   ;
-               SPEC_NOUN($$) = V_INT   ;
-              SPEC_SHORT($$) = 1      ;
+              $$->select.s._short = 1 ;
             }
    | INT    {
                $$=newLink();
@@ -576,13 +577,12 @@ type_specifier2
    | LONG   {
                $$=newLink();
                $$->class = SPECIFIER   ;
-               SPEC_NOUN($$) = V_INT   ;
               SPEC_LONG($$) = 1       ;
             }
    | SIGNED {
                $$=newLink();
                $$->class = SPECIFIER   ;
-               SPEC_SIGNED($$) = 1     ;
+               $$->select.s._signed = 1;
             }
    | UNSIGNED  {
                $$=newLink();
@@ -597,7 +597,6 @@ type_specifier2
    | CONST  {
                $$=newLink();
               $$->class = SPECIFIER ;
-              SPEC_SCLS($$) = S_CONSTANT ;
               SPEC_CONST($$) = 1;
             }
    | VOLATILE  {
@@ -658,7 +657,6 @@ type_specifier2
          {
             symbol *sym;
             sym_link   *p  ;
-
             sym = findSym(TypedefTab,NULL,$1) ;
             $$ = p = copyLinkChain(sym->type);
            SPEC_TYPEDEF(getSpec(p)) = 0;
@@ -713,24 +711,23 @@ 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
@@ -752,14 +749,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));              
-              
           }
            $$ = $2;
        }
@@ -775,7 +776,7 @@ struct_declarator_list
    ;
 
 struct_declarator
-   : declarator
+   : declarator 
    | ':' constant_expr  {  
                            $$ = newSymbol (genSymName(NestLevel),NestLevel) ; 
                            $$->bitVar = (int) floatFromVal(constExprValue($2,TRUE));
@@ -802,7 +803,7 @@ enum_specifier
                                                    (csym && csym->level == $2->level))
                                                    werror(E_DUPLICATE_TYPEDEF,csym->name);
 
-                                                addSym ( enumTab,$2,$2->name,$2->level,$2->block);
+                                                addSym ( enumTab,$2,$2->name,$2->level,$2->block, 0);
                                                addSymChain ($4);
                                                 allocVariables (reverseSyms($4));
                                                 $$ = copyLinkChain(cenum->type);
@@ -826,6 +827,8 @@ enum_specifier
 
 enumerator_list
    : enumerator
+   | enumerator_list ',' {
+                         }
    | enumerator_list ',' enumerator {
                                        $3->next = $1 ;
                                        $$ = $3  ;
@@ -914,9 +917,19 @@ declarator2
             $1->hasVargs = IS_VARG($4);
             $1->args = reverseVal($4)  ;
             
+            
             /* nest level was incremented to take care of the parms  */
             NestLevel-- ;
             currBlockno--;
+
+            // if this was a pointer to a function, remove the symbol args
+            // (if any)
+            if (IS_PTR($1->type) && IS_FUNC($1->etype)) {
+              cleanUpLevel(SymbolTab,NestLevel+1);
+              /* fprintf (stderr, "Removed parm symbols of %s in line %d\n", 
+                 $1->name, yylineno); */
+            }
+            
             $$ = $1;
          }
    | declarator2 '(' parameter_identifier_list ')'
@@ -930,18 +943,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)=GPOINTER;
         }
-   | far_near_pointer type_specifier_list pointer
+   | unqualified_pointer type_specifier_list pointer
          {
             $$ = $1 ;               
             if (IS_SPEC($2) && DCL_TYPE($3) == UPOINTER) {
@@ -963,6 +977,7 @@ pointer
                 case S_CODE:
                     DCL_PTR_CONST($3) = 1;
                     DCL_TYPE($3) = CPOINTER ;
+                    break;
                 case S_EEPROM:
                     DCL_TYPE($3) = EEPPOINTER;
                     break;
@@ -976,31 +991,17 @@ 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         {  $$ = mergeSpec ($1,$2, "type_specifier_list"); }
    ;
 
 parameter_identifier_list
@@ -1096,9 +1097,23 @@ 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;
+       $1->next=p;
+     }
+   }
 
 initializer
    : assignment_expr                { $$ = newiList(INIT_NODE,$1); }
@@ -1120,7 +1135,7 @@ 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;
                          }