fix several 'three operand in far space' problems
[fw/sdcc] / src / SDCC.y
index 44b19d5ffcbef959e58258443429802acb9fe562..98b944db8b945ed14153918536b25597ec1dc461 100644 (file)
 #include "SDCCval.h"
 #include "SDCCmem.h"
 #include "SDCCast.h"
+#include "port.h"
+#include "newalloc.h"
+#include "SDCCerr.h"
 
 extern int yyerror (char *);
 extern FILE    *yyin;
-extern char srcLstFname[];
 int NestLevel = 0 ;     /* current NestLevel       */
 int stackPtr  = 1 ;     /* stack pointer           */
 int xstackPtr = 0 ;     /* xstack pointer          */
@@ -60,7 +62,7 @@ value *cenum = NULL  ;  /* current enumeration  type chain*/
     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               */
@@ -125,6 +127,23 @@ file
 external_definition
    : 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);
@@ -201,14 +220,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
@@ -224,14 +243,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);}
@@ -250,7 +269,7 @@ 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)); }
    ;
               
 unary_operator
@@ -264,7 +283,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
@@ -288,41 +307,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
@@ -438,7 +456,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) ;
@@ -454,7 +472,7 @@ 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);
@@ -468,7 +486,7 @@ 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);
@@ -524,12 +542,12 @@ 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)) ;
         }
    ;
 
@@ -634,7 +652,7 @@ type_specifier2
    | TYPE_NAME    
          {
             symbol *sym;
-            link   *p  ;
+            sym_link   *p  ;
 
             sym = findSym(TypedefTab,NULL,$1) ;
             $$ = p = copyLinkChain(sym->type);
@@ -859,7 +877,7 @@ declarator2
    | '(' declarator ')'     { $$ = $2; }
    | declarator2 '[' ']'
          {
-            link   *p;
+            sym_link   *p;
 
             p = newLink ();
             DCL_TYPE(p) = ARRAY ;
@@ -868,7 +886,7 @@ declarator2
          }
    | declarator2 '[' constant_expr ']'
          {
-            link   *p ;
+            sym_link   *p ;
                        value *tval;
                        
             p = (tval = constExprValue($3,TRUE))->etype;
@@ -1030,7 +1048,7 @@ 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 ;
@@ -1097,7 +1115,7 @@ statement
    | jump_statement
    | INLINEASM  ';'      {
                             ast *ex = newNode(INLINEASM,NULL,NULL);
-                           ALLOC_ATOMIC(ex->values.inlineasm,strlen($1));
+                           ex->values.inlineasm = Safe_calloc(1,strlen($1)+1);
                            strcpy(ex->values.inlineasm,$1);                        
                            $$ = ex;
                          }   
@@ -1299,7 +1317,7 @@ expr_opt
 jump_statement          
    : GOTO identifier ';'   { 
                               $2->islbl = 1;
-                              $$ = newAst(EX_VALUE,symbolVal($2)); 
+                              $$ = newAst_VALUE(symbolVal($2)); 
                               $$ = newNode(GOTO,$$,NULL);
                            }
    | CONTINUE ';'          {  
@@ -1309,7 +1327,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;
@@ -1320,7 +1338,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;
        }