More strcpy() strcat() sprintf() squashing
[fw/sdcc] / src / SDCC.y
index 954010939580ec2aaf9efb5c8d1a4e636cd3cfa4..ab27ae5aef46627737cd0b49f172fb09241e318f 100644 (file)
@@ -34,6 +34,7 @@
 #include "port.h"
 #include "newalloc.h"
 #include "SDCCerr.h"
+#include "SDCCutil.h"
 
 extern int yyerror (char *);
 extern FILE    *yyin;
@@ -74,7 +75,7 @@ value *cenum = NULL  ;  /* current enumeration  type chain*/
 
 %token <yychar> IDENTIFIER TYPE_NAME
 %token <val>   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 <yyint> MUL_ASSIGN DIV_ASSIGN MOD_ASSIGN ADD_ASSIGN
@@ -85,7 +86,7 @@ value *cenum = NULL  ;  /* current enumeration  type chain*/
 %token CHAR SHORT INT LONG SIGNED UNSIGNED FLOAT DOUBLE CONST VOLATILE VOID BIT
 %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 <yyinline> INLINEASM
 %token IFX ADDRESS_OF GET_VALUE_AT_ADDRESS SPIL UNSPIL GETHBIT
 %token BITWISEAND UNARYMINUS IPUSH IPOP PCALL  ENDFUNCTION JUMPTABLE
@@ -98,11 +99,11 @@ value *cenum = NULL  ;  /* current enumeration  type chain*/
 %type <sym> struct_declarator_list  struct_declaration   struct_declaration_list
 %type <sym> declaration init_declarator_list init_declarator
 %type <sym> declaration_list identifier_list parameter_identifier_list
-%type <sym> declarator2_using_reentrant while do for
+%type <sym> declarator2_function_attributes while do for
 %type <lnk> pointer type_specifier_list type_specifier type_name
 %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> function_attribute function_attributes enum_specifier
 %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
@@ -128,7 +129,9 @@ file
    ;
 
 external_definition
-   : function_definition     { blockNo=0;}
+   : function_definition     { 
+                               blockNo=0;
+                             }
    | declaration             { 
                               if ($1 && $1->type
                                && IS_FUNC($1->type))
@@ -167,41 +170,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($$)) {
@@ -212,8 +222,8 @@ using_reentrant_interrupt
                      {
                         $$ = newLink () ;
                         $$->class = SPECIFIER ;
-                        SPEC_INTN($$) = $1 ;
-                        SPEC_INTRTN($$) = 1;
+                        FUNC_INTNO($$) = $1 ;
+                        FUNC_ISISR($$) = 1;
                      }
    ;
 
@@ -277,6 +287,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
@@ -396,34 +407,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;
@@ -756,11 +767,11 @@ struct_declaration
               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;
        }
@@ -789,8 +800,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 '}' {
@@ -804,8 +815,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 ;
                                              }
@@ -836,15 +847,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
@@ -856,28 +869,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
@@ -914,20 +946,22 @@ 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, remove the symbol args
-            // (if any)
-            if (IS_PTR($1->type) && IS_FUNC($1->etype)) {
+            // 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);
-              /* fprintf (stderr, "Removed parm symbols of %s in line %d\n", 
-                 $1->name, yylineno); */
             }
             
             $$ = $1;
@@ -953,7 +987,7 @@ pointer
          {
             $$ = $1 ;          
             $$->next = $2 ;
-            DCL_TYPE($2)=GPOINTER;
+            DCL_TYPE($2)=port->unqualified_pointer;
         }
    | unqualified_pointer type_specifier_list pointer
          {
@@ -982,7 +1016,9 @@ pointer
                     DCL_TYPE($3) = EEPPOINTER;
                     break;
                 default:
-                    werror(W_PTR_TYPE_INVALID);
+                  // this could be just "constant" 
+                  // werror(W_PTR_TYPE_INVALID);
+                    ;
                 }
             }
             else 
@@ -1001,7 +1037,20 @@ unqualified_pointer
 
 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
@@ -1056,9 +1105,13 @@ type_name
                 /* go to the end of the list */
                 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 ;
                }   
    ;
 
@@ -1101,6 +1154,12 @@ abstract_declarator2
      // $1 must be a pointer to a function
      sym_link *p=newLink();
      DCL_TYPE(p) = FUNCTION;
+     if (!$1) {
+       // ((void (code *) ()) 0) ()
+       $1=newLink();
+       DCL_TYPE($1)=CPOINTER;
+       $$ = $1;
+     }
      $1->next=p;
    }
    | abstract_declarator2 '(' parameter_type_list ')' {
@@ -1111,9 +1170,16 @@ abstract_declarator2
        // $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); }
@@ -1135,14 +1201,14 @@ statement
    | jump_statement
    | INLINEASM  ';'      {
                             ast *ex = newNode(INLINEASM,NULL,NULL);
-                           ex->values.inlineasm = malloc(strlen($1)+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); }
    ;
@@ -1229,7 +1295,8 @@ selection_statement
                               ex->values.switchVals.swNum = swLabel ;
                                  
                               /* now create the label */
-                              sprintf(lbuff,"_swBrk_%d",swLabel++);
+                              SNPRINTF(lbuff, sizeof(lbuff), 
+                                      "_swBrk_%d",swLabel++);
                               $<sym>$  =  newSymbol(lbuff,NestLevel);
                               /* put label in the break stack  */
                               STACK_PUSH(breakStack,$<sym>$);   
@@ -1245,45 +1312,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