Add support for WinCE based toolchains.
[deliverable/binutils-gdb.git] / ld / ldexp.c
index c91af29aaff237a9a0215b4650b232b9c0e95952..0c38314ffa4399d41917de861e5fc60a3edf94f0 100644 (file)
@@ -1,10 +1,13 @@
-/* Copyright (C) 1991 Free Software Foundation, Inc.
+/* This module handles expression trees.
+   Copyright (C) 1991, 92, 93, 94, 95, 96, 97, 98, 1999
+   Free Software Foundation, Inc.
+   Written by Steve Chamberlain of Cygnus Support (sac@cygnus.com).
 
 This file is part of GLD, the Gnu Linker.
 
 GLD is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 
 This file is part of GLD, the Gnu Linker.
 
 GLD is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 1, or (at your option)
+the Free Software Foundation; either version 2, or (at your option)
 any later version.
 
 GLD is distributed in the hope that it will be useful,
 any later version.
 
 GLD is distributed in the hope that it will be useful,
@@ -13,151 +16,154 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
-along with GLD; see the file COPYING.  If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+along with GLD; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
 
 /*
 
 /*
-   $Id$ 
-*/
+This module is in charge of working out the contents of expressions.
 
 
-/*
- * Written by Steve Chamberlain
- * steve@cygnus.com
- *
- * This module handles expression trees.
- */
+It has to keep track of the relative/absness of a symbol etc. This is
+done by keeping all values in a struct (an etree_value_type) which
+contains a value, a section to which it is relative and a valid bit.
+
+*/
 
 
 
 
-#include "sysdep.h"
 #include "bfd.h"
 #include "bfd.h"
+#include "sysdep.h"
+#include "bfdlink.h"
 
 #include "ld.h"
 #include "ldmain.h"
 #include "ldmisc.h"
 #include "ldexp.h"
 
 #include "ld.h"
 #include "ldmain.h"
 #include "ldmisc.h"
 #include "ldexp.h"
-#include "ldgram.tab.h"
-#include "ldsym.h"
+#include "ldgram.h"
 #include "ldlang.h"
 
 #include "ldlang.h"
 
-extern char *output_filename;
-extern unsigned int undefined_global_sym_count;
-extern unsigned int defined_global_sym_count;
-extern bfd *output_bfd;
-extern size_t largest_section;
-extern lang_statement_list_type file_chain;
-extern args_type command_line;
-extern ld_config_type config;
-
-extern lang_input_statement_type *script_file;
-extern unsigned int defined_global_sym_count;
-
-extern bfd_vma print_dot;
-
+static void exp_print_token PARAMS ((token_code_type code));
+static void make_abs PARAMS ((etree_value_type *ptr));
+static etree_value_type new_abs PARAMS ((bfd_vma value));
+static void check PARAMS ((lang_output_section_statement_type *os,
+                          const char *name, const char *op));
+static etree_value_type new_rel
+  PARAMS ((bfd_vma value, lang_output_section_statement_type *section));
+static etree_value_type new_rel_from_section
+  PARAMS ((bfd_vma value, lang_output_section_statement_type *section));
+static etree_value_type fold_binary
+  PARAMS ((etree_type *tree,
+          lang_output_section_statement_type *current_section,
+          lang_phase_type allocation_done,
+          bfd_vma dot, bfd_vma *dotp));
+static etree_value_type fold_name
+  PARAMS ((etree_type *tree,
+          lang_output_section_statement_type *current_section,
+          lang_phase_type allocation_done,
+          bfd_vma dot));
+static etree_value_type exp_fold_tree_no_dot
+  PARAMS ((etree_type *tree,
+          lang_output_section_statement_type *current_section,
+          lang_phase_type allocation_done));
 
 static void
 
 static void
-exp_print_token(outfile, code)
-FILE *outfile;
-token_code_type code;
+exp_print_token (code)
+     token_code_type code;
 {
 {
-  static struct  {
-    token_code_type code;
-    char *name;
-  } table[] =
+  static CONST struct
     {
     {
-      INT,     "int",
-      NAME,"NAME",
-      PLUSEQ,"+=",
-      MINUSEQ,"-=",
-      MULTEQ,"*=",
-      DIVEQ,"/=",
-      LSHIFTEQ,"<<=",
-      RSHIFTEQ,">>=",
-      ANDEQ,"&=",
-      OREQ,"|=",
-      OROR,"||",
-      ANDAND,"&&",
-      EQ,"==",
-      NE,"!=",
-      LE,"<=",
-      GE,">=",
-      LSHIFT,"<<",
-      RSHIFT,">>=",
-      ALIGN_K,"ALIGN",
-      BLOCK,"BLOCK",
-      SECTIONS,"SECTIONS",
-      SIZEOF_HEADERS,"SIZEOF_HEADERS",
-      NEXT,"NEXT",
-      SIZEOF,"SIZEOF",
-      ADDR,"ADDR",
-      MEMORY,"MEMORY",
-
-
-
-
-
-      DEFINED,"DEFINED",
-      TARGET_K,"TARGET",
-      SEARCH_DIR,"SEARCH_DIR",
-      MAP,"MAP",
-      LONG,"LONG",
-      SHORT,"SHORT",
-      BYTE,"BYTE",
-      ENTRY,"ENTRY",
-    0,(char *)NULL} ;
-
-
-
+      token_code_type code;
+      char *name;
+    } table[] =
+      {
+       { INT,  "int" },
+       { REL, "relocateable" },
+       { NAME,"NAME" },
+       { PLUSEQ,"+=" },
+       { MINUSEQ,"-=" },
+       { MULTEQ,"*=" },
+       { DIVEQ,"/=" },
+       { LSHIFTEQ,"<<=" },
+       { RSHIFTEQ,">>=" },
+       { ANDEQ,"&=" },
+       { OREQ,"|=" },
+       { OROR,"||" },
+       { ANDAND,"&&" },
+       { EQ,"==" },
+       { NE,"!=" },
+       { LE,"<=" },
+       { GE,">=" },
+       { LSHIFT,"<<" },
+       { RSHIFT,">>=" },
+       { ALIGN_K,"ALIGN" },
+       { BLOCK,"BLOCK" },
+       { SECTIONS,"SECTIONS" },
+       { SIZEOF_HEADERS,"SIZEOF_HEADERS" },
+       { NEXT,"NEXT" },
+       { SIZEOF,"SIZEOF" },
+       { ADDR,"ADDR" },
+       { LOADADDR,"LOADADDR" },
+       { MEMORY,"MEMORY" },
+       { DEFINED,"DEFINED" },
+       { TARGET_K,"TARGET" },
+       { SEARCH_DIR,"SEARCH_DIR" },
+       { MAP,"MAP" },
+       { QUAD,"QUAD" },
+       { SQUAD,"SQUAD" },
+       { LONG,"LONG" },
+       { SHORT,"SHORT" },
+       { BYTE,"BYTE" },
+       { ENTRY,"ENTRY" },
+       { 0,(char *)NULL }
+      };
   unsigned int idx;
   unsigned int idx;
+
   for (idx = 0; table[idx].name != (char*)NULL; idx++) {
     if (table[idx].code == code) {
   for (idx = 0; table[idx].name != (char*)NULL; idx++) {
     if (table[idx].code == code) {
-      fprintf(outfile, "%s", table[idx].name);
+      fprintf(config.map_file, "%s", table[idx].name);
       return;
     }
   }
   /* Not in table, just print it alone */
       return;
     }
   }
   /* Not in table, just print it alone */
-  fprintf(outfile, "%c",code);
+  fprintf(config.map_file, "%c",code);
 }
 
 static void 
 }
 
 static void 
-make_abs(ptr)
-etree_value_type *ptr;
+make_abs (ptr)
+     etree_value_type *ptr;
 {
 {
-  if (ptr->section != (lang_output_section_statement_type *)NULL) {
     asection *s = ptr->section->bfd_section;
     ptr->value += s->vma;
     asection *s = ptr->section->bfd_section;
     ptr->value += s->vma;
-    ptr->section = (lang_output_section_statement_type *)NULL;
-  }
-
+    ptr->section = abs_output_section;
 }
 }
-static
-etree_value_type new_abs(value)
-bfd_vma value;
+
+static etree_value_type
+new_abs (value)
+     bfd_vma value;
 {
   etree_value_type new;
 {
   etree_value_type new;
-  new.valid = true;
-  new.section = (lang_output_section_statement_type *)NULL;
+  new.valid_p = true;
+  new.section = abs_output_section;
   new.value = value;
   return new;
 }
 
 static void 
   new.value = value;
   return new;
 }
 
 static void 
-DEFUN(check, (os, name, op),
-      lang_output_section_statement_type *os AND
-      CONST char *name AND
-      CONST char *op)
+check (os, name, op)
+     lang_output_section_statement_type *os;
+     const char *name;
+     const char *op;
 {
 {
-  if (os == (lang_output_section_statement_type *)NULL) {
-    info("%F%P %s uses undefined section %s\n", op, name);
-  }
-  if (os->processed == false) {
-    info("%F%P %s forward reference of section %s\n",op, name);
-  }
+  if (os == NULL)
+    einfo (_("%F%P: %s uses undefined section %s\n"), op, name);
+  if (! os->processed)
+    einfo (_("%F%P: %s forward reference of section %s\n"), op, name);
 }
 
 }
 
-etree_type *exp_intop(value)
-bfd_vma value;
+etree_type *
+exp_intop (value)
+     bfd_vma value;
 {
 {
-  etree_type *new = (etree_type *)ldmalloc(sizeof(new->value));
+  etree_type *new = (etree_type *) stat_alloc(sizeof(new->value));
   new->type.node_code = INT;
   new->value.value = value;
   new->type.node_class = etree_value;
   new->type.node_code = INT;
   new->value.value = value;
   new->type.node_class = etree_value;
@@ -165,213 +171,300 @@ bfd_vma value;
 
 }
 
 
 }
 
+/* Build an expression representing an unnamed relocateable value.  */
+
+etree_type *
+exp_relop (section, value)
+     asection *section;
+     bfd_vma value;
+{
+  etree_type *new = (etree_type *) stat_alloc (sizeof (new->rel));
+  new->type.node_code = REL;
+  new->type.node_class = etree_rel;
+  new->rel.section = section;
+  new->rel.value = value;
+  return new;
+}
 
 
-static
-etree_value_type new_rel(value, section)
-bfd_vma value;
-lang_output_section_statement_type *section;
+static etree_value_type
+new_rel (value, section)
+     bfd_vma value;
+     lang_output_section_statement_type *section;
 {
   etree_value_type new;
 {
   etree_value_type new;
-  new.valid = true;
+  new.valid_p = true;
   new.value = value;
   new.section = section;
   return new;
 }
 
   new.value = value;
   new.section = section;
   return new;
 }
 
-static
-etree_value_type new_rel_from_section(value, section)
-bfd_vma value;
-lang_output_section_statement_type *section;
+static etree_value_type
+new_rel_from_section (value, section)
+     bfd_vma value;
+     lang_output_section_statement_type *section;
 {
   etree_value_type new;
 {
   etree_value_type new;
-  new.valid = true;
+  new.valid_p = true;
   new.value = value;
   new.section = section;
   new.value = value;
   new.section = section;
-  if (new.section != (lang_output_section_statement_type *)NULL) {
+
     new.value -= section->bfd_section->vma;
     new.value -= section->bfd_section->vma;
-  }
+
   return new;
 }
 
 static etree_value_type 
   return new;
 }
 
 static etree_value_type 
-fold_binary(tree, current_section, allocation_done, dot, dotp)
-etree_type *tree;
-lang_output_section_statement_type *current_section;
-lang_phase_type  allocation_done;
-bfd_vma dot;
-bfd_vma *dotp;
+fold_binary (tree, current_section, allocation_done, dot, dotp)
+     etree_type *tree;
+     lang_output_section_statement_type *current_section;
+     lang_phase_type allocation_done;
+     bfd_vma dot;
+     bfd_vma *dotp;
 {
   etree_value_type result;
 
 {
   etree_value_type result;
 
-  result =  exp_fold_tree(tree->binary.lhs,  current_section,
+  result = exp_fold_tree (tree->binary.lhs, current_section,
                          allocation_done, dot, dotp);
                          allocation_done, dot, dotp);
-  if (result.valid) {
-    etree_value_type other;
-    other = exp_fold_tree(tree->binary.rhs,
-                         current_section,
-                         allocation_done, dot,dotp) ;
-    if (other.valid) {
-       /* If values are from different sections, or this is an */
-       /* absolute expression, make both source args absolute */
-      if (result.section !=  other.section ||
-         current_section == (lang_output_section_statement_type *)NULL) {
-
-       make_abs(&result);
-       make_abs(&other);
-      }
-         
-      switch (tree->type.node_code) 
+  if (result.valid_p)
+    {
+      etree_value_type other;
+
+      other = exp_fold_tree (tree->binary.rhs,
+                            current_section,
+                            allocation_done, dot,dotp) ;
+      if (other.valid_p)
        {
        {
-       case '%':
-         /* Mod,  both absolule*/
+         /* If the values are from different sections, or this is an
+            absolute expression, make both the source arguments
+            absolute.  However, adding or subtracting an absolute
+            value from a relative value is meaningful, and is an
+            exception.  */
+         if (current_section != abs_output_section
+             && (other.section == abs_output_section
+                 || (result.section == abs_output_section
+                     && tree->type.node_code == '+'))
+             && (tree->type.node_code == '+'
+                 || tree->type.node_code == '-'))
+           {
+             etree_value_type hold;
 
 
-         if (other.value == 0) {
-           info("%F%S % by zero\n");
-         }
-         result.value %= other.value;
-         break;
-       case '/':
-         if (other.value == 0) {
-           info("%F%S / by zero\n");
-         }
-         result.value /= other.value;
-         break;
-#define BOP(x,y) case x : result.value = result.value y other.value;break;
-         BOP('+',+);
-         BOP('*',*);
-         BOP('-',-);
-         BOP(LSHIFT,<<);
-         BOP(RSHIFT,>>);
-         BOP(EQ,==);
-         BOP(NE,!=);
-         BOP('<',<);
-         BOP('>',>);
-         BOP(LE,<=);
-         BOP(GE,>=);
-         BOP('&',&);
-         BOP('^',^);
-         BOP('|',|);
-         BOP(ANDAND,&&);
-         BOP(OROR,||);
-       default:
-         FAIL();
+             /* If there is only one absolute term, make sure it is the
+                second one.  */
+             if (other.section != abs_output_section)
+               {
+                 hold = result;
+                 result = other;
+                 other = hold;
+               }
+           }
+         else if (result.section != other.section
+                  || current_section == abs_output_section)
+           {
+             make_abs(&result);
+             make_abs(&other);
+           }
+
+         switch (tree->type.node_code) 
+           {
+           case '%':
+             if (other.value == 0)
+               einfo (_("%F%S %% by zero\n"));
+             result.value = ((bfd_signed_vma) result.value
+                             % (bfd_signed_vma) other.value);
+             break;
+
+           case '/':
+             if (other.value == 0)
+               einfo (_("%F%S / by zero\n"));
+             result.value = ((bfd_signed_vma) result.value
+                             / (bfd_signed_vma) other.value);
+             break;
+
+#define BOP(x,y) case x : result.value = result.value y other.value; break;
+             BOP('+',+);
+             BOP('*',*);
+             BOP('-',-);
+             BOP(LSHIFT,<<);
+             BOP(RSHIFT,>>);
+             BOP(EQ,==);
+             BOP(NE,!=);
+             BOP('<',<);
+             BOP('>',>);
+             BOP(LE,<=);
+             BOP(GE,>=);
+             BOP('&',&);
+             BOP('^',^);
+             BOP('|',|);
+             BOP(ANDAND,&&);
+             BOP(OROR,||);
+
+           case MAX_K:
+             if (result.value < other.value)
+               result = other;
+             break;
+
+           case MIN_K:
+             if (result.value > other.value)
+               result = other;
+             break;
+
+           default:
+             FAIL();
+           }
+       }
+      else
+       {
+         result.valid_p = false;
        }
     }
        }
     }
-    else {
-      result.valid = false;
-    }
-  }
+
   return result;
 }
   return result;
 }
-etree_value_type invalid()
+
+etree_value_type 
+invalid ()
 {
   etree_value_type new;
 {
   etree_value_type new;
-  new.valid = false;
+  new.valid_p = false;
   return new;
 }
 
   return new;
 }
 
-etree_value_type fold_name(tree, current_section, allocation_done, dot)
-etree_type *tree;
-lang_output_section_statement_type *current_section;
-lang_phase_type  allocation_done;
-bfd_vma dot;
-
+static etree_value_type 
+fold_name (tree, current_section, allocation_done, dot)
+     etree_type *tree;
+     lang_output_section_statement_type *current_section;
+     lang_phase_type  allocation_done;
+     bfd_vma dot;
 {
   etree_value_type result;
   switch (tree->type.node_code) 
       {
       case SIZEOF_HEADERS:
        if (allocation_done != lang_first_phase_enum) 
 {
   etree_value_type result;
   switch (tree->type.node_code) 
       {
       case SIZEOF_HEADERS:
        if (allocation_done != lang_first_phase_enum) 
-           {
-             result = new_abs(bfd_sizeof_headers(output_bfd,
-                                               config.relocateable_output));
-
-           }
-       else {
-         result.valid = false;
-       }
+         {
+           result = new_abs ((bfd_vma)
+                             bfd_sizeof_headers (output_bfd,
+                                                 link_info.relocateable));
+         }
+       else
+         {
+           result.valid_p = false;
+         }
        break;
       case DEFINED:
        break;
       case DEFINED:
-       result.value =
-         ldsym_get_soft(tree->name.name) != (ldsym_type *)NULL;
-       result.section = 0;
-       result.valid = true;
+       if (allocation_done == lang_first_phase_enum)
+         result.valid_p = false;
+       else
+         {
+           struct bfd_link_hash_entry *h;
+
+           h = bfd_wrapped_link_hash_lookup (output_bfd, &link_info,
+                                             tree->name.name,
+                                             false, false, true);
+           result.value = (h != (struct bfd_link_hash_entry *) NULL
+                           && (h->type == bfd_link_hash_defined
+                               || h->type == bfd_link_hash_defweak
+                               || h->type == bfd_link_hash_common));
+           result.section = 0;
+           result.valid_p = true;
+         }
        break;
       case NAME:
        break;
       case NAME:
-       result.valid = false;
-       if (tree->name.name[0] == '.' && tree->name.name[1] == 0) {
-
-         if (allocation_done != lang_first_phase_enum) {
-           result = new_rel_from_section(dot, current_section);
-         }
-         else {
-           result = invalid();
+       result.valid_p = false;
+       if (tree->name.name[0] == '.' && tree->name.name[1] == 0)
+         {
+           if (allocation_done != lang_first_phase_enum)
+             result = new_rel_from_section(dot, current_section);
+           else
+             result = invalid();
          }
          }
-       }
-       else {
-         if (allocation_done == lang_final_phase_enum) {
-           ldsym_type *sy = ldsym_get_soft(tree->name.name);
-         
-           if (sy) {
-             asymbol **sdefp = sy->sdefs_chain;
-
-             if (sdefp) {
-               asymbol *sdef = *sdefp;
-               if (sdef->section == (asection *)NULL) {
-                 /* This is an absolute symbol */
-                 result = new_abs(sdef->value);
-               }
-               else {
-                 lang_output_section_statement_type *os =
-                   lang_output_section_statement_lookup(
-                                                        sdef->section->output_section->name);
-                 /* If the symbol is from a file which we are not
-                    relocating (-R) then return an absolute for its
-                    value */
-                 if (sdef->the_bfd->usrdata && 
-                     ((lang_input_statement_type*)(sdef->the_bfd->usrdata))->just_syms_flag == true) 
+       else if (allocation_done != lang_first_phase_enum)
+         {
+           struct bfd_link_hash_entry *h;
+
+           h = bfd_wrapped_link_hash_lookup (output_bfd, &link_info,
+                                             tree->name.name,
+                                             false, false, true);
+           if (h != NULL
+               && (h->type == bfd_link_hash_defined
+                   || h->type == bfd_link_hash_defweak))
+             {
+               if (bfd_is_abs_section (h->u.def.section))
+                 result = new_abs (h->u.def.value);
+               else if (allocation_done == lang_final_phase_enum
+                        || allocation_done == lang_allocating_phase_enum)
+                 {
+                   asection *output_section;
+
+                   output_section = h->u.def.section->output_section;
+                   if (output_section == NULL)
+                     einfo (_("%X%S: unresolvable symbol `%s' referenced in expression\n"),
+                            tree->name.name);
+                   else
                      {
                      {
-                       result = new_abs(sdef->value + (sdef->section ?
-                                                       sdef->section->vma : 0));
+                       lang_output_section_statement_type *os;
+
+                       os = (lang_output_section_statement_lookup
+                             (bfd_get_section_name (output_bfd,
+                                                    output_section)));
+
+                       /* FIXME: Is this correct if this section is
+                          being linked with -R?  */
+                       result = new_rel ((h->u.def.value
+                                          + h->u.def.section->output_offset),
+                                         os);
                      }
                      }
-                 else {
-                   result = new_rel(sdef->value + sdef->section->output_offset, os);
                  }
                  }
-               }
              }
              }
-           }
-           if (result.valid == false) {
-             info("%F%S: undefined symbol `%s' referenced in expression.\n",
-                  tree->name.name);
-           }
-
+           else if (allocation_done == lang_final_phase_enum)
+             einfo (_("%F%S: undefined symbol `%s' referenced in expression\n"),
+                    tree->name.name);
          }
          }
-       }
-
        break;
 
       case ADDR:
        break;
 
       case ADDR:
+       if (allocation_done != lang_first_phase_enum)
+         {
+           lang_output_section_statement_type *os;
 
 
-       if (allocation_done != lang_first_phase_enum) {
-         lang_output_section_statement_type *os =
-           lang_output_section_find(tree->name.name);
-         check(os,tree->name.name,"ADDR");
-         result =    new_rel((bfd_vma)0,  os);
-       }
-       else {
-         result = invalid();
-       }
+           os = lang_output_section_find (tree->name.name);
+           check (os, tree->name.name, "ADDR");
+           result = new_rel (0, os);
+         }
+       else
+         result = invalid ();
+       break;
+
+      case LOADADDR:
+       if (allocation_done != lang_first_phase_enum)
+         {
+           lang_output_section_statement_type *os;
+
+           os = lang_output_section_find (tree->name.name);
+           check (os, tree->name.name, "LOADADDR");
+           if (os->load_base == NULL)
+             result = new_rel (0, os);
+           else
+             result = exp_fold_tree_no_dot (os->load_base,
+                                            abs_output_section,
+                                            allocation_done);
+         }
+       else
+         result = invalid ();
        break;
        break;
+
       case SIZEOF:
       case SIZEOF:
-       if(allocation_done != lang_first_phase_enum) {
-         lang_output_section_statement_type *os = 
-           lang_output_section_find(tree->name.name);
-         check(os,tree->name.name,"SIZEOF");
-         result = new_abs((bfd_vma)(os->bfd_section->size));
-       }
-       else {
-         result = invalid();
-       }
+       if (allocation_done != lang_first_phase_enum)
+         {
+            int opb = bfd_octets_per_byte (output_bfd);
+           lang_output_section_statement_type *os;
+
+           os = lang_output_section_find (tree->name.name);
+           check (os, tree->name.name, "SIZEOF");
+           result = new_abs (os->bfd_section->_raw_size / opb);
+         }
+       else
+         result = invalid ();
        break;
 
       default:
        break;
 
       default:
@@ -381,195 +474,232 @@ bfd_vma dot;
 
   return result;
 }
 
   return result;
 }
-etree_value_type exp_fold_tree(tree, current_section, allocation_done,
-                              dot, dotp)
-etree_type *tree;
-lang_output_section_statement_type *current_section;
-lang_phase_type  allocation_done;
-bfd_vma dot;
-bfd_vma *dotp;
+etree_value_type 
+exp_fold_tree (tree, current_section, allocation_done, dot, dotp)
+     etree_type *tree;
+     lang_output_section_statement_type *current_section;
+     lang_phase_type  allocation_done;
+     bfd_vma dot;
+     bfd_vma *dotp;
 {
   etree_value_type result;
 
 {
   etree_value_type result;
 
-  if (tree == (etree_type *)NULL) {
-    result.valid = false;
-  }
-  else {
-    switch (tree->type.node_class) 
-       {
-       case etree_value:
-         result = new_rel(tree->value.value, current_section);
-         break;
-       case etree_unary:
-         result = exp_fold_tree(tree->unary.child,
-                                current_section,
-                                allocation_done, dot, dotp);
-         if (result.valid == true)
-             {
-               switch(tree->type.node_code) 
-                   {
-                   case ALIGN_K:
-                     if (allocation_done != lang_first_phase_enum) {
-                       result = new_rel_from_section(ALIGN(dot,
-                                                           result.value) ,
-                                                     current_section);
-
-                     }
-                     else {
-                       result.valid = false;
-                     }
-                     break;
-                   case '~':
-                     make_abs(&result);
-                     result.value = ~result.value;
-                     break;
-                   case '!':
-                     make_abs(&result);
-                     result.value = !result.value;
-                     break;
-                   case '-':
-                     make_abs(&result);
-                     result.value = -result.value;
-                     break;
-                   case NEXT:
-                     if (allocation_done ==lang_allocating_phase_enum) {
-                       make_abs(&result);
-                       result.value = ALIGN(dot, result.value);
-                     }
-                     else {
-                     /* Return next place aligned to value */
-                     result.valid = false;
-                   }
-                     break;
-                   default:
-                     FAIL();
-                   }
-             }
+  if (tree == NULL)
+    {
+      result.valid_p = false;
+      return result;
+    }
 
 
-         break;
-       case etree_trinary:
-
-         result = exp_fold_tree(tree->trinary.cond,
-                                current_section,
-                                allocation_done, dot, dotp);
-         if (result.valid) {
-           result = exp_fold_tree(result.value ?
-                                  tree->trinary.lhs:tree->trinary.rhs,
-                                  current_section,
-                                  allocation_done, dot, dotp);
-         }
+  switch (tree->type.node_class) 
+    {
+    case etree_value:
+      result = new_rel (tree->value.value, current_section);
+      break;
+
+    case etree_rel:
+      if (allocation_done != lang_final_phase_enum)
+       result.valid_p = false;
+      else
+       result = new_rel ((tree->rel.value
+                          + tree->rel.section->output_section->vma
+                          + tree->rel.section->output_offset),
+                         current_section);
+      break;
+
+    case etree_assert:
+      result = exp_fold_tree (tree->assert_s.child,
+                              current_section,
+                              allocation_done, dot, dotp);
+      if (result.valid_p)
+       {
+         if (! result.value)
+           einfo ("%F%P: %s\n", tree->assert_s.message);
+         return result;
+       }
+      break;
 
 
-         break;
-       case etree_binary:
-         result = fold_binary(tree, current_section, allocation_done,
-                              dot, dotp);
-         break;
-       case etree_assign:
-         if (tree->assign.dst[0] == '.' && tree->assign.dst[1] == 0) {
-           /* Assignment to dot can only be done during allocation */
-           if (allocation_done == lang_allocating_phase_enum) {
-             result = exp_fold_tree(tree->assign.src,
-                                    current_section,
-                                    lang_allocating_phase_enum, dot, dotp);
-             if (result.valid == false) {
-               info("%F%S invalid assignment to location counter\n");
-             }
-             else {
-               if (current_section ==
-                   (lang_output_section_statement_type  *)NULL) {
-                 info("%F%S assignment to location counter invalid outside of SECTION\n");
+    case etree_unary:
+      result = exp_fold_tree (tree->unary.child,
+                             current_section,
+                             allocation_done, dot, dotp);
+      if (result.valid_p)
+       {
+         switch (tree->type.node_code) 
+           {
+           case ALIGN_K:
+             if (allocation_done != lang_first_phase_enum)
+               result = new_rel_from_section (ALIGN_N (dot, result.value),
+                                              current_section);
+             else
+               result.valid_p = false;
+             break;
+
+           case ABSOLUTE:
+             if (allocation_done != lang_first_phase_enum && result.valid_p)
+               {
+                 result.value += result.section->bfd_section->vma;
+                 result.section = abs_output_section;
                }
                }
-               else {
-                 unsigned long nextdot =result.value +
-                   current_section->bfd_section->vma;
-                 if (nextdot < dot) {
-                   info("%F%S cannot move location counter backwards");
-                 }
-                 else {
-                   *dotp = nextdot; 
-                 }
+             else 
+               result.valid_p = false;
+             break;
+
+           case '~':
+             make_abs (&result);
+             result.value = ~result.value;
+             break;
+
+           case '!':
+             make_abs (&result);
+             result.value = !result.value;
+             break;
+
+           case '-':
+             make_abs (&result);
+             result.value = -result.value;
+             break;
+
+           case NEXT:
+             /* Return next place aligned to value.  */
+             if (allocation_done == lang_allocating_phase_enum)
+               {
+                 make_abs (&result);
+                 result.value = ALIGN_N (dot, result.value);
                }
                }
-             }
+             else
+               result.valid_p = false;
+             break;
+
+           default:
+             FAIL ();
+             break;
            }
            }
-         }
-         else {
-           ldsym_type *sy = ldsym_get(tree->assign.dst);
-
-           /* If this symbol has just been created then we'll place it into 
-            * a section of our choice
-            */
-           result = exp_fold_tree(tree->assign.src,
-                                  current_section, allocation_done,
-                                  dot, dotp);
-           if (result.valid)
+       }
+      break;
+
+    case etree_trinary:
+      result = exp_fold_tree (tree->trinary.cond, current_section,
+                             allocation_done, dot, dotp);
+      if (result.valid_p)
+       result = exp_fold_tree ((result.value
+                                ? tree->trinary.lhs
+                                : tree->trinary.rhs),
+                               current_section,
+                               allocation_done, dot, dotp);
+      break;
+
+    case etree_binary:
+      result = fold_binary (tree, current_section, allocation_done,
+                           dot, dotp);
+      break;
+
+    case etree_assign:
+    case etree_provide:
+      if (tree->assign.dst[0] == '.' && tree->assign.dst[1] == 0)
+       {
+         /* Assignment to dot can only be done during allocation */
+         if (tree->type.node_class == etree_provide)
+           einfo (_("%F%S can not PROVIDE assignment to location counter\n"));
+         if (allocation_done == lang_allocating_phase_enum
+             || (allocation_done == lang_final_phase_enum
+                 && current_section == abs_output_section))
+           {
+             result = exp_fold_tree (tree->assign.src,
+                                     current_section,
+                                     lang_allocating_phase_enum, dot,
+                                     dotp);
+             if (! result.valid_p)
+               einfo (_("%F%S invalid assignment to location counter\n"));
+             else
                {
                {
-                 asymbol *def;
-                 asymbol **def_ptr = (asymbol **)ldmalloc(sizeof(asymbol **));
-                 /* Add this definition to script file */
-                 def = (asymbol *)bfd_make_empty_symbol(script_file->the_bfd);
-                 *def_ptr = def;
-
-
-                 def->value = result.value;
-                 if (result.section !=
-                     (lang_output_section_statement_type  *)NULL) {
-                   if (current_section !=
-                       (lang_output_section_statement_type *)NULL) {
-                 
-                     def->section = result.section->bfd_section;
-                     def->flags = BSF_GLOBAL | BSF_EXPORT;
-                   }
-                   else {
-                     /* Force to absolute */
-                     def->value += result.section->bfd_section->vma;
-                     def->section = (asection *)NULL;
-                     def->flags = BSF_GLOBAL | BSF_EXPORT | BSF_ABSOLUTE;
+                 if (current_section == NULL)
+                   einfo (_("%F%S assignment to location counter invalid outside of SECTION\n"));
+                 else
+                   {
+                     bfd_vma nextdot;
+
+                     nextdot = (result.value
+                                + current_section->bfd_section->vma);
+                     if (nextdot < dot
+                         && current_section != abs_output_section)
+                       {
+                         einfo (_("%F%S cannot move location counter backwards (from %V to %V)\n"),
+                                dot, nextdot);
+                       }
+                     else
+                       *dotp = nextdot; 
                    }
                    }
-
-
-                 }
-                 else {
-                   def->section = (asection *)NULL;
-                   def->flags = BSF_GLOBAL | BSF_EXPORT | BSF_ABSOLUTE;
-                 }
-
-
-                 def->udata = (PTR)NULL;
-                 def->name = sy->name;
-                 Q_enter_global_ref(def_ptr);
                }
                }
+           }
+       }
+      else
+       {
+         result = exp_fold_tree (tree->assign.src,
+                                 current_section, allocation_done,
+                                 dot, dotp);
+         if (result.valid_p)
+           {
+             boolean create;
+             struct bfd_link_hash_entry *h;
+
+             if (tree->type.node_class == etree_assign)
+               create = true;
+             else
+               create = false;
+             h = bfd_link_hash_lookup (link_info.hash, tree->assign.dst,
+                                       create, false, false);
+             if (h == (struct bfd_link_hash_entry *) NULL)
+               {
+                 if (tree->type.node_class == etree_assign)
+                   einfo (_("%P%F:%s: hash creation failed\n"),
+                          tree->assign.dst);
+               }
+             else if (tree->type.node_class == etree_provide
+                      && h->type != bfd_link_hash_undefined
+                      && h->type != bfd_link_hash_common)
+               {
+                 /* Do nothing.  The symbol was defined by some
+                    object.  */
+               }
+             else
+               {
+                 /* FIXME: Should we worry if the symbol is already
+                    defined?  */
+                 h->type = bfd_link_hash_defined;
+                 h->u.def.value = result.value;
+                 h->u.def.section = result.section->bfd_section;
+               }
+           }
+       }
+      break;
 
 
-         }
-
-  
-         break;
-       case etree_name:
-         result = fold_name(tree, current_section, allocation_done, dot);
-         break;
-       default:
-         info("%F%S Need more of these %d",tree->type.node_class );
+    case etree_name:
+      result = fold_name (tree, current_section, allocation_done, dot);
+      break;
 
 
-       }
-  }
+    default:
+      FAIL ();
+      break;
+    }
 
   return result;
 }
 
 
   return result;
 }
 
-
-etree_value_type exp_fold_tree_no_dot(tree, current_section, allocation_done)
-etree_type *tree;
-lang_output_section_statement_type *current_section;
-lang_phase_type  allocation_done;
+static etree_value_type 
+exp_fold_tree_no_dot (tree, current_section, allocation_done)
+     etree_type *tree;
+     lang_output_section_statement_type *current_section;
+     lang_phase_type allocation_done;
 {
 return exp_fold_tree(tree, current_section, allocation_done, (bfd_vma)
                     0, (bfd_vma *)NULL);
 }
 
 etree_type *
 {
 return exp_fold_tree(tree, current_section, allocation_done, (bfd_vma)
                     0, (bfd_vma *)NULL);
 }
 
 etree_type *
-exp_binop(code, lhs, rhs)
-int code;
-etree_type *lhs;
-etree_type *rhs;
+exp_binop (code, lhs, rhs)
+     int code;
+     etree_type *lhs;
+     etree_type *rhs;
 {
   etree_type value, *new;
   etree_value_type r;
 {
   etree_type value, *new;
   etree_value_type r;
@@ -578,23 +708,24 @@ etree_type *rhs;
   value.binary.lhs = lhs;
   value.binary.rhs = rhs;
   value.type.node_class = etree_binary;
   value.binary.lhs = lhs;
   value.binary.rhs = rhs;
   value.type.node_class = etree_binary;
-  r = exp_fold_tree_no_dot(&value,  (lang_output_section_statement_type *)NULL,
+  r = exp_fold_tree_no_dot(&value,
+                          abs_output_section,
                           lang_first_phase_enum );
                           lang_first_phase_enum );
-  if (r.valid)
+  if (r.valid_p)
     {
       return exp_intop(r.value);
     }
     {
       return exp_intop(r.value);
     }
-  new = (etree_type *)ldmalloc(sizeof(new->binary));
+  new = (etree_type *) stat_alloc (sizeof (new->binary));
   memcpy((char *)new, (char *)&value, sizeof(new->binary));
   return new;
 }
 
 etree_type *
   memcpy((char *)new, (char *)&value, sizeof(new->binary));
   return new;
 }
 
 etree_type *
-exp_trinop(code, cond, lhs, rhs)
-int code;
-etree_type *cond;
-etree_type *lhs;
-etree_type *rhs;
+exp_trinop (code, cond, lhs, rhs)
+     int code;
+     etree_type *cond;
+     etree_type *lhs;
+     etree_type *rhs;
 {
   etree_type value, *new;
   etree_value_type r;
 {
   etree_type value, *new;
   etree_value_type r;
@@ -605,19 +736,19 @@ etree_type *rhs;
   value.type.node_class = etree_trinary;
   r= exp_fold_tree_no_dot(&value,  (lang_output_section_statement_type
                                    *)NULL,lang_first_phase_enum);
   value.type.node_class = etree_trinary;
   r= exp_fold_tree_no_dot(&value,  (lang_output_section_statement_type
                                    *)NULL,lang_first_phase_enum);
-  if (r.valid) {
+  if (r.valid_p) {
     return exp_intop(r.value);
   }
     return exp_intop(r.value);
   }
-  new = (etree_type *)ldmalloc(sizeof(new->trinary));
+  new = (etree_type *) stat_alloc (sizeof (new->trinary));
   memcpy((char *)new,(char *) &value, sizeof(new->trinary));
   return new;
 }
 
 
 etree_type *
   memcpy((char *)new,(char *) &value, sizeof(new->trinary));
   return new;
 }
 
 
 etree_type *
-exp_unop(code, child)
-int code;
-etree_type *child;
+exp_unop (code, child)
+     int code;
+     etree_type *child;
 {
   etree_type value, *new;
 
 {
   etree_type value, *new;
 
@@ -625,37 +756,36 @@ etree_type *child;
   value.unary.type.node_code = code;
   value.unary.child = child;
   value.unary.type.node_class = etree_unary;
   value.unary.type.node_code = code;
   value.unary.child = child;
   value.unary.type.node_class = etree_unary;
-r = exp_fold_tree_no_dot(&value,(lang_output_section_statement_type *)NULL,
-             lang_first_phase_enum);
-if (r.valid) {
+  r = exp_fold_tree_no_dot(&value,abs_output_section,
+                          lang_first_phase_enum);
+  if (r.valid_p) {
     return exp_intop(r.value);
   }
     return exp_intop(r.value);
   }
-  new = (etree_type *)ldmalloc(sizeof(new->unary));
+  new = (etree_type *) stat_alloc (sizeof (new->unary));
   memcpy((char *)new, (char *)&value, sizeof(new->unary));
   return new;
 }
 
 
 etree_type *
   memcpy((char *)new, (char *)&value, sizeof(new->unary));
   return new;
 }
 
 
 etree_type *
-exp_nameop(code, name)
-int code;
-char *name;
+exp_nameop (code, name)
+     int code;
+     CONST char *name;
 {
 {
-
   etree_type value, *new;
   etree_type value, *new;
-
   etree_value_type r;
   value.name.type.node_code = code;
   value.name.name = name;
   value.name.type.node_class = etree_name;
 
 
   etree_value_type r;
   value.name.type.node_code = code;
   value.name.name = name;
   value.name.type.node_class = etree_name;
 
 
-  r = exp_fold_tree_no_dot(&value,(lang_output_section_statement_type *)NULL,
-               lang_first_phase_enum);
-  if (r.valid) {
+  r = exp_fold_tree_no_dot(&value,
+                          (lang_output_section_statement_type *)NULL,
+                          lang_first_phase_enum);
+  if (r.valid_p) {
     return exp_intop(r.value);
   }
     return exp_intop(r.value);
   }
-  new = (etree_type *)ldmalloc(sizeof(new->name));
+  new = (etree_type *) stat_alloc (sizeof (new->name));
   memcpy((char *)new, (char *)&value, sizeof(new->name));
   return new;
 
   memcpy((char *)new, (char *)&value, sizeof(new->name));
   return new;
 
@@ -665,10 +795,10 @@ char *name;
 
 
 etree_type *
 
 
 etree_type *
-exp_assop(code, dst, src)
-int code;
-char *dst;
-etree_type *src;
+exp_assop (code, dst, src)
+     int code;
+     CONST char *dst;
+     etree_type *src;
 {
   etree_type value, *new;
 
 {
   etree_type value, *new;
 
@@ -684,62 +814,119 @@ etree_type *src;
     return exp_intop(result);
   }
 #endif
     return exp_intop(result);
   }
 #endif
-  new = (etree_type*)ldmalloc(sizeof(new->assign));
+  new = (etree_type*) stat_alloc (sizeof (new->assign));
   memcpy((char *)new, (char *)&value, sizeof(new->assign));
   return new;
 }
 
   memcpy((char *)new, (char *)&value, sizeof(new->assign));
   return new;
 }
 
+/* Handle PROVIDE.  */
+
+etree_type *
+exp_provide (dst, src)
+     const char *dst;
+     etree_type *src;
+{
+  etree_type *n;
+
+  n = (etree_type *) stat_alloc (sizeof (n->assign));
+  n->assign.type.node_code = '=';
+  n->assign.type.node_class = etree_provide;
+  n->assign.src = src;
+  n->assign.dst = dst;
+  return n;
+}
+
+/* Handle ASSERT.  */
+
+etree_type *
+exp_assert (exp, message)
+     etree_type *exp;
+     const char *message;
+{
+  etree_type *n;
+
+  n = (etree_type *) stat_alloc (sizeof (n->assert_s));
+  n->assert_s.type.node_code = '!';
+  n->assert_s.type.node_class = etree_assert;
+  n->assert_s.child = exp;
+  n->assert_s.message = message;
+  return n;
+}
+
 void 
 void 
-exp_print_tree(outfile, tree)
-FILE *outfile;
-etree_type *tree;
+exp_print_tree (tree)
+     etree_type *tree;
 {
   switch (tree->type.node_class) {
   case etree_value:
 {
   switch (tree->type.node_class) {
   case etree_value:
-    fprintf(outfile,"0x%08lx",(bfd_vma)(tree->value.value));
+    minfo ("0x%v", tree->value.value);
+    return;
+  case etree_rel:
+    if (tree->rel.section->owner != NULL)
+      minfo ("%B:", tree->rel.section->owner);
+    minfo ("%s+0x%v", tree->rel.section->name, tree->rel.value);
     return;
   case etree_assign:
 #if 0
     if (tree->assign.dst->sdefs != (asymbol *)NULL){
     return;
   case etree_assign:
 #if 0
     if (tree->assign.dst->sdefs != (asymbol *)NULL){
-      fprintf(outfile,"%s (%x) ",tree->assign.dst->name,
+      fprintf(config.map_file,"%s (%x) ",tree->assign.dst->name,
              tree->assign.dst->sdefs->value);
     }
     else {
              tree->assign.dst->sdefs->value);
     }
     else {
-      fprintf(outfile,"%s (UNDEFINED)",tree->assign.dst->name);
+      fprintf(config.map_file,"%s (UNDEFINED)",tree->assign.dst->name);
     }
 #endif
     }
 #endif
-    fprintf(outfile,"%s ",tree->assign.dst);
-    exp_print_token(outfile,tree->type.node_code);
-    exp_print_tree(outfile,tree->assign.src);
+    fprintf(config.map_file,"%s",tree->assign.dst);
+    exp_print_token(tree->type.node_code);
+    exp_print_tree(tree->assign.src);
+    break;
+  case etree_provide:
+    fprintf (config.map_file, "PROVIDE (%s, ", tree->assign.dst);
+    exp_print_tree (tree->assign.src);
+    fprintf (config.map_file, ")");
     break;
   case etree_binary:
     break;
   case etree_binary:
-    exp_print_tree(outfile,tree->binary.lhs);
-    exp_print_token(outfile,tree->type.node_code);
-    exp_print_tree(outfile,tree->binary.rhs);
+    fprintf(config.map_file,"(");
+    exp_print_tree(tree->binary.lhs);
+    exp_print_token(tree->type.node_code);
+    exp_print_tree(tree->binary.rhs);
+    fprintf(config.map_file,")");
     break;
   case etree_trinary:
     break;
   case etree_trinary:
-    exp_print_tree(outfile,tree->trinary.cond);
-    fprintf(outfile,"?");
-    exp_print_tree(outfile,tree->trinary.lhs);
-    fprintf(outfile,":");
-    exp_print_tree(outfile,tree->trinary.rhs);
+    exp_print_tree(tree->trinary.cond);
+    fprintf(config.map_file,"?");
+    exp_print_tree(tree->trinary.lhs);
+    fprintf(config.map_file,":");
+    exp_print_tree(tree->trinary.rhs);
     break;
   case etree_unary:
     break;
   case etree_unary:
-    exp_print_token(outfile,tree->unary.type.node_code);
-    fprintf(outfile,"(");
-    exp_print_tree(outfile,tree->unary.child);
-    fprintf(outfile,")");
+    exp_print_token(tree->unary.type.node_code);
+    if (tree->unary.child) 
+    {
+    fprintf(config.map_file,"(");
+    exp_print_tree(tree->unary.child);
+    fprintf(config.map_file,")");
+  }
+    
+    break;
+
+  case etree_assert:
+    fprintf (config.map_file, "ASSERT (");
+    exp_print_tree (tree->assert_s.child);
+    fprintf (config.map_file, ", %s)", tree->assert_s.message);
     break;
     break;
+
   case etree_undef:
   case etree_undef:
-    fprintf(outfile,"????????");
+    fprintf(config.map_file,"????????");
     break;
   case etree_name:
     if (tree->type.node_code == NAME) {
     break;
   case etree_name:
     if (tree->type.node_code == NAME) {
-      fprintf(outfile,"%s", tree->name.name);
+      fprintf(config.map_file,"%s", tree->name.name);
     }
     else {
     }
     else {
-      exp_print_token(outfile,tree->type.node_code);
-      fprintf(outfile,"(%s)", tree->name.name);
+      exp_print_token(tree->type.node_code);
+      if (tree->name.name)
+      fprintf(config.map_file,"(%s)", tree->name.name);
     }
     break;
   default:
     }
     break;
   default:
@@ -748,39 +935,53 @@ etree_type *tree;
   }
 }
 
   }
 }
 
-
-
-
 bfd_vma
 bfd_vma
-exp_get_vma(tree, def, name, allocation_done)
-etree_type *tree;
-bfd_vma def;
-char *name;
-lang_phase_type allocation_done;
+exp_get_vma (tree, def, name, allocation_done)
+     etree_type *tree;
+     bfd_vma def;
+     char *name;
+     lang_phase_type allocation_done;
 {
   etree_value_type r;
 
 {
   etree_value_type r;
 
-  if (tree != (etree_type *)NULL) {
-    r = exp_fold_tree_no_dot(tree,
-                     (lang_output_section_statement_type *)NULL,
-                     allocation_done);
-    if (r.valid == false && name) {
-      info("%F%S Nonconstant expression for %s\n",name);
+  if (tree != NULL)
+    {
+      r = exp_fold_tree_no_dot (tree, abs_output_section, allocation_done);
+      if (! r.valid_p && name != NULL)
+       einfo (_("%F%S nonconstant expression for %s\n"), name);
+      return r.value;
     }
     }
-    return r.value;
-  }
-  else {
+  else
     return def;
     return def;
-  }
 }
 
 int 
 }
 
 int 
-exp_get_value_int(tree,def,name, allocation_done)
-etree_type *tree;
-int def;
-char *name;
-lang_phase_type allocation_done;
+exp_get_value_int (tree,def,name, allocation_done)
+     etree_type *tree;
+     int def;
+     char *name;
+     lang_phase_type allocation_done;
 {
   return (int)exp_get_vma(tree,(bfd_vma)def,name, allocation_done);
 }
 
 {
   return (int)exp_get_vma(tree,(bfd_vma)def,name, allocation_done);
 }
 
+
+bfd_vma
+exp_get_abs_int (tree, def, name, allocation_done)
+     etree_type *tree;
+     int def ATTRIBUTE_UNUSED;
+     char *name;
+     lang_phase_type allocation_done;
+{
+  etree_value_type res;
+  res = exp_fold_tree_no_dot (tree, abs_output_section, allocation_done);
+
+  if (res.valid_p)
+    {
+      res.value += res.section->bfd_section->vma;
+    }
+  else {
+    einfo (_("%F%S non constant expression for %s\n"),name);
+  }
+  return res.value;
+}
This page took 0.039674 seconds and 4 git commands to generate.