* lexsup.c (parse_args): Add support for new options -( -) with
[binutils-gdb.git] / ld / ldlang.c
index e1f3f2f541915e69d7a9d5d71ee6c3d716563357..6a4ab5fffb976309b32a744013c4d8b9af1c769a 100644 (file)
@@ -1,4 +1,5 @@
-/* Copyright (C) 1991 Free Software Foundation, Inc.
+/* Linker command language support.
+   Copyright (C) 1991, 92, 93, 94 Free Software Foundation, Inc.
 
 This file is part of GLD, the Gnu Linker.
 
@@ -16,45 +17,38 @@ 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.  */
 
-/* $Id$
- *
-*/
-
 #include "bfd.h"
 #include "sysdep.h"
+#include "libiberty.h"
+#include "bfdlink.h"
 
 #include "ld.h"
 #include "ldmain.h"
-#include "ldsym.h"
 #include "ldgram.h"
-#include "ldwarn.h"
-#include "ldlang.h"
 #include "ldexp.h"
+#include "ldlang.h"
 #include "ldemul.h"
 #include "ldlex.h"
 #include "ldmisc.h"
-#include "ldindr.h"
 #include "ldctor.h"
+#include "ldfile.h"
+
 /* FORWARDS */
-PROTO (static void, print_statements, (void));
-PROTO (static void, print_statement, (lang_statement_union_type *,
+static void print_statements PARAMS ((void));
+static void print_statement PARAMS ((lang_statement_union_type *,
                                      lang_output_section_statement_type *));
+static lang_statement_union_type *new_statement PARAMS ((enum statement_enum,
+                                                        size_t,
+                                                        lang_statement_list_type*));
+
 
 /* LOCALS */
 static struct obstack stat_obstack;
 
-#define obstack_chunk_alloc ldmalloc
+#define obstack_chunk_alloc xmalloc
 #define obstack_chunk_free free
 static CONST char *startup_file;
 static lang_statement_list_type input_file_chain;
-
-/* Points to the last statement in the .data section, so we can add
-   stuff to the data section without pain */
-static lang_statement_list_type end_of_data_section_statement_list;
-
-/* List of statements needed to handle constructors */
-extern lang_statement_list_type constructor_list;
-
 static boolean placed_commons = false;
 static lang_output_section_statement_type *default_common_section;
 static boolean map_option_f;
@@ -63,43 +57,96 @@ static lang_input_statement_type *first_file;
 static lang_statement_list_type lang_output_section_statement;
 static CONST char *current_target;
 static CONST char *output_target;
-static size_t longest_section_name = 8;
-static asection common_section;
-static section_userdata_type common_section_userdata;
+static int longest_section_name = 8;
 static lang_statement_list_type statement_list;
 
+static void print_size PARAMS ((size_t value));
+static void print_alignment PARAMS ((unsigned int value));
+static void print_fill PARAMS ((fill_type value));
+static void print_section PARAMS ((const char *name));
+static void lang_for_each_statement_worker
+  PARAMS ((void (*func) (lang_statement_union_type *),
+          lang_statement_union_type *s));
+static lang_input_statement_type *new_afile
+  PARAMS ((const char *name, lang_input_file_enum_type file_type,
+          const char *target, boolean add_to_list));
+static void print_flags PARAMS ((int *ignore_flags));
+static void init_os PARAMS ((lang_output_section_statement_type *s));
+static void wild_doit PARAMS ((lang_statement_list_type *ptr,
+                              asection *section,
+                              lang_output_section_statement_type *output,
+                              lang_input_statement_type *file));
+static void wild_section PARAMS ((lang_wild_statement_type *ptr,
+                                 const char *section,
+                                 lang_input_statement_type *file,
+                                 lang_output_section_statement_type *output));
+static lang_input_statement_type *lookup_name PARAMS ((const char *name));
+static void load_symbols PARAMS ((lang_input_statement_type *entry));
+static void wild PARAMS ((lang_wild_statement_type *s,
+                         const char *section, const char *file,
+                         const char *target,
+                         lang_output_section_statement_type *output));
+static bfd *open_output PARAMS ((const char *name));
+static void ldlang_open_output PARAMS ((lang_statement_union_type *statement));
+static void open_input_bfds PARAMS ((lang_statement_union_type *statement));
+static void lang_reasonable_defaults PARAMS ((void));
+static void lang_place_undefineds PARAMS ((void));
+static void map_input_to_output_sections
+  PARAMS ((lang_statement_union_type *s,
+          const char *target,
+          lang_output_section_statement_type *output_section_statement));
+static void print_output_section_statement
+  PARAMS ((lang_output_section_statement_type *output_section_statement));
+static void print_assignment
+  PARAMS ((lang_assignment_statement_type *assignment,
+          lang_output_section_statement_type *output_section));
+static void print_input_statement PARAMS ((lang_input_statement_type *statm));
+static void print_input_section PARAMS ((lang_input_section_type *in));
+static void print_fill_statement PARAMS ((lang_fill_statement_type *fill));
+static void print_data_statement PARAMS ((lang_data_statement_type *data));
+static void print_reloc_statement PARAMS ((lang_reloc_statement_type *reloc));
+static void print_padding_statement PARAMS ((lang_padding_statement_type *s));
+static void print_wild_statement
+  PARAMS ((lang_wild_statement_type *w,
+          lang_output_section_statement_type *os));
+static void print_statement PARAMS ((lang_statement_union_type *s,
+                                    lang_output_section_statement_type *os));
+static void print_statements PARAMS ((void));
+static bfd_vma insert_pad PARAMS ((lang_statement_union_type **this_ptr,
+                                  fill_type fill, unsigned int power,
+                                  asection *output_section_statement,
+                                  bfd_vma dot));
+static bfd_vma size_input_section
+  PARAMS ((lang_statement_union_type **this_ptr,
+          lang_output_section_statement_type *output_section_statement,
+          fill_type fill, bfd_vma dot, boolean relax));
+static bfd_vma lang_do_assignments
+  PARAMS ((lang_statement_union_type * s,
+          lang_output_section_statement_type *output_section_statement,
+          fill_type fill,
+          bfd_vma dot));
+static void lang_finish PARAMS ((void));
+static void lang_check PARAMS ((void));
+static void lang_common PARAMS ((void));
+static boolean lang_one_common PARAMS ((struct bfd_link_hash_entry *, PTR));
+static void lang_place_orphans PARAMS ((void));
+static int topower PARAMS ((int));
+static void reset_memory_regions PARAMS ((void));
+
 /* EXPORTS */
-boolean relaxing;
 lang_output_section_statement_type *abs_output_section;
 lang_statement_list_type *stat_ptr = &statement_list;
-lang_input_statement_type *script_file = 0;
-boolean option_longmap = false;
-lang_statement_list_type file_chain =
-{0};
-CONST char *entry_symbol = 0;
-bfd_size_type largest_section = 0;
+lang_statement_list_type file_chain = { 0 };
+static const char *entry_symbol = 0;
 boolean lang_has_input_file = false;
-lang_output_section_statement_type *create_object_symbols = 0;
 boolean had_output_filename = false;
 boolean lang_float_flag = false;
+boolean delete_output_file_on_failure = false;
+
+etree_type *base; /* Relocation base - or null */
 
-/* IMPORTS */
-extern char *default_target;
-
-extern unsigned int undefined_global_sym_count;
-extern char *current_file;
-extern bfd *output_bfd;
-extern enum bfd_architecture ldfile_output_architecture;
-extern unsigned long ldfile_output_machine;
-extern char *ldfile_output_machine_name;
-extern ldsym_type *symbol_head;
-extern unsigned int commons_pending;
-extern args_type command_line;
-extern ld_config_type config;
-extern boolean had_script;
-extern boolean write_map;
-
-#ifdef __STDC__
+
+#if defined(__STDC__) || defined(ALMOST_STDC)
 #define cat(a,b) a##b
 #else
 #define cat(a,b) a/**/b
@@ -111,37 +158,37 @@ extern boolean write_map;
 
 #define outside_symbol_address(q) ((q)->value +   outside_section_address(q->section))
 
-void EXFUN (lang_add_data, (int type, union etree_union * exp));
-
 PTR
-DEFUN (stat_alloc, (size),
-       size_t size)
+stat_alloc (size)
+     size_t size;
 {
   return obstack_alloc (&stat_obstack, size);
 }
+
 static void
-DEFUN (print_size, (value),
-       size_t value)
+print_size (value)
+     size_t value;
 {
   fprintf (config.map_file, "%5x", (unsigned) value);
 }
+
 static void
-DEFUN (print_alignment, (value),
-       unsigned int value)
+print_alignment (value)
+     unsigned int value;
 {
   fprintf (config.map_file, "2**%1u", value);
 }
+
 static void
-DEFUN (print_fill, (value),
-       fill_type value)
+print_fill (value)
+     fill_type value;
 {
   fprintf (config.map_file, "%04x", (unsigned) value);
 }
 
-
 static void
-DEFUN (print_section, (name),
-       CONST char *CONST name)
+print_section (name)
+     CONST char *name;
 {
   fprintf (config.map_file, "%*s", -longest_section_name, name);
 }
@@ -152,9 +199,9 @@ DEFUN (print_section, (name),
 */
 
 static void
-DEFUN (lang_for_each_statement_worker, (func, s),
-       void (*func) ()AND
-       lang_statement_union_type * s)
+lang_for_each_statement_worker (func, s)
+     void (*func) PARAMS ((lang_statement_union_type *));
+     lang_statement_union_type *s;
 {
   for (; s != (lang_statement_union_type *) NULL; s = s->next)
     {
@@ -176,6 +223,7 @@ DEFUN (lang_for_each_statement_worker, (func, s),
             s->wild_statement.children.head);
          break;
        case lang_data_statement_enum:
+       case lang_reloc_statement_enum:
        case lang_object_symbols_statement_enum:
        case lang_output_statement_enum:
        case lang_target_statement_enum:
@@ -193,8 +241,8 @@ DEFUN (lang_for_each_statement_worker, (func, s),
 }
 
 void
-DEFUN (lang_for_each_statement, (func),
-       void (*func) ())
+lang_for_each_statement (func)
+     void (*func) PARAMS ((lang_statement_union_type *));
 {
   lang_for_each_statement_worker (func,
                                  statement_list.head);
@@ -202,8 +250,8 @@ DEFUN (lang_for_each_statement, (func),
 
 /*----------------------------------------------------------------------*/
 void
-DEFUN (lang_list_init, (list),
-       lang_statement_list_type * list)
+lang_list_init (list)
+     lang_statement_list_type *list;
 {
   list->head = (lang_statement_union_type *) NULL;
   list->tail = &list->head;
@@ -217,10 +265,10 @@ DEFUN (lang_list_init, (list),
 
 static
 lang_statement_union_type *
-DEFUN (new_statement, (type, size, list),
-       enum statement_enum type AND
-       bfd_size_type size AND
-       lang_statement_list_type * list)
+new_statement (type, size, list)
+     enum statement_enum type;
+     size_t size;
+     lang_statement_list_type * list;
 {
   lang_statement_union_type *new = (lang_statement_union_type *)
   stat_alloc (size);
@@ -243,14 +291,22 @@ DEFUN (new_statement, (type, size, list),
 
  */
 static lang_input_statement_type *
-DEFUN (new_afile, (name, file_type, target),
-       CONST char *CONST name AND
-       CONST lang_input_file_enum_type file_type AND
-       CONST char *CONST target)
+new_afile (name, file_type, target, add_to_list)
+     CONST char *name;
+     lang_input_file_enum_type file_type;
+     CONST char *target;
+     boolean add_to_list;
 {
+  lang_input_statement_type *p;
 
-  lang_input_statement_type *p = new_stat (lang_input_statement,
-                                          stat_ptr);
+  if (add_to_list)
+    p = new_stat (lang_input_statement, stat_ptr);
+  else
+    {
+      p = ((lang_input_statement_type *)
+          stat_alloc (sizeof (lang_input_statement_type)));
+      p->header.next = NULL;
+    }
 
   lang_has_input_file = true;
   p->target = target;
@@ -277,12 +333,19 @@ DEFUN (new_afile, (name, file_type, target),
       p->is_archive = true;
       p->filename = name;
       p->real = true;
-      p->local_sym_name = concat ("-l", name, "");
+      p->local_sym_name = concat ("-l", name, (const char *) NULL);
       p->just_syms_flag = false;
       p->search_dirs_flag = true;
       break;
-    case lang_input_file_is_search_file_enum:
     case lang_input_file_is_marker_enum:
+      p->filename = name;
+      p->is_archive = false;
+      p->real = false;
+      p->local_sym_name = name;
+      p->just_syms_flag = false;
+      p->search_dirs_flag = true;
+      break;
+    case lang_input_file_is_search_file_enum:
       p->filename = name;
       p->is_archive = false;
       p->real = true;
@@ -301,12 +364,13 @@ DEFUN (new_afile, (name, file_type, target),
     default:
       FAIL ();
     }
+  p->the_bfd = (bfd *) NULL;
   p->asymbols = (asymbol **) NULL;
-  p->superfile = (lang_input_statement_type *) NULL;
   p->next_real_file = (lang_statement_union_type *) NULL;
   p->next = (lang_statement_union_type *) NULL;
   p->symbol_count = 0;
   p->common_output_section = (asection *) NULL;
+  p->loaded = false;
   lang_statement_append (&input_file_chain,
                         (lang_statement_union_type *) p,
                         &p->next_real_file);
@@ -314,35 +378,18 @@ DEFUN (new_afile, (name, file_type, target),
 }
 
 lang_input_statement_type *
-DEFUN (lang_add_input_file, (name, file_type, target),
-       CONST char *name AND
-       lang_input_file_enum_type file_type AND
-       CONST char *target)
+lang_add_input_file (name, file_type, target)
+     CONST char *name;
+     lang_input_file_enum_type file_type;
+     CONST char *target;
 {
-  /* Look it up or build a new one */
   lang_has_input_file = true;
-#if 0
-  lang_input_statement_type *p;
-
-  for (p = (lang_input_statement_type *) input_file_chain.head;
-       p != (lang_input_statement_type *) NULL;
-       p = (lang_input_statement_type *) (p->next_real_file))
-    {
-      /* Sometimes we have incomplete entries in here */
-      if (p->filename != (char *) NULL)
-       {
-         if (strcmp (name, p->filename) == 0)
-           return p;
-       }
-
-    }
-#endif
-  return new_afile (name, file_type, target);
+  return new_afile (name, file_type, target, true);
 }
 
 /* Build enough state so that the parser can build its tree */
 void
-DEFUN_VOID (lang_init)
+lang_init ()
 {
   obstack_begin (&stat_obstack, 1000);
 
@@ -358,7 +405,7 @@ DEFUN_VOID (lang_init)
                                    (char *) NULL);
   abs_output_section = lang_output_section_statement_lookup (BFD_ABS_SECTION_NAME);
 
-  abs_output_section->bfd_section = &bfd_abs_section;
+  abs_output_section->bfd_section = bfd_abs_section_ptr;
 
 }
 
@@ -377,8 +424,8 @@ static lang_memory_region_type *lang_memory_region_list;
 static lang_memory_region_type **lang_memory_region_list_tail = &lang_memory_region_list;
 
 lang_memory_region_type *
-DEFUN (lang_memory_region_lookup, (name),
-       CONST char *CONST name)
+lang_memory_region_lookup (name)
+     CONST char *CONST name;
 {
 
   lang_memory_region_type *p = lang_memory_region_list;
@@ -410,7 +457,7 @@ DEFUN (lang_memory_region_lookup, (name),
     *lang_memory_region_list_tail = new;
     lang_memory_region_list_tail = &new->next;
     new->origin = 0;
-    new->length = ~0;
+    new->length = ~(bfd_size_type)0;
     new->current = 0;
     new->had_full_message = false;
 
@@ -420,8 +467,8 @@ DEFUN (lang_memory_region_lookup, (name),
 
 
 lang_output_section_statement_type *
-DEFUN (lang_output_section_find, (name),
-       CONST char *CONST name)
+lang_output_section_find (name)
+     CONST char *CONST name;
 {
   lang_statement_union_type *u;
   lang_output_section_statement_type *lookup;
@@ -440,8 +487,8 @@ DEFUN (lang_output_section_find, (name),
 }
 
 lang_output_section_statement_type *
-DEFUN (lang_output_section_statement_lookup, (name),
-       CONST char *CONST name)
+lang_output_section_statement_lookup (name)
+     CONST char *CONST name;
 {
   lang_output_section_statement_type *lookup;
 
@@ -459,9 +506,16 @@ DEFUN (lang_output_section_statement_lookup, (name),
       lookup->next = (lang_statement_union_type *) NULL;
       lookup->bfd_section = (asection *) NULL;
       lookup->processed = false;
+      lookup->loadable = 1;
       lookup->addr_tree = (etree_type *) NULL;
       lang_list_init (&lookup->children);
 
+      lookup->memspec = (CONST char *) NULL;
+      lookup->flags = 0;
+      lookup->subsection_alignment = -1;
+      lookup->section_alignment = -1;
+      lookup->load_base = (union etree_union *) NULL;
+
       lang_statement_append (&lang_output_section_statement,
                             (lang_statement_union_type *) lookup,
                             &lookup->next);
@@ -471,8 +525,8 @@ DEFUN (lang_output_section_statement_lookup, (name),
 
 /*ARGSUSED*/
 static void
-DEFUN (print_flags, (ignore_flags),
-       int *ignore_flags)
+print_flags (ignore_flags)
+     int *ignore_flags;
 {
   fprintf (config.map_file, "(");
 #if 0
@@ -485,11 +539,11 @@ DEFUN (print_flags, (ignore_flags),
   if (flags->flag_loadable)
     fprintf (outfile, "L");
 #endif
 fprintf (config.map_file, ")");
+ fprintf (config.map_file, ")");
 }
 
 void
-DEFUN_VOID (lang_map)
+lang_map ()
 {
   lang_memory_region_type *m;
 
@@ -497,7 +551,9 @@ DEFUN_VOID (lang_map)
 #ifdef HOST_64_BIT
   fprintf (config.map_file, "name\t\torigin\t\tlength\t\tattributes\n");
 #else
-  fprintf (config.map_file, "name\t\torigin   length\t\tattributes\n");
+  fprintf (config.map_file,
+          "name\t\torigin   length   r_size   c_size    is    attributes\n");
+
 #endif
   for (m = lang_memory_region_list;
        m != (lang_memory_region_type *) NULL;
@@ -506,8 +562,15 @@ DEFUN_VOID (lang_map)
       fprintf (config.map_file, "%-16s", m->name);
       print_address (m->origin);
       print_space ();
-      print_address (m->length);
+      print_address ((bfd_vma)m->length);
       print_space ();
+      print_address ((bfd_vma)m->old_length);
+      print_space();
+      print_address (m->current - m->origin);
+      print_space();
+      if (m->old_length)
+       fprintf (config.map_file, " %2d%%  ",
+               (int) ((m->current - m->origin) * 100 / m->old_length));
       print_flags (&m->flags);
       fprintf (config.map_file, "\n");
     }
@@ -523,8 +586,8 @@ DEFUN_VOID (lang_map)
  *
  */
 static void
-DEFUN (init_os, (s),
-       lang_output_section_statement_type * s)
+init_os (s)
+     lang_output_section_statement_type * s;
 {
 /*  asection *section = bfd_get_section_by_name(output_bfd, s->name);*/
   section_userdata_type *new =
@@ -536,11 +599,11 @@ DEFUN (init_os, (s),
     s->bfd_section = bfd_make_section (output_bfd, s->name);
   if (s->bfd_section == (asection *) NULL)
     {
-      einfo ("%P%F output format %s cannot represent section called %s\n",
+      einfo ("%P%F: output format %s cannot represent section called %s\n",
             output_bfd->xvec->name, s->name);
     }
   s->bfd_section->output_section = s->bfd_section;
-  /* s->bfd_section->flags = s->flags;*/
+/*  s->bfd_section->flags = s->flags;*/
 
   /* We initialize an output sections output offset to minus its own */
   /* vma to allow us to output a section through itself */
@@ -564,48 +627,58 @@ DEFUN (init_os, (s),
 */
 
 static void
-DEFUN (wild_doit, (ptr, section, output, file),
-       lang_statement_list_type * ptr AND
-       asection * section AND
-       lang_output_section_statement_type * output AND
-       lang_input_statement_type * file)
+wild_doit (ptr, section, output, file)
+     lang_statement_list_type * ptr;
+     asection * section;
+     lang_output_section_statement_type * output;
+     lang_input_statement_type * file;
 {
   if (output->bfd_section == (asection *) NULL)
-    {
-      init_os (output);
-    }
+    init_os (output);
 
   if (section != (asection *) NULL
       && section->output_section == (asection *) NULL)
+  {
+    /* Add a section reference to the list */
+    lang_input_section_type *new = new_stat (lang_input_section, ptr);
+
+    new->section = section;
+    new->ifile = file;
+    section->output_section = output->bfd_section;
+
+    /* We don't copy the SEC_NEVER_LOAD flag from an input section to
+       an output section, because we want to be able to include a
+       SEC_NEVER_LOAD section in the middle of an otherwise loaded
+       section (I don't know why we want to do this, but we do).
+       build_link_order in ldwrite.c handles this case by turning the
+       embedded SEC_NEVER_LOAD section into a fill.  */
+    section->output_section->flags |=
+      section->flags & (flagword) (~ SEC_NEVER_LOAD);
+
+    if (!output->loadable) 
     {
-      /* Add a section reference to the list */
-      lang_input_section_type *new = new_stat (lang_input_section, ptr);
-
-      new->section = section;
-      new->ifile = file;
-      section->output_section = output->bfd_section;
-      section->output_section->flags |= section->flags;
-      if (section->alignment_power > output->bfd_section->alignment_power)
-       {
-         output->bfd_section->alignment_power = section->alignment_power;
-       }
+      /* Turn off load flag */
+      output->bfd_section->flags &= ~SEC_LOAD;
+      output->bfd_section->flags |= SEC_NEVER_LOAD;
     }
-}
-
-static asection *
-DEFUN (our_bfd_get_section_by_name, (abfd, section),
-       bfd * abfd AND
-       CONST char *section)
-{
-  return bfd_get_section_by_name (abfd, section);
+    if (section->alignment_power > output->bfd_section->alignment_power)
+    {
+      output->bfd_section->alignment_power = section->alignment_power;
+    }
+    /* If supplied an aligmnet, then force it */
+    if (output->section_alignment != -1)
+    {
+      output->bfd_section->alignment_power = output->section_alignment;
+    }
+  }
 }
 
 static void
-DEFUN (wild_section, (ptr, section, file, output),
-       lang_wild_statement_type * ptr AND
-       CONST char *section AND
-       lang_input_statement_type * file AND
-       lang_output_section_statement_type * output)
+wild_section (ptr, section, file, output)
+     lang_wild_statement_type * ptr;
+     CONST char *section;
+     lang_input_statement_type * file;
+     lang_output_section_statement_type * output;
 {
   asection *s;
 
@@ -614,17 +687,21 @@ DEFUN (wild_section, (ptr, section, file, output),
       if (section == (char *) NULL)
        {
          /* Do the creation to all sections in the file */
-         for (s = file->the_bfd->sections; s != (asection *) NULL; s = s->next)
+         for (s = file->the_bfd->sections; s != NULL; s = s->next)
            {
-             wild_doit (&ptr->children, s, output, file);
+             /* except for bss */
+             if ((s->flags & SEC_IS_COMMON)  == 0)
+               {
+                 wild_doit (&ptr->children, s, output, file);
+               }
            }
        }
       else
        {
          /* Do the creation to the named section only */
-         wild_doit (&ptr->children,
-                    our_bfd_get_section_by_name (file->the_bfd, section),
-                    output, file);
+         s = bfd_get_section_by_name (file->the_bfd, section);
+         if (s != NULL)
+           wild_doit (&ptr->children, s, output, file);
        }
     }
 }
@@ -637,10 +714,9 @@ DEFUN (wild_section, (ptr, section, file, output),
    not define anything we need at the time, they won't have all their
    symbols read. If we need them later, we'll have to redo it.
    */
-static
-lang_input_statement_type *
-DEFUN (lookup_name, (name),
-       CONST char *CONST name)
+static lang_input_statement_type *
+lookup_name (name)
+     CONST char *name;
 {
   lang_input_statement_type *search;
 
@@ -649,36 +725,69 @@ DEFUN (lookup_name, (name),
        search = (lang_input_statement_type *) search->next_real_file)
     {
       if (search->filename == (char *) NULL && name == (char *) NULL)
-       {
-         return search;
-       }
-      if (search->filename != (char *) NULL && name != (char *) NULL)
-       {
-         if (strcmp (search->filename, name) == 0)
-           {
-             ldmain_open_file_read_symbol (search);
-             return search;
-           }
-       }
+       return search;
+      if (search->filename != (char *) NULL
+         && name != (char *) NULL
+         && strcmp (search->filename, name) == 0)
+       break;
     }
 
-  /* There isn't an afile entry for this file yet, this must be
-     because the name has only appeared inside a load script and not
-     on the command line  */
-  search = new_afile (name, lang_input_file_is_file_enum, default_target);
-  ldmain_open_file_read_symbol (search);
+  if (search == (lang_input_statement_type *) NULL)
+    search = new_afile (name, lang_input_file_is_file_enum, default_target,
+                       false);
+
+  /* If we have already added this file, or this file is not real
+     (FIXME: can that ever actually happen?) or the name is NULL
+     (FIXME: can that ever actually happen?) don't add this file.  */
+  if (search->loaded
+      || ! search->real
+      || search->filename == (const char *) NULL)
+    return search;
+
+  load_symbols (search);
+
   return search;
+}
 
+/* Get the symbols for an input file.  */
 
+static void
+load_symbols (entry)
+     lang_input_statement_type *entry;
+{
+  if (entry->loaded)
+    return;
+
+  ldfile_open_file (entry);
+
+  if (bfd_check_format (entry->the_bfd, bfd_object))
+    {
+      ldlang_add_file (entry);
+      if (trace_files || trace_file_tries)
+       info_msg ("%I\n", entry);
+    }
+  else if (bfd_check_format (entry->the_bfd, bfd_archive))
+    {
+      /* There is nothing to do here; the add_symbols routine will
+        call ldlang_add_file (via the add_archive_element callback)
+        for each element of the archive which is used.  */
+    }
+  else
+    einfo ("%F%B: file not recognized: %E\n", entry->the_bfd);
+
+  if (bfd_link_add_symbols (entry->the_bfd, &link_info) == false)
+    einfo ("%F%B: could not read symbols: %E\n", entry->the_bfd);
+
+  entry->loaded = true;
 }
 
 static void
-DEFUN (wild, (s, section, file, target, output),
-       lang_wild_statement_type * s AND
-       CONST char *CONST section AND
-       CONST char *CONST file AND
-       CONST char *CONST target AND
-       lang_output_section_statement_type * output)
+wild (s, section, file, target, output)
+     lang_wild_statement_type * s;
+     CONST char *section;
+     CONST char *file;
+     CONST char *target;
+     lang_output_section_statement_type * output;
 {
   lang_input_statement_type *f;
 
@@ -710,41 +819,47 @@ DEFUN (wild, (s, section, file, target, output),
 /*
   read in all the files
   */
+
 static bfd *
-DEFUN (open_output, (name),
-       CONST char *CONST name)
+open_output (name)
+     CONST char *name;
 {
-  extern unsigned long ldfile_output_machine;
-  extern enum bfd_architecture ldfile_output_architecture;
-
-  extern CONST char *output_filename;
   bfd *output;
 
   if (output_target == (char *) NULL)
-  {
-    if (current_target != (char *) NULL)
-     output_target = current_target;
-    else
-     output_target = default_target;
-  }
+    {
+      if (current_target != (char *) NULL)
+       output_target = current_target;
+      else
+       output_target = default_target;
+    }
   output = bfd_openw (name, output_target);
-  output_filename = name;
 
   if (output == (bfd *) NULL)
-  {
-    if (bfd_error == invalid_target)
     {
-      einfo ("%P%F target %s not found\n", output_target);
+      if (bfd_get_error () == bfd_error_invalid_target)
+       {
+         einfo ("%P%F: target %s not found\n", output_target);
+       }
+      einfo ("%P%F: cannot open output file %s: %E\n", name);
     }
-    einfo ("%P%F problem opening output file %s, %E", name);
-  }
+
+  delete_output_file_on_failure = 1;
 
   /*  output->flags |= D_PAGED;*/
 
-  bfd_set_format (output, bfd_object);
-  bfd_set_arch_mach(output,
-                   ldfile_output_architecture,
-                   ldfile_output_machine);
+  if (! bfd_set_format (output, bfd_object))
+    einfo ("%P%F:%s: can not make object file: %E\n", name);
+  if (! bfd_set_arch_mach (output,
+                          ldfile_output_architecture,
+                          ldfile_output_machine))
+    einfo ("%P%F:%s: can not set architecture: %E\n", name);
+
+  link_info.hash = bfd_link_hash_table_create (output);
+  if (link_info.hash == (struct bfd_link_hash_table *) NULL)
+    einfo ("%P%F: can not create link hash table: %E\n");
+
+  bfd_set_gp_size (output, g_switch_value);
   return output;
 }
 
@@ -752,15 +867,16 @@ DEFUN (open_output, (name),
 
 
 static void
-DEFUN (ldlang_open_output, (statement),
-       lang_statement_union_type * statement)
+ldlang_open_output (statement)
+     lang_statement_union_type * statement;
 {
   switch (statement->header.type)
     {
-      case lang_output_statement_enum:
+    case lang_output_statement_enum:
+      ASSERT (output_bfd == (bfd *) NULL);
       output_bfd = open_output (statement->output_statement.name);
       ldemul_set_output_arch ();
-      if (config.magic_demand_paged && !config.relocateable_output)
+      if (config.magic_demand_paged && !link_info.relocateable)
        output_bfd->flags |= D_PAGED;
       else
        output_bfd->flags &= ~D_PAGED;
@@ -768,6 +884,10 @@ DEFUN (ldlang_open_output, (statement),
        output_bfd->flags |= WP_TEXT;
       else
        output_bfd->flags &= ~WP_TEXT;
+      if (config.traditional_format)
+       output_bfd->flags |= BFD_TRADITIONAL_FORMAT;
+      else
+       output_bfd->flags &= ~BFD_TRADITIONAL_FORMAT;
       break;
 
     case lang_target_statement_enum:
@@ -779,8 +899,8 @@ DEFUN (ldlang_open_output, (statement),
 }
 
 static void
-DEFUN (open_input_bfds, (statement),
-       lang_statement_union_type * statement)
+open_input_bfds (statement)
+     lang_statement_union_type * statement;
 {
   switch (statement->header.type)
     {
@@ -798,7 +918,7 @@ DEFUN (open_input_bfds, (statement),
       if (statement->input_statement.real == true)
        {
          statement->input_statement.target = current_target;
-         lookup_name (statement->input_statement.filename);
+         load_symbols (&statement->input_statement);
        }
       break;
     default:
@@ -811,9 +931,6 @@ DEFUN (open_input_bfds, (statement),
 static void
 lang_reasonable_defaults ()
 {
-
-
-
 #if 0
   lang_output_section_statement_lookup (".text");
   lang_output_section_statement_lookup (".data");
@@ -849,8 +966,8 @@ typedef struct ldlang_undef_chain_list
 static ldlang_undef_chain_list_type *ldlang_undef_chain_list_head;
 
 void
-DEFUN (ldlang_add_undef, (name),
-       CONST char *CONST name)
+ldlang_add_undef (name)
+     CONST char *CONST name;
 {
   ldlang_undef_chain_list_type *new =
   (ldlang_undef_chain_list_type
@@ -867,66 +984,34 @@ DEFUN (ldlang_add_undef, (name),
    script file.
 */
 static void
-DEFUN_VOID (lang_place_undefineds)
-{
-  ldlang_undef_chain_list_type *ptr = ldlang_undef_chain_list_head;
-
-  while (ptr != (ldlang_undef_chain_list_type *) NULL)
-    {
-      asymbol *def;
-      asymbol **def_ptr = (asymbol **) stat_alloc ((bfd_size_type) (sizeof (asymbol **)));
-
-      def = (asymbol *) bfd_make_empty_symbol (script_file->the_bfd);
-      *def_ptr = def;
-      def->name = ptr->name;
-      def->section = &bfd_und_section;
-      Q_enter_global_ref (def_ptr, ptr->name);
-      ptr = ptr->next;
-    }
-}
-
-/* Copy important data from out internal form to the bfd way. Also
-   create a section for the dummy file
- */
-
-static void
-DEFUN_VOID (lang_create_output_section_statements)
+lang_place_undefineds ()
 {
-  lang_statement_union_type *os;
+  ldlang_undef_chain_list_type *ptr;
 
-  for (os = lang_output_section_statement.head;
-       os != (lang_statement_union_type *) NULL;
-       os = os->output_section_statement.next)
+  for (ptr = ldlang_undef_chain_list_head;
+       ptr != (ldlang_undef_chain_list_type *) NULL;
+       ptr = ptr->next)
     {
-      lang_output_section_statement_type *s =
-      &os->output_section_statement;
+      struct bfd_link_hash_entry *h;
 
-      init_os (s);
+      h = bfd_link_hash_lookup (link_info.hash, ptr->name, true, false, true);
+      if (h == (struct bfd_link_hash_entry *) NULL)
+       einfo ("%P%F: bfd_link_hash_lookup failed: %E");
+      if (h->type == bfd_link_hash_new)
+       {
+         h->type = bfd_link_hash_undefined;
+         h->u.undef.abfd = NULL;
+         bfd_link_add_undef (link_info.hash, h);
+       }
     }
-
-}
-
-static void
-DEFUN_VOID (lang_init_script_file)
-{
-  script_file = lang_add_input_file ("script file",
-                                    lang_input_file_is_fake_enum,
-                                    (char *) NULL);
-  script_file->the_bfd = bfd_create ("script file", output_bfd);
-  script_file->symbol_count = 0;
-  script_file->the_bfd->sections = output_bfd->sections;
-  abs_output_section = lang_output_section_statement_lookup (BFD_ABS_SECTION_NAME);
-
-  abs_output_section->bfd_section = &bfd_abs_section;
-
 }
 
 /* Open input files and attatch to output sections */
 static void
-DEFUN (map_input_to_output_sections, (s, target, output_section_statement),
-       lang_statement_union_type * s AND
-       CONST char *target AND
-       lang_output_section_statement_type * output_section_statement)
+map_input_to_output_sections (s, target, output_section_statement)
+     lang_statement_union_type * s;
+     CONST char *target;
+     lang_output_section_statement_type * output_section_statement;
 {
   for (; s != (lang_statement_union_type *) NULL; s = s->next)
     {
@@ -959,8 +1044,13 @@ DEFUN (map_input_to_output_sections, (s, target, output_section_statement),
        case lang_input_section_enum:
        case lang_object_symbols_statement_enum:
        case lang_data_statement_enum:
+       case lang_reloc_statement_enum:
        case lang_assignment_statement_enum:
        case lang_padding_statement_enum:
+       case lang_input_statement_enum:
+         if (output_section_statement != NULL
+             && output_section_statement->bfd_section == NULL)
+           init_os (output_section_statement);
          break;
        case lang_afile_asection_pair_statement_enum:
          FAIL ();
@@ -969,78 +1059,91 @@ DEFUN (map_input_to_output_sections, (s, target, output_section_statement),
          /* Mark the specified section with the supplied address */
          {
            lang_output_section_statement_type *os =
-           lang_output_section_statement_lookup
-           (s->address_statement.section_name);
+             lang_output_section_statement_lookup
+               (s->address_statement.section_name);
 
+           if (os->bfd_section == NULL)
+             init_os (os);
            os->addr_tree = s->address_statement.address;
-           if (os->bfd_section == (asection *) NULL)
-             {
-               einfo ("%P%F can't set the address of undefined section %s\n",
-                      s->address_statement.section_name);
-             }
          }
          break;
-       case lang_input_statement_enum:
-         /* A standard input statement, has no wildcards */
-         /*    ldmain_open_file_read_symbol(&s->input_statement);*/
-         break;
        }
     }
 }
 
-
-
-
-
 static void
-DEFUN (print_output_section_statement, (output_section_statement),
-       lang_output_section_statement_type * output_section_statement)
+print_output_section_statement (output_section_statement)
+     lang_output_section_statement_type * output_section_statement;
 {
   asection *section = output_section_statement->bfd_section;
 
   print_nl ();
   print_section (output_section_statement->name);
 
+
   if (section)
-    {
-      print_dot = section->vma;
-      print_space ();
-      print_section ("");
-      print_space ();
-      print_address (section->vma);
-      print_space ();
-      print_size (bfd_get_section_size_before_reloc (section));
-      print_space ();
-      print_alignment (section->alignment_power);
-      print_space ();
+  {
+    print_dot = section->vma;
+    print_space ();
+    print_section ("");
+    print_space ();
+    print_address (section->vma);
+    print_space ();
+    print_size (section->_raw_size);
+    print_space();
+    print_size(section->_cooked_size);
+    print_space ();
+    print_alignment (section->alignment_power);
+    print_space ();
 #if 0
-      fprintf (config.map_file, "%s flags", output_section_statement->region->name);
-      print_flags (stdout, &output_section_statement->flags);
+    fprintf (config.map_file, "%s flags", output_section_statement->region->name);
+    print_flags (stdout, &output_section_statement->flags);
 #endif
-      if (section->flags & SEC_LOAD)
-       fprintf (config.map_file, "load ");
-      if (section->flags & SEC_ALLOC)
-       fprintf (config.map_file, "alloc ");
-      if (section->flags & SEC_RELOC)
-       fprintf (config.map_file, "reloc ");
-      if (section->flags & SEC_HAS_CONTENTS)
-       fprintf (config.map_file, "contents ");
+    if (section->flags & SEC_LOAD)
+     fprintf (config.map_file, "load ");
+    if (section->flags & SEC_ALLOC)
+     fprintf (config.map_file, "alloc ");
+    if (section->flags & SEC_RELOC)
+     fprintf (config.map_file, "reloc ");
+    if (section->flags & SEC_HAS_CONTENTS)
+     fprintf (config.map_file, "contents ");
 
-    }
+  }
   else
+  {
+    fprintf (config.map_file, " (no attached output section)");
+  }
+  print_nl ();
+  if (output_section_statement->load_base)
     {
-      fprintf (config.map_file, "No attached output section");
+      int b = exp_get_value_int(output_section_statement->load_base,
+                               0, "output base", lang_final_phase_enum);
+      printf("Output address   %08x\n", b);
     }
-  print_nl ();
+  if (output_section_statement->section_alignment >= 0
+      || output_section_statement->section_alignment >= 0) 
+  {
+    printf("\t\t\t\t\tforced alignment ");
+    if ( output_section_statement->section_alignment >= 0) 
+    {
+      printf("section 2**%d ",output_section_statement->section_alignment );
+    }
+    if ( output_section_statement->subsection_alignment >= 0) 
+    {
+      printf("subsection 2**%d ",output_section_statement->subsection_alignment );
+    }
+  
+    print_nl ();
+  }
   print_statement (output_section_statement->children.head,
                   output_section_statement);
 
 }
 
 static void
-DEFUN (print_assignment, (assignment, output_section),
-       lang_assignment_statement_type * assignment AND
-       lang_output_section_statement_type * output_section)
+print_assignment (assignment, output_section)
+     lang_assignment_statement_type * assignment;
+     lang_output_section_statement_type * output_section;
 {
   etree_value_type result;
 
@@ -1071,8 +1174,8 @@ DEFUN (print_assignment, (assignment, output_section),
 }
 
 static void
-DEFUN (print_input_statement, (statm),
-       lang_input_statement_type * statm)
+print_input_statement (statm)
+     lang_input_statement_type * statm;
 {
   if (statm->filename != (char *) NULL)
     {
@@ -1080,27 +1183,39 @@ DEFUN (print_input_statement, (statm),
     }
 }
 
-static void
-DEFUN (print_symbol, (q),
-       asymbol * q)
+/* Print all the defined symbols for the abfd provided by in the supplied
+   section.
+*/
+
+static boolean 
+print_one_symbol (hash_entry, ptr)
+struct  bfd_link_hash_entry *hash_entry;
+PTR ptr;
 {
-  print_section ("");
-  fprintf (config.map_file, " ");
-  print_section ("");
-  fprintf (config.map_file, " ");
-  print_address (outside_symbol_address (q));
-  fprintf (config.map_file, "              %s", q->name ? q->name : " ");
-  print_nl ();
+  asection * sec = (asection *)ptr;
+
+  if (hash_entry->type == bfd_link_hash_defined) 
+    {
+      if (sec == hash_entry->u.def.section) {
+       print_section ("");
+       fprintf (config.map_file, " ");
+       print_section ("");
+       fprintf (config.map_file, " ");
+       print_address (hash_entry->u.def.value + outside_section_address (sec));
+       fprintf (config.map_file, "              %s", hash_entry->root.string);
+       print_nl ();
+      }
+    }
+
+  return true;
 }
 
 static void
-DEFUN (print_input_section, (in),
-       lang_input_section_type * in)
+print_input_section (in)
+     lang_input_section_type * in;
 {
   asection *i = in->section;
-  int size = i->reloc_done ?
-  bfd_get_section_size_after_reloc (i) :
-  bfd_get_section_size_before_reloc (i);
+  bfd_size_type size = i->_cooked_size != 0 ? i->_cooked_size : i->_raw_size;
 
   if (size != 0)
     {
@@ -1112,7 +1227,9 @@ DEFUN (print_input_section, (in),
        {
          print_address (i->output_section->vma + i->output_offset);
          fprintf (config.map_file, " ");
-         print_size (size);
+         print_size (i->_raw_size);
+         fprintf (config.map_file, " ");
+         print_size(i->_cooked_size);
          fprintf (config.map_file, " ");
          print_alignment (i->alignment_power);
          fprintf (config.map_file, " ");
@@ -1139,22 +1256,8 @@ DEFUN (print_input_section, (in),
              fprintf (config.map_file, "(overhead %d bytes)", (int) bfd_alloc_size (abfd));
              print_nl ();
 
-             /* Find all the symbols in this file defined in this section */
-
-               if (in->ifile->symbol_count)
-                 {
-                   asymbol **p;
-
-                   for (p = in->ifile->asymbols; *p; p++)
-                     {
-                       asymbol *q = *p;
-
-                       if (bfd_get_section (q) == i && q->flags & BSF_GLOBAL)
-                         {
-                           print_symbol (q);
-                         }
-                     }
-                 }
+             /* Print all the symbols */
+             bfd_link_hash_traverse (link_info.hash, print_one_symbol, (PTR) i);
            }
          else
            {
@@ -1172,16 +1275,16 @@ DEFUN (print_input_section, (in),
 }
 
 static void
-DEFUN (print_fill_statement, (fill),
-       lang_fill_statement_type * fill)
+print_fill_statement (fill)
+     lang_fill_statement_type * fill;
 {
   fprintf (config.map_file, "FILL mask ");
   print_fill (fill->fill);
 }
 
 static void
-DEFUN (print_data_statement, (data),
-       lang_data_statement_type * data)
+print_data_statement (data)
+     lang_data_statement_type * data;
 {
 /*  bfd_vma value; */
   print_section ("");
@@ -1208,6 +1311,10 @@ DEFUN (print_data_statement, (data),
       fprintf (config.map_file, "LONG ");
       print_dot += LONG_SIZE;
       break;
+    case QUAD:
+      fprintf (config.map_file, "QUAD ");
+      print_dot += QUAD_SIZE;
+      break;
     }
 
   exp_print_tree (data->exp);
@@ -1215,10 +1322,36 @@ DEFUN (print_data_statement, (data),
   fprintf (config.map_file, "\n");
 }
 
+/* Print a reloc statement.  */
+
+static void
+print_reloc_statement (reloc)
+     lang_reloc_statement_type *reloc;
+{
+  print_section ("");
+  print_space ();
+  print_section ("");
+  print_space ();
+
+/*  ASSERT(print_dot == data->output_vma);*/
+
+  print_address (reloc->output_vma + reloc->output_section->vma);
+  print_space ();
+  print_address (reloc->addend_value);
+  print_space ();
+
+  fprintf (config.map_file, "RELOC %s ", reloc->howto->name);
+
+  print_dot += bfd_get_reloc_size (reloc->howto);
+
+  exp_print_tree (reloc->addend_exp);
+
+  fprintf (config.map_file, "\n");
+}  
 
 static void
-DEFUN (print_padding_statement, (s),
-       lang_padding_statement_type * s)
+print_padding_statement (s)
+     lang_padding_statement_type * s;
 {
   print_section ("");
   print_space ();
@@ -1236,9 +1369,9 @@ DEFUN (print_padding_statement, (s),
 }
 
 static void
-DEFUN (print_wild_statement, (w, os),
-       lang_wild_statement_type * w AND
-       lang_output_section_statement_type * os)
+print_wild_statement (w, os)
+     lang_wild_statement_type * w;
+     lang_output_section_statement_type * os;
 {
   fprintf (config.map_file, " from ");
   if (w->filename != (char *) NULL)
@@ -1262,9 +1395,9 @@ DEFUN (print_wild_statement, (w, os),
 
 }
 static void
-DEFUN (print_statement, (s, os),
-       lang_statement_union_type * s AND
-       lang_output_section_statement_type * os)
+print_statement (s, os)
+     lang_statement_union_type * s;
+     lang_output_section_statement_type * os;
 {
   while (s)
     {
@@ -1293,6 +1426,9 @@ DEFUN (print_statement, (s, os),
        case lang_data_statement_enum:
          print_data_statement (&s->data_statement);
          break;
+       case lang_reloc_statement_enum:
+         print_reloc_statement (&s->reloc_statement);
+         break;
        case lang_input_section_enum:
          print_input_section (&s->input_section);
          break;
@@ -1312,7 +1448,7 @@ DEFUN (print_statement, (s, os),
        case lang_output_statement_enum:
          fprintf (config.map_file, "OUTPUT(%s %s)\n",
                   s->output_statement.name,
-                  output_target);
+                  output_target ? output_target : "");
          break;
        case lang_input_statement_enum:
          print_input_statement (&s->input_statement);
@@ -1327,7 +1463,7 @@ DEFUN (print_statement, (s, os),
 
 
 static void
-DEFUN_VOID (print_statements)
+print_statements ()
 {
   print_statement (statement_list.head,
                   abs_output_section);
@@ -1335,12 +1471,12 @@ DEFUN_VOID (print_statements)
 }
 
 static bfd_vma
-DEFUN (insert_pad, (this_ptr, fill, power, output_section_statement, dot),
-       lang_statement_union_type ** this_ptr AND
-       fill_type fill AND
-       unsigned int power AND
-       asection * output_section_statement AND
-       bfd_vma dot)
+insert_pad (this_ptr, fill, power, output_section_statement, dot)
+     lang_statement_union_type ** this_ptr;
+     fill_type fill;
+     unsigned int power;
+     asection * output_section_statement;
+     bfd_vma dot;
 {
   /* Align this section first to the
      input sections requirement, then
@@ -1382,38 +1518,36 @@ DEFUN (insert_pad, (this_ptr, fill, power, output_section_statement, dot),
 
 /* Work out how much this section will move the dot point */
 static bfd_vma
-DEFUN (size_input_section, (this_ptr, output_section_statement, fill, dot),
-       lang_statement_union_type ** this_ptr AND
-       lang_output_section_statement_type * output_section_statement AND
-       unsigned short fill AND
-       bfd_vma dot)
+size_input_section (this_ptr, output_section_statement, fill, dot, relax)
+     lang_statement_union_type ** this_ptr;
+     lang_output_section_statement_type * output_section_statement;
+     fill_type fill;
+     bfd_vma dot;
+     boolean relax;
 {
   lang_input_section_type *is = &((*this_ptr)->input_section);
   asection *i = is->section;
 
   if (is->ifile->just_syms_flag == false)
     {
+      if (output_section_statement->subsection_alignment != -1)
+       i->alignment_power =
+       output_section_statement->subsection_alignment;
+
       dot = insert_pad (this_ptr, fill, i->alignment_power,
                        output_section_statement->bfd_section, dot);
 
-      /* remember the largest size so we can malloc the largest area
-         needed for the output stage. Only remember the size of sections
-         which we will actually allocate  */
-      if (((i->flags &
-           (SEC_HAS_CONTENTS | SEC_LOAD)) == (SEC_HAS_CONTENTS | SEC_LOAD))
-         && (bfd_get_section_size_before_reloc (i) > largest_section))
-       {
-         largest_section = bfd_get_section_size_before_reloc (i);
-       }
-
       /* Remember where in the output section this input section goes */
 
       i->output_offset = dot - output_section_statement->bfd_section->vma;
 
-      /* Mark how big the output section must be to contain this now */
-      dot += bfd_get_section_size_before_reloc (i);
-      output_section_statement->bfd_section->_raw_size =
-       dot - output_section_statement->bfd_section->vma;
+      /* Mark how big the output section must be to contain this now
+        */
+      if (i->_cooked_size != 0)
+       dot += i->_cooked_size;
+      else
+       dot += i->_raw_size;
+      output_section_statement->bfd_section->_raw_size = dot - output_section_statement->bfd_section->vma;
     }
   else
     {
@@ -1423,242 +1557,324 @@ DEFUN (size_input_section, (this_ptr, output_section_statement, fill, dot),
   return dot;
 }
 
-/* Sizing happens in two passes, first pass we allocate worst case
-   stuff. The second pass (if relaxing), we use what we learnt to
-   change the size of some relocs from worst case to better
-   */
-static boolean had_relax;
+/* This variable indicates whether bfd_relax_section should be called
+   again.  */
 
-static bfd_vma
-DEFUN (lang_size_sections, (s, output_section_statement, prev, fill,
-                           dot, relax),
-       lang_statement_union_type * s AND
-       lang_output_section_statement_type * output_section_statement AND
-       lang_statement_union_type ** prev AND
-       unsigned short fill AND
-       bfd_vma dot AND
-       boolean relax)
+static boolean relax_again;
+
+/* Set the sizes for all the output sections.  */
+
+bfd_vma
+lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
+     lang_statement_union_type * s;
+     lang_output_section_statement_type * output_section_statement;
+     lang_statement_union_type ** prev;
+     fill_type fill;
+     bfd_vma dot;
+     boolean relax;
 {
   /* Size up the sections from their constituent parts */
   for (; s != (lang_statement_union_type *) NULL; s = s->next)
+  {
+    switch (s->header.type)
     {
-      switch (s->header.type)
-       {
-
-       case lang_output_section_statement_enum:
-         {
-           bfd_vma after;
-           lang_output_section_statement_type *os = &s->output_section_statement;
-
-           if (os->bfd_section == &bfd_abs_section)
-             {
-               /* No matter what happens, an abs section starts at zero */
-               bfd_set_section_vma (0, os->bfd_section, 0);
-             }
-           else
-             {
-               if (os->addr_tree == (etree_type *) NULL)
-                 {
-                   /* No address specified for this section, get one
-                      from the region specification
-                      */
-                   if (os->region == (lang_memory_region_type *) NULL)
-                     {
-                       os->region = lang_memory_region_lookup ("*default*");
-                     }
-                   dot = os->region->current;
-                 }
-               else
-                 {
-                   etree_value_type r;
-
-                   r = exp_fold_tree (os->addr_tree,
-                                      abs_output_section,
-                                      lang_allocating_phase_enum,
-                                      dot, &dot);
-                   if (r.valid == false)
-                     {
-                       einfo ("%F%S: non constant address expression for section %s\n",
-                              os->name);
-                     }
-                   dot = r.value;
-                 }
-               /* The section starts here */
-               /* First, align to what the section needs */
-
-
-               dot = align_power (dot, os->bfd_section->alignment_power);
-               bfd_set_section_vma (0, os->bfd_section, dot);
-             }
 
+     case lang_output_section_statement_enum:
+     {
+       bfd_vma after;
+       lang_output_section_statement_type *os = &s->output_section_statement;
+
+       if (os->bfd_section == NULL)
+        {
+          /* This section was never actually created.  */
+          break;
+        }
+
+       /* If this is a COFF shared library section, use the size and
+         address from the input section.  FIXME: This is COFF
+         specific; it would be cleaner if there were some other way
+         to do this, but nothing simple comes to mind.  */
+       if ((os->bfd_section->flags & SEC_COFF_SHARED_LIBRARY) != 0)
+        {
+          asection *input;
+
+          if (os->children.head == NULL
+              || os->children.head->next != NULL
+              || os->children.head->header.type != lang_input_section_enum)
+            einfo ("%P%X: Internal error on COFF shared library section %s",
+                   os->name);
+
+          input = os->children.head->input_section.section;
+          bfd_set_section_vma (os->bfd_section->owner,
+                               os->bfd_section,
+                               bfd_section_vma (input->owner, input));
+          os->bfd_section->_raw_size = input->_raw_size;
+          break;
+        }
+
+       if (bfd_is_abs_section (os->bfd_section))
+       {
+        /* No matter what happens, an abs section starts at zero */
+        ASSERT (os->bfd_section->vma == 0);
+       }
+       else
+       {
+        if (os->addr_tree == (etree_type *) NULL)
+        {
+          /* No address specified for this section, get one
+             from the region specification
+             */
+          if (os->region == (lang_memory_region_type *) NULL)
+          {
+            os->region = lang_memory_region_lookup ("*default*");
+          }
+          dot = os->region->current;
+          if (os->section_alignment == -1)
+            dot = align_power (dot, os->bfd_section->alignment_power);
+        }
+        else
+        {
+          etree_value_type r;
+
+          r = exp_fold_tree (os->addr_tree,
+                             abs_output_section,
+                             lang_allocating_phase_enum,
+                             dot, &dot);
+          if (r.valid == false)
+          {
+            einfo ("%F%S: non constant address expression for section %s\n",
+                   os->name);
+          }
+          dot = r.value;
+        }
+        /* The section starts here */
+        /* First, align to what the section needs */
+
+        if (os->section_alignment != -1)
+          dot = align_power (dot, os->section_alignment);
+
+        bfd_set_section_vma (0, os->bfd_section, dot);
+        
+        if (os->load_base) {
+          os->bfd_section->lma 
+            = exp_get_value_int(os->load_base, 0,"load base", lang_final_phase_enum);
+        }
+
+        os->bfd_section->output_offset = 0;
+       }
+
+       (void) lang_size_sections (os->children.head, os, &os->children.head,
+                                 os->fill, dot, relax);
+       /* Ignore the size of the input sections, use the vma and size to */
+       /* align against */
+
+       after = ALIGN_N (os->bfd_section->vma +
+                       os->bfd_section->_raw_size,
+                       /* The coercion here is important, see ld.h.  */
+                       (bfd_vma) os->block_value);
+
+       if (bfd_is_abs_section (os->bfd_section))
+        ASSERT (after == os->bfd_section->vma);
+       else
+        os->bfd_section->_raw_size = after - os->bfd_section->vma;
+       dot = os->bfd_section->vma + os->bfd_section->_raw_size;
+       os->processed = true;
+
+       /* Replace into region ? */
+       if (os->region != (lang_memory_region_type *) NULL)
+       {
+        os->region->current = dot;
+        /* Make sure this isn't silly */
+        if (( os->region->current
+              > os->region->origin + os->region->length)
+            || ( os->region->origin > os->region->current ))
+          {
+            einfo ("%X%P: region %s is full (%B section %s)\n",
+                   os->region->name,
+                   os->bfd_section->owner,
+                   os->bfd_section->name);
+            /* Reset the region pointer */
+            os->region->current = 0;
+
+          }
+
+       }
+     }
 
-           os->bfd_section->output_offset = 0;
+      break;
+     case lang_constructors_statement_enum:
+      dot = lang_size_sections (constructor_list.head,
+                               output_section_statement,
+                               &s->wild_statement.children.head,
+                               fill,
+                               dot, relax);
+      break;
 
-           (void) lang_size_sections (os->children.head, os, &os->children.head,
-                                      os->fill, dot, relax);
-           /* Ignore the size of the input sections, use the vma and size to */
-           /* align against */
+     case lang_data_statement_enum:
+     {
+       unsigned int size = 0;
+
+       s->data_statement.output_vma = dot - output_section_statement->bfd_section->vma;
+       s->data_statement.output_section =
+       output_section_statement->bfd_section;
+
+       switch (s->data_statement.type)
+       {
+        case QUAD:
+        size = QUAD_SIZE;
+        break;
+       case LONG:
+        size = LONG_SIZE;
+        break;
+       case SHORT:
+        size = SHORT_SIZE;
+        break;
+       case BYTE:
+        size = BYTE_SIZE;
+        break;
+
+       }
+       dot += size;
+       output_section_statement->bfd_section->_raw_size += size;
+     }
+      break;
 
+     case lang_reloc_statement_enum:
+     {
+       int size;
 
-           after = ALIGN (os->bfd_section->vma +
-                          os->bfd_section->_raw_size,
-                          os->block_value);
+       s->reloc_statement.output_vma =
+        dot - output_section_statement->bfd_section->vma;
+       s->reloc_statement.output_section =
+        output_section_statement->bfd_section;
+       size = bfd_get_reloc_size (s->reloc_statement.howto);
+       dot += size;
+       output_section_statement->bfd_section->_raw_size += size;
+     }
+     break;
+     
+     case lang_wild_statement_enum:
 
+      dot = lang_size_sections (s->wild_statement.children.head,
+                               output_section_statement,
+                               &s->wild_statement.children.head,
 
-           os->bfd_section->_raw_size = after - os->bfd_section->vma;
-           dot = os->bfd_section->vma + os->bfd_section->_raw_size;
-           os->processed = true;
+                               fill, dot, relax);
 
-           /* Replace into region ? */
-           if (os->addr_tree == (etree_type *) NULL
-               && os->region != (lang_memory_region_type *) NULL)
-             {
-               os->region->current = dot;
-               /* Make sure this isn't silly */
-               if (os->region->current >
-                   os->region->origin +
-                   os->region->length)
-                 {
-                   einfo ("%X%P: Region %s is full (%B section %s)\n",
-                          os->region->name,
-                          os->bfd_section->owner,
-                          os->bfd_section->name);
-                   /* Reset the region pointer */
-                   os->region->current = 0;
-
-                 }
-
-             }
-         }
+      break;
 
-         break;
-       case lang_constructors_statement_enum:
-         dot = lang_size_sections (constructor_list.head,
-                                   output_section_statement,
-                                   &s->wild_statement.children.head,
-                                   fill,
-                                   dot, relax);
-         break;
+     case lang_object_symbols_statement_enum:
+      link_info.create_object_symbols_section =
+       output_section_statement->bfd_section;
+      break;
+     case lang_output_statement_enum:
+     case lang_target_statement_enum:
+      break;
+     case lang_input_section_enum:
+      {
+       asection *i;
 
-       case lang_data_statement_enum:
+       i = (*prev)->input_section.section;
+       if (! relax)
+         i->_cooked_size = i->_raw_size;
+       else
          {
-           unsigned int size = 0;
-
-           s->data_statement.output_vma = dot - output_section_statement->bfd_section->vma;
-           s->data_statement.output_section =
-             output_section_statement->bfd_section;
-
-           switch (s->data_statement.type)
-             {
-             case LONG:
-               size = LONG_SIZE;
-               break;
-             case SHORT:
-               size = SHORT_SIZE;
-               break;
-             case BYTE:
-               size = BYTE_SIZE;
-               break;
+           boolean again;
 
-             }
-           dot += size;
-           output_section_statement->bfd_section->_raw_size += size;
+           if (! bfd_relax_section (i->owner, i, &link_info, &again))
+             einfo ("%P%F: can't relax section: %E\n");
+           if (again)
+             relax_again = true;
          }
-         break;
-
-       case lang_wild_statement_enum:
-
-         dot = lang_size_sections (s->wild_statement.children.head,
-                                   output_section_statement,
-                                   &s->wild_statement.children.head,
-
-                                   fill, dot, relax);
-
-         break;
-
-       case lang_object_symbols_statement_enum:
-         create_object_symbols = output_section_statement;
-         break;
-       case lang_output_statement_enum:
-       case lang_target_statement_enum:
-         break;
-       case lang_input_section_enum:
-         if (relax)
-           {
-             relaxing = true;
-
-             had_relax = had_relax || relax_section (prev);
-             relaxing = false;
-
-           }
-
-         dot = size_input_section (prev,
-                                   output_section_statement,
-                                   output_section_statement->fill, dot);
-         break;
-       case lang_input_statement_enum:
-         break;
-       case lang_fill_statement_enum:
-         s->fill_statement.output_section = output_section_statement->bfd_section;
-
-         fill = s->fill_statement.fill;
-         break;
-       case lang_assignment_statement_enum:
-         {
-           bfd_vma newdot = dot;
-
-           exp_fold_tree (s->assignment_statement.exp,
-                          output_section_statement,
-                          lang_allocating_phase_enum,
-                          dot,
-                          &newdot);
+       dot = size_input_section (prev,
+                                 output_section_statement,
+                                 output_section_statement->fill,
+                                 dot, relax);
+      }
+      break;
+     case lang_input_statement_enum:
+      break;
+     case lang_fill_statement_enum:
+      s->fill_statement.output_section = output_section_statement->bfd_section;
 
-           if (newdot != dot && !relax)
-             /* We've been moved ! so insert a pad */
-             {
-               lang_statement_union_type *new =
-               (lang_statement_union_type *)
-               stat_alloc ((bfd_size_type) (sizeof (lang_padding_statement_type)));
-
-               /* Link into existing chain */
-               new->header.next = *prev;
-               *prev = new;
-               new->header.type = lang_padding_statement_enum;
-               new->padding_statement.output_section =
-                 output_section_statement->bfd_section;
-               new->padding_statement.output_offset =
-                 dot - output_section_statement->bfd_section->vma;
-               new->padding_statement.fill = fill;
-               new->padding_statement.size = newdot - dot;
-               output_section_statement->bfd_section->_raw_size +=
-                 new->padding_statement.size;
-               dot = newdot;
-             }
-         }
+      fill = s->fill_statement.fill;
+      break;
+     case lang_assignment_statement_enum:
+     {
+       bfd_vma newdot = dot;
+
+       exp_fold_tree (s->assignment_statement.exp,
+                     output_section_statement,
+                     lang_allocating_phase_enum,
+                     dot,
+                     &newdot);
+
+       if (newdot != dot && !relax)
+        {
+          /* The assignment changed dot.  Insert a pad.  */
+          if (output_section_statement == abs_output_section)
+            {
+              /* If we don't have an output section, then just adjust
+                 the default memory address.  */
+              lang_memory_region_lookup ("*default*")->current = newdot;
+            }
+          else
+            {
+              lang_statement_union_type *new =
+                ((lang_statement_union_type *)
+                 stat_alloc (sizeof (lang_padding_statement_type)));
+
+              /* Link into existing chain */
+              new->header.next = *prev;
+              *prev = new;
+              new->header.type = lang_padding_statement_enum;
+              new->padding_statement.output_section =
+                output_section_statement->bfd_section;
+              new->padding_statement.output_offset =
+                dot - output_section_statement->bfd_section->vma;
+              new->padding_statement.fill = fill;
+              new->padding_statement.size = newdot - dot;
+              output_section_statement->bfd_section->_raw_size +=
+                new->padding_statement.size;
+            }
+
+          dot = newdot;
+        }
+     }
+     break;
+
+   case lang_padding_statement_enum:
+     /* If we are relaxing, and this is not the first pass, some
+       padding statements may have been inserted during previous
+       passes.  We may have to move the padding statement to a new
+       location if dot has a different value at this point in this
+       pass than it did at this point in the previous pass.  */
+     s->padding_statement.output_offset =
+       dot - output_section_statement->bfd_section->vma;
+     dot += s->padding_statement.size;
+     break;
+
+     default:
+      FAIL ();
+      break;
 
-         break;
-       default:
-         FAIL ();
-         break;
-         /* This can only get here when relaxing is turned on */
-       case lang_padding_statement_enum:
+      /* This can only get here when relaxing is turned on */
 
-       case lang_address_statement_enum:
-         break;
-       }
-      prev = &s->header.next;
+     case lang_address_statement_enum:
+      break;
     }
+    prev = &s->header.next;
+  }
   return dot;
 }
 
 static bfd_vma
-DEFUN (lang_do_assignments, (s, output_section_statement, fill, dot),
-       lang_statement_union_type * s AND
-       lang_output_section_statement_type * output_section_statement AND
-       unsigned short fill AND
-       bfd_vma dot)
+lang_do_assignments (s, output_section_statement, fill, dot)
+     lang_statement_union_type * s;
+     lang_output_section_statement_type * output_section_statement;
+     fill_type fill;
+     bfd_vma dot;
 {
-
   for (; s != (lang_statement_union_type *) NULL; s = s->next)
     {
       switch (s->header.type)
@@ -1673,11 +1889,15 @@ DEFUN (lang_do_assignments, (s, output_section_statement, fill, dot),
        case lang_output_section_statement_enum:
          {
            lang_output_section_statement_type *os =
-           &(s->output_section_statement);
+             &(s->output_section_statement);
 
-           dot = os->bfd_section->vma;
-           (void) lang_do_assignments (os->children.head, os, os->fill, dot);
-           dot = os->bfd_section->vma + os->bfd_section->_raw_size;
+           if (os->bfd_section != NULL)
+             {
+               dot = os->bfd_section->vma;
+               (void) lang_do_assignments (os->children.head, os,
+                                           os->fill, dot);
+               dot = os->bfd_section->vma + os->bfd_section->_raw_size;
+             }
          }
          break;
        case lang_wild_statement_enum:
@@ -1704,10 +1924,13 @@ DEFUN (lang_do_assignments, (s, output_section_statement, fill, dot),
                                   lang_final_phase_enum, dot, &dot);
            s->data_statement.value = value.value;
            if (value.valid == false)
-             einfo ("%F%P: Invalid data statement\n");
+             einfo ("%F%P: invalid data statement\n");
          }
          switch (s->data_statement.type)
            {
+           case QUAD:
+             dot += QUAD_SIZE;
+             break;
            case LONG:
              dot += LONG_SIZE;
              break;
@@ -1719,11 +1942,29 @@ DEFUN (lang_do_assignments, (s, output_section_statement, fill, dot),
              break;
            }
          break;
+
+       case lang_reloc_statement_enum:
+         {
+           etree_value_type value;
+
+           value = exp_fold_tree (s->reloc_statement.addend_exp,
+                                  abs_output_section,
+                                  lang_final_phase_enum, dot, &dot);
+           s->reloc_statement.addend_value = value.value;
+           if (value.valid == false)
+             einfo ("%F%P: invalid reloc statement\n");
+         }
+         dot += bfd_get_reloc_size (s->reloc_statement.howto);
+         break;
+
        case lang_input_section_enum:
          {
            asection *in = s->input_section.section;
 
-           dot += bfd_get_section_size_before_reloc (in);
+           if (in->_cooked_size != 0)
+             dot += in->_cooked_size;
+           else
+             dot += in->_raw_size;
          }
          break;
 
@@ -1756,93 +1997,54 @@ DEFUN (lang_do_assignments, (s, output_section_statement, fill, dot),
   return dot;
 }
 
-
-
-static void
-DEFUN_VOID (lang_relocate_globals)
-{
-
-  /*
-    Each ldsym_type maintains a chain of pointers to asymbols which
-    references the definition.  Replace each pointer to the referenence
-    with a pointer to only one place, preferably the definition. If
-    the defintion isn't available then the common symbol, and if
-    there isn't one of them then choose one reference.
-    */
-
-  FOR_EACH_LDSYM (lgs)
-  {
-    asymbol *it;
-
-    if (lgs->sdefs_chain)
-      {
-       it = *(lgs->sdefs_chain);
-      }
-    else if (lgs->scoms_chain != (asymbol **) NULL)
-      {
-       it = *(lgs->scoms_chain);
-      }
-    else if (lgs->srefs_chain != (asymbol **) NULL)
-      {
-       it = *(lgs->srefs_chain);
-      }
-    else
-      {
-       /* This can happen when the command line asked for a symbol to
-          be -u */
-       it = (asymbol *) NULL;
-      }
-    if (it != (asymbol *) NULL)
-      {
-       asymbol **ptr = lgs->srefs_chain;;
-       if (lgs->flags & SYM_WARNING)
-         {
-           produce_warnings (lgs, it);
-         }
-
-       while (ptr != (asymbol **) NULL)
-         {
-           asymbol *ref = *ptr;
-
-           *ptr = it;
-           ptr = (asymbol **) (ref->udata);
-         }
-      }
-  }
-}
-
-
-
 static void
-DEFUN_VOID (lang_finish)
+lang_finish ()
 {
-  ldsym_type *lgs;
+  struct bfd_link_hash_entry *h;
+  boolean warn = link_info.relocateable ? false : true;
 
   if (entry_symbol == (char *) NULL)
     {
-      /* No entry has been specified, look for start */
+      /* No entry has been specified.  Look for start, but don't warn
+        if we don't find it.  */
       entry_symbol = "start";
+      warn = false;
     }
-  lgs = ldsym_get_soft (entry_symbol);
-  if (lgs && lgs->sdefs_chain)
-    {
-      asymbol *sy = *(lgs->sdefs_chain);
-
-      /* We can set the entry address*/
-      bfd_set_start_address (output_bfd,
-                            outside_symbol_address (sy));
 
+  h = bfd_link_hash_lookup (link_info.hash, entry_symbol, false, false, true);
+  if (h != (struct bfd_link_hash_entry *) NULL
+      && h->type == bfd_link_hash_defined)
+    {
+      bfd_vma val;
+
+      val = (h->u.def.value
+            + bfd_get_section_vma (output_bfd,
+                                   h->u.def.section->output_section)
+            + h->u.def.section->output_offset);
+      if (! bfd_set_start_address (output_bfd, val))
+       einfo ("%P%F:%s: can't set start address\n", entry_symbol);
     }
   else
     {
-      /* Can't find anything reasonable,
-         use the first address in the text section
-         */
-      asection *ts = bfd_get_section_by_name (output_bfd, ".text");
+      asection *ts;
 
-      if (ts)
+      /* Can't find the entry symbol.  Use the first address in the
+        text section.  */
+      ts = bfd_get_section_by_name (output_bfd, ".text");
+      if (ts != (asection *) NULL)
+       {
+         if (warn)
+           einfo ("%P: warning: cannot find entry symbol %s; defaulting to %V\n",
+                  entry_symbol, bfd_get_section_vma (output_bfd, ts));
+         if (! bfd_set_start_address (output_bfd,
+                                      bfd_get_section_vma (output_bfd, ts)))
+           einfo ("%P%F: can't set start address\n");
+       }
+      else
        {
-         bfd_set_start_address (output_bfd, ts->vma);
+         if (warn)
+           einfo ("%P: warning: cannot find entry symbol %s; not setting start address\n",
+                  entry_symbol);
        }
     }
 }
@@ -1850,7 +2052,7 @@ DEFUN_VOID (lang_finish)
 /* By now we know the target architecture, and we may have an */
 /* ldfile_output_machine_name */
 static void
-DEFUN_VOID (lang_check)
+lang_check ()
 {
   lang_statement_union_type *file;
   bfd *input_bfd;
@@ -1862,9 +2064,6 @@ DEFUN_VOID (lang_check)
        file != (lang_statement_union_type *) NULL;
        file = file->input_statement.next)
     {
-      unsigned long ldfile_new_output_machine = 0;
-      enum bfd_architecture ldfile_new_output_architecture = bfd_arch_unknown;
-
       input_bfd = file->input_statement.the_bfd;
 
       input_machine = bfd_get_mach (input_bfd);
@@ -1876,7 +2075,7 @@ DEFUN_VOID (lang_check)
 
       compatible = bfd_arch_get_compatible (input_bfd,
                                            output_bfd);
-
       if (compatible)
        {
          ldfile_output_machine = compatible->mach;
@@ -1885,125 +2084,114 @@ DEFUN_VOID (lang_check)
       else
        {
 
-         info ("%P: warning, %s architecture of input file `%B' incompatible with %s output\n",
+         einfo ("%P: warning: %s architecture of input file `%B' is incompatible with %s output\n",
                bfd_printable_name (input_bfd), input_bfd,
                bfd_printable_name (output_bfd));
 
-         bfd_set_arch_mach (output_bfd,
-                            ldfile_new_output_architecture,
-                            ldfile_new_output_machine);
+         if (! bfd_set_arch_mach (output_bfd,
+                                  input_architecture,
+                                  input_machine))
+           einfo ("%P%F:%s: can't set architecture: %E\n",
+                  bfd_get_filename (output_bfd));
        }
 
     }
 }
 
-/*
- * run through all the global common symbols and tie them
- * to the output section requested.
- *
- As an experiment we do this 4 times, once for all the byte sizes,
- then all the two  bytes, all the four bytes and then everything else
-  */
+/* Look through all the global common symbols and attach them to the
+   correct section.  The -sort-common command line switch may be used
+   to roughly sort the entries by size.  */
 
 static void
-DEFUN_VOID (lang_common)
+lang_common ()
 {
-  ldsym_type *lgs;
-  size_t power;
+  if (link_info.relocateable
+      && ! command_line.force_common_definition)
+    return;
 
-  if (config.relocateable_output == false ||
-      command_line.force_common_definition == true)
+  if (! config.sort_common)
+    bfd_link_hash_traverse (link_info.hash, lang_one_common, (PTR) NULL);
+  else
     {
-      for (power = 1; (config.sort_common == true && power == 1) || (power <= 16); power <<= 1)
-       {
-         for (lgs = symbol_head;
-              lgs != (ldsym_type *) NULL;
-              lgs = lgs->next)
-           {
-             asymbol *com;
-             unsigned int power_of_two;
-             size_t size;
-             size_t align;
+      unsigned int power;
 
-             if (lgs->scoms_chain != (asymbol **) NULL)
-               {
-                 com = *(lgs->scoms_chain);
-                 size = com->value;
-                 switch (size)
-                   {
-                   case 0:
-                   case 1:
-                     align = 1;
-                     power_of_two = 0;
-                     break;
-                   case 2:
-                     power_of_two = 1;
-                     align = 2;
-                     break;
-                   case 3:
-                   case 4:
-                     power_of_two = 2;
-                     align = 4;
-                     break;
-                   case 5:
-                   case 6:
-                   case 7:
-                   case 8:
-                     power_of_two = 3;
-                     align = 8;
-                     break;
-                   default:
-                     power_of_two = 4;
-                     align = 16;
-                     break;
-                   }
-                 if (config.sort_common == false || align == power)
-                   {
-                     /* Change from a common symbol into a definition of
-                        a symbol */
-                     lgs->sdefs_chain = lgs->scoms_chain;
-                     lgs->scoms_chain = (asymbol **) NULL;
-                     commons_pending--;
-                     /* Point to the correct common section */
-                     com->section =
-                       ((lang_input_statement_type *)
-                        (com->the_bfd->usrdata))->common_section;
-                     /*  Fix the size of the common section */
-
-                     com->section->_raw_size =
-                       ALIGN (com->section->_raw_size, align);
-
-                     /* Remember if this is the biggest alignment ever seen */
-                     if (power_of_two > com->section->alignment_power)
-                       {
-                         com->section->alignment_power = power_of_two;
-                       }
+      for (power = 1; power <= 16; power <<= 1)
+       bfd_link_hash_traverse (link_info.hash, lang_one_common,
+                               (PTR) &power);
+    }
+}
 
-                     /* Symbol stops being common and starts being global, but
-                        we remember that it was common once. */
+/* Place one common symbol in the correct section.  */
 
-                     com->flags = BSF_EXPORT | BSF_GLOBAL | BSF_OLD_COMMON;
-                     com->value = com->section->_raw_size;
+static boolean
+lang_one_common (h, info)
+     struct bfd_link_hash_entry *h;
+     PTR info;
+{
+  unsigned int power_of_two;
+  bfd_vma size;
+  size_t align;
+  asection *section;
 
-                     if (write_map)
-                       {
-                         fprintf (config.map_file, "Allocating common %s: %x at %x %s\n",
-                                  lgs->name,
-                                  (unsigned) size,
-                                  (unsigned) com->value,
-                                  com->the_bfd->filename);
-                       }
+  if (h->type != bfd_link_hash_common)
+    return true;
+
+  size = h->u.c.size;
+  switch (size)
+    {
+    case 0:
+    case 1:
+      power_of_two = 0;
+      align = 1;
+      break;
+    case 2:
+      power_of_two = 1;
+      align = 2;
+      break;
+    case 3:
+    case 4:
+      power_of_two = 2;
+      align = 4;
+      break;
+    case 5:
+    case 6:
+    case 7:
+    case 8:
+      power_of_two = 3;
+      align = 8;
+      break;
+    default:
+      power_of_two = 4;
+      align = 16;
+      break;
+    }
+             
+  if (config.sort_common && align != *(unsigned int *) info)
+    return true;
 
-                     com->section->_raw_size += size;
+  section = h->u.c.section;
 
-                   }
-               }
+  /* Increase the size of the section.  */
+  section->_raw_size = ALIGN_N (section->_raw_size, align);
 
-           }
-       }
-    }
+  /* Adjust the alignment if necessary.  */
+  if (power_of_two > section->alignment_power)
+    section->alignment_power = power_of_two;
+
+  /* Change the symbol from common to defined.  */
+  h->type = bfd_link_hash_defined;
+  h->u.def.section = section;
+  h->u.def.value = section->_raw_size;
 
+  /* Increase the size of the section.  */
+  section->_raw_size += size;
 
+  if (config.map_file != NULL)
+    fprintf (config.map_file, "Allocating common %s: %lx at %lx %s\n",
+            h->root.string, (unsigned long) size,
+            (unsigned long) h->u.def.value, section->owner->filename);
+
+  return true;
 }
 
 /*
@@ -2014,7 +2202,7 @@ into the statement tree.
 */
 
 static void
-DEFUN_VOID (lang_place_orphans)
+lang_place_orphans ()
 {
   lang_input_statement_type *file;
 
@@ -2024,6 +2212,9 @@ DEFUN_VOID (lang_place_orphans)
     {
       asection *s;
 
+      if (file->just_syms_flag)
+       continue;
+
       for (s = file->the_bfd->sections;
           s != (asection *) NULL;
           s = s->next)
@@ -2038,13 +2229,13 @@ DEFUN_VOID (lang_place_orphans)
                  /* This is a lonely common section which must
                     have come from an archive. We attatch to the
                     section with the wildcard  */
-                 if (config.relocateable_output != true
-                     && command_line.force_common_definition == false)
+                 if (! link_info.relocateable
+                     && ! command_line.force_common_definition)
                    {
                      if (default_common_section ==
                          (lang_output_section_statement_type *) NULL)
                        {
-                         info ("%P: No [COMMON] command, defaulting to .bss\n");
+                         info_msg ("%P: no [COMMON] command, defaulting to .bss\n");
 
                          default_common_section =
                            lang_output_section_statement_lookup (".bss");
@@ -2068,9 +2259,9 @@ DEFUN_VOID (lang_place_orphans)
 
 
 void
-DEFUN (lang_set_flags, (ptr, flags),
-       int *ptr AND
-       CONST char *flags)
+lang_set_flags (ptr, flags)
+     int *ptr;
+     CONST char *flags;
 {
   boolean state = false;
 
@@ -2100,18 +2291,35 @@ DEFUN (lang_set_flags, (ptr, flags),
          /*      ptr->flag_loadable= state;*/
          break;
        default:
-         einfo ("%P%F illegal syntax in flags\n");
+         einfo ("%P%F: invalid syntax in flags\n");
          break;
        }
       flags++;
     }
 }
 
+/* Call a function on each input file.  This function will be called
+   on an archive, but not on the elements.  */
+
+void
+lang_for_each_input_file (func)
+     void (*func) PARAMS ((lang_input_statement_type *));
+{
+  lang_input_statement_type *f;
+
+  for (f = (lang_input_statement_type *) input_file_chain.head;
+       f != NULL;
+       f = (lang_input_statement_type *) f->next_real_file)
+    func (f);
+}
 
+/* Call a function on each file.  The function will be called on all
+   the elements of an archive which are included in the link, but will
+   not be called on the archive file itself.  */
 
 void
-DEFUN (lang_for_each_file, (func),
-       PROTO (void, (*func), (lang_input_statement_type *)))
+lang_for_each_file (func)
+     void (*func) PARAMS ((lang_input_statement_type *));
 {
   lang_input_statement_type *f;
 
@@ -2123,10 +2331,13 @@ DEFUN (lang_for_each_file, (func),
     }
 }
 
+#if 0
+
+/* Not used.  */
 
 void
-DEFUN (lang_for_each_input_section, (func),
-       PROTO (void, (*func), (bfd * ab, asection * as)))
+lang_for_each_input_section (func)
+     void (*func) PARAMS ((bfd * ab, asection * as));
 {
   lang_input_statement_type *f;
 
@@ -2145,47 +2356,76 @@ DEFUN (lang_for_each_input_section, (func),
     }
 }
 
-
+#endif
 
 void
-DEFUN (ldlang_add_file, (entry),
-       lang_input_statement_type * entry)
+ldlang_add_file (entry)
+     lang_input_statement_type * entry;
 {
+  bfd **pp;
 
   lang_statement_append (&file_chain,
                         (lang_statement_union_type *) entry,
                         &entry->next);
+
+  /* The BFD linker needs to have a list of all input BFDs involved in
+     a link.  */
+  ASSERT (entry->the_bfd->link_next == (bfd *) NULL);
+  ASSERT (entry->the_bfd != output_bfd);
+  for (pp = &link_info.input_bfds;
+       *pp != (bfd *) NULL;
+       pp = &(*pp)->link_next)
+    ;
+  *pp = entry->the_bfd;
+  entry->the_bfd->usrdata = (PTR) entry;
+  bfd_set_gp_size (entry->the_bfd, g_switch_value);
 }
 
 void
-DEFUN (lang_add_output, (name),
-       CONST char *name)
+lang_add_output (name, from_script)
+     CONST char *name;
+     int from_script;
 {
-  lang_output_statement_type *new = new_stat (lang_output_statement,
-                                             stat_ptr);
-
-  new->name = name;
-  had_output_filename = true;
+  /* Make -o on command line override OUTPUT in script.  */
+  if (had_output_filename == false || !from_script)
+    {
+      output_filename = name;
+      had_output_filename = true;
+    }
 }
 
 
 static lang_output_section_statement_type *current_section;
 
+static int topower(x)
+     int x;
+{
+  unsigned  int i = 1;
+  int l;
+  if (x < 0) return -1;
+  for (l = 0; l < 32; l++) 
+  {
+    if (i >= x) return l;
+    i<<=1;
+  }
+  return 0;
+}
 void
-DEFUN (lang_enter_output_section_statement,
-       (output_section_statement_name,
-       address_exp,
-       flags,
-       block_value),
-       char *output_section_statement_name AND
-       etree_type * address_exp AND
-       int flags AND
-       bfd_vma block_value)
+lang_enter_output_section_statement (output_section_statement_name,
+                                    address_exp, flags, block_value,
+                                    align, subalign, ebase)
+     const char *output_section_statement_name;
+     etree_type * address_exp;
+     int flags;
+     bfd_vma block_value;
+     etree_type *align;
+     etree_type *subalign;
+     etree_type *ebase;
 {
   lang_output_section_statement_type *os;
 
   current_section =
-    os =
+   os =
     lang_output_section_statement_lookup (output_section_statement_name);
 
 
@@ -2197,30 +2437,42 @@ DEFUN (lang_enter_output_section_statement,
 
   if (os->addr_tree ==
       (etree_type *) NULL)
-    {
-      os->addr_tree =
-       address_exp;
-    }
+  {
+    os->addr_tree =
+     address_exp;
+  }
   os->flags = flags;
-  os->block_value = block_value;
+  if (flags & SEC_NEVER_LOAD)
+   os->loadable = 0;
+  else
+   os->loadable = 1;
+  os->block_value = block_value ? block_value : 1;
   stat_ptr = &os->children;
 
+  os->subsection_alignment = topower(
+   exp_get_value_int(subalign, -1,
+                    "subsection alignment",
+                    0));
+  os->section_alignment = topower(
+   exp_get_value_int(align, -1,
+                    "section alignment", 0));
+
+  os->load_base = ebase;
 }
 
+
 void
-DEFUN_VOID (lang_final)
+lang_final ()
 {
-  if (had_output_filename == false)
-    {
-      extern CONST char *output_filename;
+  lang_output_statement_type *new =
+    new_stat (lang_output_statement, stat_ptr);
 
-      lang_add_output (output_filename);
-    }
+  new->name = output_filename;
 }
 
 /* Reset the current counters in the regions */
 static void
-DEFUN_VOID (reset_memory_regions)
+reset_memory_regions ()
 {
   lang_memory_region_type *p = lang_memory_region_list;
 
@@ -2228,51 +2480,20 @@ DEFUN_VOID (reset_memory_regions)
        p != (lang_memory_region_type *) NULL;
        p = p->next)
     {
+      p->old_length = (bfd_size_type) (p->current - p->origin);
       p->current = p->origin;
     }
 }
 
-
-asymbol *
-DEFUN (create_symbol, (name, flags, section),
-       CONST char *name AND
-       flagword flags AND
-       asection * section)
-{
-  extern lang_input_statement_type *script_file;
-  asymbol **def_ptr = (asymbol **) stat_alloc ((bfd_size_type) (sizeof (asymbol **)));
-
-  /* Add this definition to script file */
-  asymbol *def = (asymbol *) bfd_make_empty_symbol (script_file->the_bfd);
-
-  def->name = buystring (name);
-  def->udata = 0;
-  def->flags = flags;
-  def->section = section;
-
-  *def_ptr = def;
-  Q_enter_global_ref (def_ptr, name);
-  return def;
-}
-
 void
-DEFUN_VOID (lang_process)
+lang_process ()
 {
-
-  if (had_script == false)
-    {
-      parse_line (ldemul_get_script (), 1);
-    }
   lang_reasonable_defaults ();
   current_target = default_target;
 
   lang_for_each_statement (ldlang_open_output);        /* Open the output file */
-  /* For each output section statement, create a section in the output
-     file */
-  lang_create_output_section_statements ();
 
-  /* Create a dummy bfd for the script */
-  lang_init_script_file ();
+  ldemul_create_output_section_statements ();
 
   /* Add to the hash table all undefineds on the command line */
   lang_place_undefineds ();
@@ -2281,13 +2502,16 @@ DEFUN_VOID (lang_process)
   current_target = default_target;
   lang_for_each_statement (open_input_bfds);
 
-  common_section.userdata = (PTR) & common_section_userdata;
+  /* Build all sets based on the information gathered from the input
+     files.  */
+  ldctor_build_sets ();
 
+  /* Size up the common data */
+  lang_common ();
 
   /* Run through the contours of the script and attatch input sections
      to the correct output sections
      */
-  find_constructors ();
   map_input_to_output_sections (statement_list.head, (char *) NULL,
                                (lang_output_section_statement_type *) NULL);
 
@@ -2295,50 +2519,49 @@ DEFUN_VOID (lang_process)
   /* Find any sections not attatched explicitly and handle them */
   lang_place_orphans ();
 
-  /* Size up the common data */
-  lang_common ();
-
   ldemul_before_allocation ();
 
-
-  /* Size up the sections */
-  lang_size_sections (statement_list.head,
-                     abs_output_section,
-                     &(statement_list.head), 0, (bfd_vma) 0, false);
-
-
   /* Now run around and relax if we can */
   if (command_line.relax)
     {
-      reset_memory_regions ();
+      /* First time round is a trial run to get the 'worst case'
+        addresses of the objects if there was no relaxing.  */
+      lang_size_sections (statement_list.head,
+                         abs_output_section,
+                         &(statement_list.head), 0, (bfd_vma) 0, false);
 
-      /* Move the global symbols around */
-      lang_relocate_globals ();
 
-      had_relax = true;
-      while (had_relax)
+      reset_memory_regions ();
+
+      /* Keep relaxing until bfd_relax_section gives up.  */
+      do
        {
+         relax_again = false;
 
-         had_relax = false;
+         /* Do all the assignments with our current guesses as to
+            section sizes.  */
+         lang_do_assignments (statement_list.head,
+                              abs_output_section,
+                              (fill_type) 0, (bfd_vma) 0);
 
+         /* Perform another relax pass - this time we know where the
+            globals are, so can make better guess.  */
          lang_size_sections (statement_list.head,
-                             (lang_output_section_statement_type *) NULL,
+                             abs_output_section,
                              &(statement_list.head), 0, (bfd_vma) 0, true);
-         /* FIXME. Until the code in relax is fixed so that it only reads in
-            stuff once, we cant iterate since there is no way for the linker to
-            know what has been patched and what hasn't */
-         break;
-
        }
-
-
-
-
+      while (relax_again);
+    }
+  else
+    {
+      /* Size up the sections.  */
+      lang_size_sections (statement_list.head,
+                         abs_output_section,
+                         &(statement_list.head), 0, (bfd_vma) 0, false);
     }
-
 
   /* See if anything special should be done now we know how big
-     everything is */
+     everything is */
   ldemul_after_allocation ();
 
   /* Do all the assignments, now that we know the final restingplaces
@@ -2346,26 +2569,24 @@ DEFUN_VOID (lang_process)
 
   lang_do_assignments (statement_list.head,
                       abs_output_section,
-                      0, (bfd_vma) 0);
-
-
-  /* Move the global symbols around */
-  lang_relocate_globals ();
+                      (fill_type) 0, (bfd_vma) 0);
 
   /* Make sure that we're not mixing architectures */
 
   lang_check ();
 
   /* Final stuffs */
+
+  ldemul_finish ();
   lang_finish ();
 }
 
 /* EXPORTED TO YACC */
 
 void
-DEFUN (lang_add_wild, (section_name, filename),
-       CONST char *CONST section_name AND
-       CONST char *CONST filename)
+lang_add_wild (section_name, filename)
+     CONST char *CONST section_name;
+     CONST char *CONST filename;
 {
   lang_wild_statement_type *new = new_stat (lang_wild_statement,
                                            stat_ptr);
@@ -2384,9 +2605,9 @@ DEFUN (lang_add_wild, (section_name, filename),
 }
 
 void
-DEFUN (lang_section_start, (name, address),
-       CONST char *name AND
-       etree_type * address)
+lang_section_start (name, address)
+     CONST char *name;
+     etree_type * address;
 {
   lang_address_statement_type *ad = new_stat (lang_address_statement, stat_ptr);
 
@@ -2394,16 +2615,30 @@ DEFUN (lang_section_start, (name, address),
   ad->address = address;
 }
 
+/* Set the start symbol to NAME.  CMDLINE is nonzero if this is called
+   because of a -e argument on the command line, or zero if this is
+   called by ENTRY in a linker script.  Command line arguments take
+   precedence.  */
+
 void
-DEFUN (lang_add_entry, (name),
-       CONST char *name)
+lang_add_entry (name, cmdline)
+     CONST char *name;
+     int cmdline;
 {
-  entry_symbol = name;
+  static int from_cmdline;
+
+  if (entry_symbol == NULL
+      || cmdline
+      || ! from_cmdline)
+    {
+      entry_symbol = name;
+      from_cmdline = cmdline;
+    }
 }
 
 void
-DEFUN (lang_add_target, (name),
-       CONST char *name)
+lang_add_target (name)
+     CONST char *name;
 {
   lang_target_statement_type *new = new_stat (lang_target_statement,
                                              stat_ptr);
@@ -2413,8 +2648,8 @@ DEFUN (lang_add_target, (name),
 }
 
 void
-DEFUN (lang_add_map, (name),
-       CONST char *name)
+lang_add_map (name)
+     CONST char *name;
 {
   while (*name)
     {
@@ -2429,8 +2664,8 @@ DEFUN (lang_add_map, (name),
 }
 
 void
-DEFUN (lang_add_fill, (exp),
-       int exp)
+lang_add_fill (exp)
+     int exp;
 {
   lang_fill_statement_type *new = new_stat (lang_fill_statement,
                                            stat_ptr);
@@ -2439,9 +2674,9 @@ DEFUN (lang_add_fill, (exp),
 }
 
 void
-DEFUN (lang_add_data, (type, exp),
-       int type AND
-       union etree_union *exp)
+lang_add_data (type, exp)
+     int type;
+     union etree_union *exp;
 {
 
   lang_data_statement_type *new = new_stat (lang_data_statement,
@@ -2452,9 +2687,37 @@ DEFUN (lang_add_data, (type, exp),
 
 }
 
+/* Create a new reloc statement.  RELOC is the BFD relocation type to
+   generate.  HOWTO is the corresponding howto structure (we could
+   look this up, but the caller has already done so).  SECTION is the
+   section to generate a reloc against, or NAME is the name of the
+   symbol to generate a reloc against.  Exactly one of SECTION and
+   NAME must be NULL.  ADDEND is an expression for the addend.  */
+
+void
+lang_add_reloc (reloc, howto, section, name, addend)
+     bfd_reloc_code_real_type reloc;
+     const reloc_howto_type *howto;
+     asection *section;
+     const char *name;
+     union etree_union *addend;
+{
+  lang_reloc_statement_type *p = new_stat (lang_reloc_statement, stat_ptr);
+  
+  p->reloc = reloc;
+  p->howto = howto;
+  p->section = section;
+  p->name = name;
+  p->addend_exp = addend;
+
+  p->addend_value = 0;
+  p->output_section = NULL;
+  p->output_vma = 0;
+}
+
 void
-DEFUN (lang_add_assignment, (exp),
-       etree_type * exp)
+lang_add_assignment (exp)
+     etree_type * exp;
 {
   lang_assignment_statement_type *new = new_stat (lang_assignment_statement,
                                                  stat_ptr);
@@ -2463,49 +2726,42 @@ DEFUN (lang_add_assignment, (exp),
 }
 
 void
-DEFUN (lang_add_attribute, (attribute),
-       enum statement_enum attribute)
+lang_add_attribute (attribute)
+     enum statement_enum attribute;
 {
   new_statement (attribute, sizeof (lang_statement_union_type), stat_ptr);
 }
 
 void
-DEFUN (lang_startup, (name),
-       CONST char *name)
+lang_startup (name)
+     CONST char *name;
 {
   if (startup_file != (char *) NULL)
     {
-      einfo ("%P%FMultiple STARTUP files\n");
+      einfo ("%P%Fmultiple STARTUP files\n");
     }
   first_file->filename = name;
   first_file->local_sym_name = name;
+  first_file->real = true;
 
   startup_file = name;
 }
 
 void
-DEFUN (lang_float, (maybe),
-       boolean maybe)
+lang_float (maybe)
+     boolean maybe;
 {
   lang_float_flag = maybe;
 }
 
 void
-DEFUN (lang_leave_output_section_statement, (fill, memspec),
-       bfd_vma fill AND
-       CONST char *memspec)
+lang_leave_output_section_statement (fill, memspec)
+     bfd_vma fill;
+     CONST char *memspec;
 {
   current_section->fill = fill;
   current_section->region = lang_memory_region_lookup (memspec);
   stat_ptr = &statement_list;
-
-  /* We remember if we are closing a .data section, since we use it to
-     store constructors in */
-  if (strcmp (current_section->name, ".data") == 0)
-    {
-      end_of_data_section_statement_list = statement_list;
-
-    }
 }
 
 /*
@@ -2515,25 +2771,30 @@ DEFUN (lang_leave_output_section_statement, (fill, memspec),
  If the symbol already exists, then do nothing.
 */
 void
-DEFUN (lang_abs_symbol_at_beginning_of, (section, name),
-       CONST char *section AND
-       CONST char *name)
+lang_abs_symbol_at_beginning_of (secname, name)
+     const char *secname;
+     const char *name;
 {
-  if (ldsym_undefined (name))
+  struct bfd_link_hash_entry *h;
+
+  h = bfd_link_hash_lookup (link_info.hash, name, true, true, true);
+  if (h == (struct bfd_link_hash_entry *) NULL)
+    einfo ("%P%F: bfd_link_hash_lookup failed: %E\n");
+
+  if (h->type == bfd_link_hash_new
+      || h->type == bfd_link_hash_undefined)
     {
-      asection *s = bfd_get_section_by_name (output_bfd, section);
-      asymbol *def = create_symbol (name,
-                                   BSF_GLOBAL | BSF_EXPORT,
-                                   &bfd_abs_section);
+      asection *sec;
 
-      if (s != (asection *) NULL)
-       {
-         def->value = s->vma;
-       }
+      h->type = bfd_link_hash_defined;
+
+      sec = bfd_get_section_by_name (output_bfd, secname);
+      if (sec == (asection *) NULL)
+       h->u.def.value = 0;
       else
-       {
-         def->value = 0;
-       }
+       h->u.def.value = bfd_get_section_vma (output_bfd, sec);
+
+      h->u.def.section = bfd_abs_section_ptr;
     }
 }
 
@@ -2544,44 +2805,50 @@ DEFUN (lang_abs_symbol_at_beginning_of, (section, name),
  If the symbol already exists, then do nothing.
 */
 void
-DEFUN (lang_abs_symbol_at_end_of, (section, name),
-       CONST char *section AND
-       CONST char *name)
+lang_abs_symbol_at_end_of (secname, name)
+     const char *secname;
+     const char *name;
 {
-  if (ldsym_undefined (name))
+  struct bfd_link_hash_entry *h;
+
+  h = bfd_link_hash_lookup (link_info.hash, name, true, true, true);
+  if (h == (struct bfd_link_hash_entry *) NULL)
+    einfo ("%P%F: bfd_link_hash_lookup failed: %E\n");
+
+  if (h->type == bfd_link_hash_new
+      || h->type == bfd_link_hash_undefined)
     {
-      asection *s = bfd_get_section_by_name (output_bfd, section);
+      asection *sec;
 
-      /* Add a symbol called _end */
-      asymbol *def = create_symbol (name,
-                                   BSF_GLOBAL | BSF_EXPORT,
-                                   &bfd_abs_section);
+      h->type = bfd_link_hash_defined;
 
-      if (s != (asection *) NULL)
-       {
-         def->value = s->vma + s->_raw_size;
-       }
+      sec = bfd_get_section_by_name (output_bfd, secname);
+      if (sec == (asection *) NULL)
+       h->u.def.value = 0;
       else
-       {
-         def->value = 0;
-       }
+       h->u.def.value = (bfd_get_section_vma (output_bfd, sec)
+                         + bfd_section_size (output_bfd, sec));
+
+      h->u.def.section = bfd_abs_section_ptr;
     }
 }
 
 void
-DEFUN (lang_statement_append, (list, element, field),
-       lang_statement_list_type * list AND
-       lang_statement_union_type * element AND
-       lang_statement_union_type ** field)
+lang_statement_append (list, element, field)
+     lang_statement_list_type * list;
+     lang_statement_union_type * element;
+     lang_statement_union_type ** field;
 {
   *(list->tail) = element;
   list->tail = field;
 }
 
-/* Set the output format type */
+/* Set the output format type.  -oformat overrides scripts.  */
 void
-DEFUN (lang_add_output_format, (format),
-       CONST char *format)
+lang_add_output_format (format, from_script)
+     CONST char *format;
+     int from_script;
 {
-  output_target = format;
+  if (output_target == NULL || !from_script)
+    output_target = format;
 }