]> git.gag.com Git - fw/sdcc/blobdiff - src/SDCC.y
sdcc:
[fw/sdcc] / src / SDCC.y
index 1ffd9a4e482271869e67eba4f9169711be17613d..95f19b129f5fba708e23e8119df9df9ce44790e9 100644 (file)
@@ -102,14 +102,15 @@ bool uselessDecl = TRUE;
 %token DUMMY_READ_VOLATILE ENDCRITICAL SWAP INLINE RESTRICT
 
 %type <yyint> Interrupt_storage
-%type <sym> identifier declarator declarator2 declarator3 enumerator_list enumerator
+%type <sym> identifier identifier_or_typename declarator declarator2 declarator3
+%type <sym> enumerator_list enumerator
 %type <sym> struct_declarator function_declarator function_declarator2
 %type <sym> struct_declarator_list struct_declaration struct_declaration_list
 %type <sym> declaration init_declarator_list init_declarator
 %type <sym> declaration_list identifier_list
 %type <sym> declarator2_function_attributes while do for critical
 %type <lnk> pointer type_specifier_list type_specifier type_name
-%type <lnk> storage_class_specifier struct_or_union_specifier
+%type <lnk> storage_class_specifier struct_or_union_specifier function_specifier
 %type <lnk> declaration_specifiers sfr_reg_bit sfr_attributes type_specifier2
 %type <lnk> function_attribute function_attributes enum_specifier
 %type <lnk> abstract_declarator abstract_declarator2 unqualified_pointer
@@ -520,6 +521,20 @@ declaration_specifiers
      else
        $$ = mergeSpec($1,$2, "type_specifier declaration_specifiers");
    }
+   | function_specifier                                    { $$ = $1; }
+   | function_specifier declaration_specifiers          { 
+     /* 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, "function_specifier declaration_specifiers - skipped");
+       $$ = $2 ;
+     }
+     else
+       $$ = mergeSpec($1,$2, "function_specifier declaration_specifiers");
+   }
    ;
 
 init_declarator_list
@@ -556,6 +571,13 @@ storage_class_specifier
                }
    ;
 
+function_specifier
+   : INLINE   {
+                  $$ = newLink (SPECIFIER) ;
+                  SPEC_INLINE($$) = 1 ;
+               }
+   ;
+
 Interrupt_storage
    : INTERRUPT { $$ = INTNO_UNSPEC ; }
    | INTERRUPT constant_expr
@@ -625,6 +647,10 @@ type_specifier2
                   $$=newLink(SPECIFIER);
                   SPEC_VOLATILE($$) = 1 ;
                }
+   | RESTRICT  {
+                  $$=newLink(SPECIFIER);
+                  SPEC_RESTRICT($$) = 1 ;
+               }
    | FLOAT     {
                   $$=newLink(SPECIFIER);
                   SPEC_NOUN($$) = V_FLOAT;
@@ -962,40 +988,37 @@ enum_specifier
    ;
 
 enumerator_list
-   : enumerator
-   | enumerator_list ',' {
-                         }
-   | enumerator_list ',' enumerator
-     {
-       symbol *dsym;
-
-       for (dsym=$1; dsym; dsym=dsym->next)
-         {
-           if (strcmp($3->name, dsym->name)==0)
-             {
-               werrorfl($3->fileDef, $3->lineDef, E_DUPLICATE_MEMBER, "enum", $3->name);
-               werrorfl(dsym->fileDef, dsym->lineDef, E_PREVIOUS_DEF);
-             }
-         }
-
-       $3->next = $1 ;
-       $$ = $3  ;
-     }
-   ;
+    : enumerator
+    | enumerator_list ','
+    | enumerator_list ',' enumerator
+      {
+        $3->next = $1 ;
+        $$ = $3  ;
+      }
+    ;
 
 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 ;
-       // do this now, so we can use it for the next enums in the list
-       addSymChain(&$1);
-     }
-   ;
+    : identifier opt_assign_expr
+      {
+        symbol *sym;
+
+        /* make the symbol one level up */
+        $1->level-- ;
+        // check if the symbol at the same level already exists
+        if ((sym = findSymWithLevel (SymbolTab, $1)) &&
+          sym->level == $1->level)
+          {
+            werrorfl ($1->fileDef, $1->lineDef, E_DUPLICATE_MEMBER, "enum", $1->name);
+            werrorfl (sym->fileDef, sym->lineDef, E_PREVIOUS_DEF);
+          }
+        $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
    :  '='   constant_expr  {
@@ -1159,6 +1182,7 @@ pointer
                  DCL_TSPEC($1) = $2;
                  DCL_PTR_CONST($1) = SPEC_CONST($2);
                  DCL_PTR_VOLATILE($1) = SPEC_VOLATILE($2);
+                 DCL_PTR_RESTRICT($1) = SPEC_RESTRICT($2);
              }
              else
                  werror (W_PTR_TYPE_INVALID);
@@ -1171,39 +1195,40 @@ pointer
          }
    | unqualified_pointer type_specifier_list pointer
          {
-             $$ = $1 ;
-             if (IS_SPEC($2) && DCL_TYPE($3) == UPOINTER) {
-                 DCL_PTR_CONST($1) = SPEC_CONST($2);
-                 DCL_PTR_VOLATILE($1) = SPEC_VOLATILE($2);
-                 switch (SPEC_SCLS($2)) {
-                 case S_XDATA:
-                     DCL_TYPE($3) = FPOINTER;
-                     break;
-                 case S_IDATA:
-                     DCL_TYPE($3) = IPOINTER ;
-                     break;
-                 case S_PDATA:
-                     DCL_TYPE($3) = PPOINTER ;
-                     break;
-                 case S_DATA:
-                     DCL_TYPE($3) = POINTER ;
-                     break;
-                 case S_CODE:
-                     DCL_TYPE($3) = CPOINTER ;
-                     break;
-                 case S_EEPROM:
-                     DCL_TYPE($3) = EEPPOINTER;
-                     break;
-                 default:
-                   // this could be just "constant"
-                   // werror(W_PTR_TYPE_INVALID);
-                     ;
-                 }
-             }
-             else
-                 werror (W_PTR_TYPE_INVALID);
-             $$->next = $3 ;
-         }
+            $$ = $1 ;               
+            if (IS_SPEC($2) && DCL_TYPE($3) == UPOINTER) {
+                DCL_PTR_CONST($1) = SPEC_CONST($2);
+                DCL_PTR_VOLATILE($1) = SPEC_VOLATILE($2);
+                DCL_PTR_RESTRICT($1) = SPEC_RESTRICT($2);
+                switch (SPEC_SCLS($2)) {
+                case S_XDATA:
+                    DCL_TYPE($3) = FPOINTER;
+                    break;
+                case S_IDATA:
+                    DCL_TYPE($3) = IPOINTER ;
+                    break;
+                case S_PDATA:
+                    DCL_TYPE($3) = PPOINTER ;
+                    break;
+                case S_DATA:
+                    DCL_TYPE($3) = POINTER ;
+                    break;
+                case S_CODE:
+                    DCL_TYPE($3) = CPOINTER ;
+                    break;
+                case S_EEPROM:
+                    DCL_TYPE($3) = EEPPOINTER;
+                    break;
+                default:
+                  // this could be just "constant" 
+                  // werror(W_PTR_TYPE_INVALID);
+                    ;
+                }
+            }
+            else 
+                werror (W_PTR_TYPE_INVALID);
+            $$->next = $3 ;
+        }
    ;
 
 unqualified_pointer
@@ -1693,5 +1718,17 @@ jump_statement
 identifier
    : IDENTIFIER   { $$ = newSymbol ($1,NestLevel) ; }
    ;
+
+identifier_or_typename
+    : identifier
+    | TYPE_NAME {
+        symbol *sym;
+        sym_link   *p  ;
+        sym = findSym(TypedefTab,NULL,$1) ;
+        $$ = p = copyLinkChain(sym->type);
+        SPEC_TYPEDEF(getSpec(p)) = 0;
+        ignoreTypedefType = 1;
+      }
+
 %%