Initial revision
authorSteve Chamberlain <sac@cygnus>
Tue, 26 Nov 1991 02:16:53 +0000 (02:16 +0000)
committerSteve Chamberlain <sac@cygnus>
Tue, 26 Nov 1991 02:16:53 +0000 (02:16 +0000)
gas/config/obj-coff-bfd.c [new file with mode: 0755]
gas/config/obj-coff-bfd.h [new file with mode: 0755]

diff --git a/gas/config/obj-coff-bfd.c b/gas/config/obj-coff-bfd.c
new file mode 100755 (executable)
index 0000000..ed25683
--- /dev/null
@@ -0,0 +1,2184 @@
+
+/* coff object file format
+   Copyright (C) 1989, 1990, 1991 Free Software Foundation, Inc.
+
+This file is part of GAS.
+
+GAS is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GAS is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GAS; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/*
+
+ How does this releate to the rest of GAS ?
+
+ Well, all the other files in gas are more or less a black box. It
+ takes care of openning files, parsing command lines, stripping blanks
+ etc etc. This module gets a chance to register what it wants to do by
+ saying that it is interested in various pseduo ops. The other big
+ change is write_object_file. This runs through all the data
+ structures that gas builds, and outputs the file in the format of our
+ choice.
+
+ Hacked for BFDness by steve chamberlain
+ sac@cygnus.com
+*/
+
+#include "as.h"
+#include "obstack.h"
+#include "subsegs.h"
+#include "frags.h"
+
+
+
+
+
+/* This vector is used to turn an internal segment into a section #
+   suitable for insertion into a coff symbol table 
+*/
+
+const short seg_N_TYPE[] = { /* in: segT   out: N_TYPE bits */
+       C_ABS_SECTION,
+       1,
+       2,
+       3,
+       4,
+       5,
+       6,
+       7,
+       8,
+       9,
+       10,
+       C_UNDEF_SECTION,                /* SEG_UNKNOWN */
+       C_UNDEF_SECTION,                /* SEG_ABSENT */
+       C_UNDEF_SECTION,                /* SEG_PASS1 */
+       C_UNDEF_SECTION,                /* SEG_GOOF */
+       C_UNDEF_SECTION,                /* SEG_BIG */
+       C_UNDEF_SECTION,                /* SEG_DIFFERENCE */
+       C_DEBUG_SECTION,                /* SEG_DEBUG */
+       C_NTV_SECTION,          /* SEG_NTV */
+       C_PTV_SECTION,          /* SEG_PTV */
+       C_REGISTER_SECTION,     /* SEG_REGISTER */
+};
+
+int function_lineoff = -1;     /* Offset in line#s where the last function
+                                  started (the odd entry for line #0) */
+
+int our_lineno_number = 0;     /* we use this to build pointers from .bf's
+                                  into the linetable.  It should match
+                                  exactly the values that are later
+                                  assigned in text_lineno_number by
+                                  write.c. */
+
+int text_lineno_number = 0;
+
+/* Add 4 to the real value to get the index and compensate the
+   negatives. This vector is used by S_GET_SEGMENT to turn a coff
+   section number into a segment number 
+*/
+static symbolS *previous_file_symbol = NULL;
+void c_symbol_merge();
+
+symbolS *c_section_symbol();
+bfd *abfd;
+void EXFUN(bfd_as_write_hook,(struct internal_filehdr *,
+                             bfd *abfd));
+
+static void EXFUN(fill_section,(bfd *abfd ,
+                               struct internal_filehdr *f, unsigned
+                               long *));
+
+
+char *EXFUN(s_get_name,(symbolS *s));
+static symbolS *EXFUN(tag_find_or_make,(char *name));
+static symbolS* EXFUN(tag_find,(char *name));
+
+
+static void EXFUN(w_symbols,(
+bfd *abfd ,
+char **where ,
+                       symbolS *symbol_rootP));
+
+
+
+static void EXFUN( obj_coff_def,(int what));
+static void EXFUN( obj_coff_lcomm,(void));
+static void EXFUN( obj_coff_dim,(void));
+static void EXFUN( obj_coff_text,(void));
+static void EXFUN( obj_coff_data,(void));
+static void EXFUN( obj_coff_endef,(void));
+static void EXFUN( obj_coff_line,(void));
+static void EXFUN( obj_coff_ln,(void));
+static void EXFUN( obj_coff_scl,(void));
+static void EXFUN( obj_coff_size,(void));
+static void EXFUN( obj_coff_stab,(int what));
+static void EXFUN( obj_coff_tag,(void));
+static void EXFUN( obj_coff_type,(void));
+static void EXFUN( obj_coff_val,(void));
+static void EXFUN( obj_coff_section,(void));
+static void EXFUN( tag_init,(void));
+static void EXFUN( tag_insert,(char *name, symbolS *symbolP));
+
+
+static struct hash_control *tag_hash;
+static symbolS *def_symbol_in_progress = NULL;
+
+const pseudo_typeS obj_pseudo_table[] = {
+       { "def",        obj_coff_def,           0       },
+       { "dim",        obj_coff_dim,           0       },
+       { "endef",      obj_coff_endef,         0       },
+       { "line",       obj_coff_line,          0       },
+       { "ln",         obj_coff_ln,            0       },
+       { "scl",        obj_coff_scl,           0       },
+       { "size",       obj_coff_size,          0       },
+       { "tag",        obj_coff_tag,           0       },
+       { "type",       obj_coff_type,          0       },
+       { "val",        obj_coff_val,           0       },
+        { "section",    obj_coff_section,       0       },
+        { "text",    obj_coff_text,       0       },
+        { "data",    obj_coff_data,       0       },
+
+       { "ident",      s_ignore,               0 }, /* we don't yet handle this. */
+       { "ABORT",      s_abort,                0 },
+       { "lcomm",      obj_coff_lcomm, 0},
+       { NULL} /* end sentinel */
+}; /* obj_pseudo_table */
+
+
+
+/* Section stuff 
+
+   We allow more than just the standard 3 sections, infact, we allow
+   10 sections, (though the usual three have to be there).
+
+   This structure performs the mappings for us:
+
+*/
+
+/* OBS stuff 
+static struct internal_scnhdr bss_section_header;
+struct internal_scnhdr data_section_header;
+struct internal_scnhdr text_section_header;
+
+const segT N_TYPE_seg [32] =
+{
+
+};
+
+*/
+
+#define N_SEG 32
+typedef struct 
+{
+  segT seg_t;  
+int i;  
+} seg_info_type;
+
+seg_info_type seg_info_off_by_4[N_SEG] = 
+{
+{SEG_PTV,  },
+{SEG_NTV,  },
+{SEG_DEBUG, },
+{SEG_ABSOLUTE,  },
+{SEG_UNKNOWN,   },
+{SEG_E0}, 
+{SEG_E1},
+{SEG_E2},
+{SEG_E3},
+{SEG_E4},
+{SEG_E5},
+{SEG_E6},
+{SEG_E7},
+{SEG_E8}, 
+{SEG_E9},
+{SEG_REGISTER},
+
+};
+
+#define SEG_INFO_FROM_SECTION_NUMBER(x) (seg_info_off_by_4[(x)+4])
+#define SEG_INFO_FROM_SEG_NUMBER(x) (seg_info_off_by_4[(x)])
+
+
+static relax_addressT 
+DEFUN(relax_align,(address, alignment),
+register relax_addressT address AND
+register long alignment )
+{
+  relax_addressT       mask;
+  relax_addressT       new_address;
+
+  mask = ~ ( (~0) << alignment );
+  new_address = (address + mask) & (~ mask);
+  return (new_address - address);
+} /* relax_align() */
+
+
+segT 
+DEFUN(s_get_segment,(x) ,
+symbolS* x)
+{
+  return SEG_INFO_FROM_SECTION_NUMBER(x->sy_symbol.ost_entry.n_scnum).seg_t;
+}
+
+
+
+/* calculate the size of the frag chain and fill in the section header
+   to contain all of it, also fill in the addr of the sections */
+static unsigned int  DEFUN(size_section,(abfd, idx),
+                 bfd *abfd AND
+                 unsigned int idx)
+{
+  asection *sec;
+  unsigned int size = 0;
+  fragS *frag = segment_info[idx].frag_root;
+  while (frag) {
+      if (frag->fr_address != size) {  
+         printf("Out of step\n");
+         size = frag->fr_address;
+       }
+      size += frag->fr_fix;
+      switch (frag->fr_type) {
+       case rs_fill:
+       case rs_org:
+         size  +=    frag->fr_offset * frag->fr_var;
+         break;
+       case rs_align:
+         size  +=   relax_align(size, frag->fr_offset);
+       }
+      frag = frag->fr_next;
+    }
+  segment_info[idx].scnhdr.s_size = size;
+  return size;
+}
+
+/* Count the relocations in a chain */
+
+static unsigned int DEFUN(count_entries_in_chain,(idx),
+                         unsigned int idx)
+{
+  unsigned int nrelocs;
+  fixS *fixup_ptr;
+
+  /* Count the relocations */
+  fixup_ptr = segment_info[idx].fix_root;
+  nrelocs = 0;
+  while (fixup_ptr != (fixS *)NULL) 
+      {
+       nrelocs ++ ;
+       fixup_ptr = fixup_ptr->fx_next;
+
+      }
+  return nrelocs;
+}
+
+/* output all the relocations for a section */
+void DEFUN(do_relocs_for,(abfd, file_cursor),
+          bfd *abfd AND
+          unsigned long *file_cursor)
+{
+  unsigned int nrelocs;
+  arelent **reloc_ptr_vector;
+  arelent *reloc_vector;
+  asymbol **ptrs;
+  unsigned int idx;
+  
+  asection *section = (asection *)(segment_info[idx].user_stuff);
+  unsigned int i;
+  fixS *from;
+  for (idx = SEG_E0; idx < SEG_E9; idx++) 
+  {
+    if (segment_info[idx].scnhdr.s_name[0]) 
+    {
+
+      struct external_reloc *ext_ptr;
+      struct external_reloc *external_reloc_vec;
+      unsigned int external_reloc_size;
+      fixS *   fix_ptr = segment_info[idx].fix_root;
+      nrelocs = count_entries_in_chain(idx);
+      external_reloc_size = nrelocs * RELSZ;
+      external_reloc_vec = (struct external_reloc*)alloca(external_reloc_size);
+
+      ext_ptr = external_reloc_vec;
+      
+      /* Fill in the internal coff style reloc struct from the
+        internal fix list */
+      while (fix_ptr)
+      {
+       symbolS *symbol_ptr;
+       struct internal_reloc intr;
+       
+       symbol_ptr = fix_ptr->fx_addsy;
+
+         /* If this relocation is attached to a symbol then it's ok
+            to output it */
+         intr.r_type = TC_COFF_FIX2RTYPE(fix_ptr);
+         intr.r_vaddr = fix_ptr->fx_frag->fr_address +  fix_ptr->fx_where ;
+         
+         intr.r_offset = fix_ptr->fx_offset;
+         
+       if (symbol_ptr)
+         intr.r_symndx = symbol_ptr->sy_number;
+       else
+        intr.r_symndx = -1;
+       
+         (void)bfd_coff_swap_reloc_out(abfd, &intr, ext_ptr);
+         ext_ptr++;
+
+       fix_ptr = fix_ptr->fx_next;
+      }
+      
+      /* Write out the reloc table */
+      segment_info[idx].scnhdr.s_relptr = *file_cursor;
+      segment_info[idx].scnhdr.s_nreloc = nrelocs;
+      bfd_write(external_reloc_vec, 1, external_reloc_size, abfd);
+      *file_cursor += external_reloc_size;
+    }
+  }
+}
+
+
+/* run through a frag chain and write out the data to go with it, fill
+   in the scnhdrs with the info on the file postions 
+*/
+static void DEFUN(fill_section,(abfd, filehdr, file_cursor),
+                 bfd *abfd AND
+                 struct internal_filehdr *filehdr AND
+                 unsigned long *file_cursor)
+{
+
+  unsigned int i;
+  unsigned int paddr = 0;
+  
+  for (i = SEG_E0; i < SEG_UNKNOWN; i++) {  
+      unsigned int offset = 0;
+
+      struct internal_scnhdr *s = &( segment_info[i].scnhdr);
+         
+      if (s->s_name[0]) {
+         fragS *frag = segment_info[i].frag_root;
+         char *buffer =  alloca(s->s_size);
+         s->s_scnptr = *file_cursor;
+         s->s_paddr =  paddr;
+         s->s_vaddr =  paddr;
+
+         s->s_flags = STYP_REG;
+         if (strcmp(s->s_name,".text")==0)
+          s->s_flags |= STYP_TEXT;
+         else if (strcmp(s->s_name,".data")==0)
+          s->s_flags |= STYP_DATA;
+         else if (strcmp(s->s_name,".text")==0)
+          s->s_flags |= STYP_BSS | STYP_NOLOAD;
+
+
+         while (frag) {
+             unsigned int fill_size;
+             unsigned int count;
+             switch (frag->fr_type) {
+               case rs_fill:
+               case rs_align:
+               case rs_org:
+                 if(frag->fr_fix) 
+                 {
+                   memcpy(buffer + frag->fr_address,
+                          frag->fr_literal,
+                          frag->fr_fix);
+                   offset += frag->fr_fix;
+                 }
+
+                 fill_size = frag->fr_var;
+                 if (fill_size)        
+                 {
+                   unsigned int off = frag->fr_fix;
+                   for (count = frag->fr_offset; count;  count--) 
+                   {
+                     memcpy(buffer +  frag->fr_address  + off,
+                            frag->fr_literal + frag->fr_fix,
+                            fill_size);
+                     off += fill_size;
+                     offset += fill_size;
+                     
+                   }
+
+                 }
+                 break;
+               default:        
+                 abort();
+               }
+             frag = frag->fr_next;
+           }
+
+         /*paddr += offset; 
+          This causes problems with relocation. For the moment, all
+          sections start at 0
+          */
+         bfd_write(buffer, s->s_size,1,abfd);
+         *file_cursor += s->s_size;
+       }      
+    }
+}
+
+
+
+/* Coff file generation & utilities */
+
+
+static void 
+DEFUN(obj_header_append,(abfd, filehdr, aouthdr),
+      bfd *abfd AND
+      struct internal_filehdr *filehdr AND
+      struct internal_aouthdr *aouthdr)
+{
+  unsigned int i;
+  char buffer[1000];
+  char buffero[1000];
+
+  bfd_seek(abfd, 0, 0);
+#if 0  
+  filehdr.f_opthdr = bfd_coff_swap_aouthdr_out(abfd, aouthdr,
+                                              buffero);
+#else
+  filehdr->f_opthdr = 0;
+#endif
+  i = bfd_coff_swap_filehdr_out(abfd, filehdr, buffer);
+
+  bfd_write(buffer, i ,1, abfd);
+  bfd_write(buffero, filehdr->f_opthdr, 1, abfd);
+
+  for (i = SEG_E0; i < SEG_E9; i++) 
+  {
+    if (segment_info[i].scnhdr.s_name[0]) 
+    {  
+      unsigned int size =
+       bfd_coff_swap_scnhdr_out(abfd,
+                               &(segment_info[i].scnhdr),
+                               buffer);
+      bfd_write(buffer, size, 1, abfd);
+    }
+  }
+}
+
+
+void 
+DEFUN(symbol_to_chars,(abfd, where, symbolP),
+      bfd*abfd AND
+      char **where AND
+      symbolS *symbolP)
+{
+  unsigned int numaux = symbolP->sy_symbol.ost_entry.n_numaux;
+  unsigned int i;
+
+  /* Turn any symbols with register attributes into abs symbols */
+  if (S_GET_SEGMENT(symbolP) == SEG_REGISTER) 
+  {
+    S_SET_SEGMENT(symbolP, SEG_ABSOLUTE);
+  }
+  *where += bfd_coff_swap_sym_out(abfd, &symbolP->sy_symbol.ost_entry,
+                                 *where);
+       
+  for (i = 0; i < numaux; i++) 
+  {
+    *where += bfd_coff_swap_aux_out(abfd,
+                                   &symbolP->sy_symbol.ost_auxent[i],
+                                   S_GET_DATA_TYPE(symbolP),
+                                   S_GET_STORAGE_CLASS(symbolP),
+                                   *where);
+  }
+} 
+
+
+
+
+void obj_symbol_new_hook(symbolP)
+symbolS *symbolP;
+{
+       char underscore = 0;      /* Symbol has leading _ */
+
+       /* Effective symbol */
+       /* Store the pointer in the offset. */
+       S_SET_ZEROES(symbolP, 0L);
+       S_SET_DATA_TYPE(symbolP, T_NULL);
+       S_SET_STORAGE_CLASS(symbolP, 0);
+       S_SET_NUMBER_AUXILIARY(symbolP, 0);
+       /* Additional information */
+       symbolP->sy_symbol.ost_flags = 0;
+       /* Auxiliary entries */
+       bzero((char*)&symbolP->sy_symbol.ost_auxent[0], AUXESZ);
+
+#ifdef STRIP_UNDERSCORE
+       /* Remove leading underscore at the beginning of the symbol.
+        * This is to be compatible with the standard librairies.
+        */
+       if (*S_GET_NAME(symbolP) == '_') {
+               underscore = 1;
+               S_SET_NAME(symbolP, S_GET_NAME(symbolP) + 1);
+       } /* strip underscore */
+#endif /* STRIP_UNDERSCORE */
+
+       if (S_IS_STRING(symbolP))
+           SF_SET_STRING(symbolP);
+       if (!underscore && S_IS_LOCAL(symbolP))
+           SF_SET_LOCAL(symbolP);
+
+       return;
+} /* obj_symbol_new_hook() */
+
+ /* stack stuff */
+stack* stack_init(chunk_size, element_size)
+unsigned long chunk_size;
+unsigned long element_size;
+{
+       stack* st;
+
+       if ((st = (stack*)malloc(sizeof(stack))) == (stack*)0)
+           return (stack*)0;
+       if ((st->data = malloc(chunk_size)) == (char*)0) {
+               free(st);
+               return (stack*)0;
+       }
+       st->pointer = 0;
+       st->size = chunk_size;
+       st->chunk_size = chunk_size;
+       st->element_size = element_size;
+       return st;
+} /* stack_init() */
+
+void stack_delete(st)
+stack* st;
+{
+    free(st->data);
+    free(st);
+}
+
+char *stack_push(st, element)
+stack *st;
+char *element;
+{
+       if (st->pointer + st->element_size >= st->size) {
+               st->size += st->chunk_size;
+               if ((st->data = xrealloc(st->data, st->size)) == (char*)0)
+                   return (char*)0;
+       }
+       memcpy(st->data + st->pointer, element, st->element_size);
+       st->pointer += st->element_size;
+       return st->data + st->pointer;
+} /* stack_push() */
+
+char* stack_pop(st)
+stack* st;
+{
+    if ((st->pointer -= st->element_size) < 0) {
+       st->pointer = 0;
+       return (char*)0;
+    }
+    return st->data + st->pointer;
+}
+
+char* stack_top(st)
+stack* st;
+{
+    return st->data + st->pointer - st->element_size;
+}
+
+
+/*
+ * Handle .ln directives.
+ */
+
+static void obj_coff_ln() {
+       if (def_symbol_in_progress != NULL) {
+               as_warn(".ln pseudo-op inside .def/.endef: ignored.");
+               demand_empty_rest_of_line();
+               return;
+       } /* wrong context */
+
+       c_line_new(0,
+                  obstack_next_free(&frags) - frag_now->fr_literal,
+                  get_absolute_expression(),
+                  frag_now);
+
+       demand_empty_rest_of_line();
+       return;
+} /* obj_coff_line() */
+
+/*
+ *                     def()
+ *
+ * Handle .def directives.
+ *
+ * One might ask : why can't we symbol_new if the symbol does not
+ * already exist and fill it with debug information.  Because of
+ * the C_EFCN special symbol. It would clobber the value of the
+ * function symbol before we have a chance to notice that it is
+ * a C_EFCN. And a second reason is that the code is more clear this
+ * way. (at least I think it is :-).
+ *
+ */
+
+#define SKIP_SEMI_COLON()      while (*input_line_pointer++ != ';')
+#define SKIP_WHITESPACES()     while (*input_line_pointer == ' ' || \
+                                     *input_line_pointer == '\t') \
+                                         input_line_pointer++;
+
+static void obj_coff_def(what)
+int what;
+{
+    char name_end; /* Char after the end of name */
+    char *symbol_name; /* Name of the debug symbol */
+    char *symbol_name_copy; /* Temporary copy of the name */
+    unsigned int symbol_name_length;
+    /*$char*   directiveP;$ */         /* Name of the pseudo opcode */
+    /*$char directive[MAX_DIRECTIVE];$ */ /* Backup of the directive */
+    /*$char end = 0;$ */ /* If 1, stop parsing */
+
+    if (def_symbol_in_progress != NULL) {
+       as_warn(".def pseudo-op used inside of .def/.endef: ignored.");
+       demand_empty_rest_of_line();
+       return;
+    } /* if not inside .def/.endef */
+
+    SKIP_WHITESPACES();
+
+    def_symbol_in_progress = (symbolS *) obstack_alloc(&notes, sizeof(*def_symbol_in_progress));
+    bzero(def_symbol_in_progress, sizeof(*def_symbol_in_progress));
+
+    symbol_name = input_line_pointer;
+    name_end = get_symbol_end();
+    symbol_name_length = strlen(symbol_name);
+    symbol_name_copy = xmalloc(symbol_name_length + 1);
+    strcpy(symbol_name_copy, symbol_name);
+
+    /* Initialize the new symbol */
+#ifdef STRIP_UNDERSCORE
+    S_SET_NAME(def_symbol_in_progress, (*symbol_name_copy == '_'
+                                       ? symbol_name_copy + 1
+                                       : symbol_name_copy));
+#else /* STRIP_UNDERSCORE */
+    S_SET_NAME(def_symbol_in_progress, symbol_name_copy);
+#endif /* STRIP_UNDERSCORE */
+    /* free(symbol_name_copy); */
+    def_symbol_in_progress->sy_name_offset = ~0;
+    def_symbol_in_progress->sy_number = ~0;
+    def_symbol_in_progress->sy_frag = &zero_address_frag;
+
+    if (S_IS_STRING(def_symbol_in_progress)) {
+       SF_SET_STRING(def_symbol_in_progress);
+    } /* "long" name */
+
+    *input_line_pointer = name_end;
+
+    demand_empty_rest_of_line();
+    return;
+} /* obj_coff_def() */
+
+unsigned int dim_index;
+static void obj_coff_endef() {
+       symbolS *symbolP;
+/* DIM BUG FIX sac@cygnus.com */
+       dim_index =0;
+       if (def_symbol_in_progress == NULL) {
+               as_warn(".endef pseudo-op used outside of .def/.endef: ignored.");
+               demand_empty_rest_of_line();
+               return;
+       } /* if not inside .def/.endef */
+
+       /* Set the section number according to storage class. */
+       switch (S_GET_STORAGE_CLASS(def_symbol_in_progress)) {
+       case C_STRTAG:
+       case C_ENTAG:
+       case C_UNTAG:
+               SF_SET_TAG(def_symbol_in_progress);
+               /* intentional fallthrough */
+       case C_FILE:
+       case C_TPDEF:
+               SF_SET_DEBUG(def_symbol_in_progress);
+               S_SET_SEGMENT(def_symbol_in_progress, SEG_DEBUG);
+               break;
+
+       case C_EFCN:
+               SF_SET_LOCAL(def_symbol_in_progress);   /* Do not emit this symbol. */
+               /* intentional fallthrough */
+       case C_BLOCK:
+               SF_SET_PROCESS(def_symbol_in_progress); /* Will need processing before writing */
+               /* intentional fallthrough */
+       case C_FCN:
+               S_SET_SEGMENT(def_symbol_in_progress, SEG_E0);
+
+               if (def_symbol_in_progress->sy_symbol.ost_entry.n_name[1] == 'b') { /* .bf */
+                       if (function_lineoff < 0) {
+                               fprintf(stderr, "`.bf' symbol without preceding function\n");
+                       } /* missing function symbol */
+                       SA_GET_SYM_LNNOPTR(def_symbol_in_progress) = function_lineoff;
+                       SF_SET_PROCESS(def_symbol_in_progress); /* Will need relocating */
+                       function_lineoff = -1;
+               }
+               break;
+
+#ifdef C_AUTOARG
+       case C_AUTOARG:
+#endif /* C_AUTOARG */
+       case C_AUTO:
+       case C_REG:
+       case C_MOS:
+       case C_MOE:
+       case C_MOU:
+       case C_ARG:
+       case C_REGPARM:
+       case C_FIELD:
+       case C_EOS:
+               SF_SET_DEBUG(def_symbol_in_progress);
+               S_SET_SEGMENT(def_symbol_in_progress, SEG_ABSOLUTE);
+               break;
+
+       case C_EXT:
+       case C_STAT:
+       case C_LABEL:   
+       /* Valid but set somewhere else (s_comm, s_lcomm, colon) */
+               break;
+
+       case C_USTATIC:
+       case C_EXTDEF:
+       case C_ULABEL:
+               as_warn("unexpected storage class %d", S_GET_STORAGE_CLASS(def_symbol_in_progress));
+               break;
+       } /* switch on storage class */
+
+       /* Now that we have built a debug symbol, try to
+          find if we should merge with an existing symbol
+          or not.  If a symbol is C_EFCN or SEG_ABSOLUTE or
+          untagged SEG_DEBUG it never merges. */
+
+       /* Two cases for functions.  Either debug followed
+          by definition or definition followed by debug.
+          For definition first, we will merge the debug
+          symbol into the definition.  For debug first, the
+          lineno entry MUST point to the definition
+          function or else it will point off into space
+          when crawl_symbols() merges the debug
+          symbol into the real symbol.  Therefor, let's
+          presume the debug symbol is a real function
+          reference. */
+
+       /* FIXME-SOON If for some reason the definition
+          label/symbol is never seen, this will probably
+          leave an undefined symbol at link time. */
+
+       if (S_GET_STORAGE_CLASS(def_symbol_in_progress) == C_EFCN
+           || (S_GET_SEGMENT(def_symbol_in_progress) == SEG_DEBUG
+               && !SF_GET_TAG(def_symbol_in_progress))
+           || S_GET_SEGMENT(def_symbol_in_progress) == SEG_ABSOLUTE
+           || (symbolP = symbol_find_base(S_GET_NAME(def_symbol_in_progress), DO_NOT_STRIP)) == NULL) {
+
+               symbol_append(def_symbol_in_progress, symbol_lastP, &symbol_rootP, &symbol_lastP);
+
+       } else {
+               /* This symbol already exists, merge the
+                  newly created symbol into the old one.
+                  This is not mandatory. The linker can
+                  handle duplicate symbols correctly. But I
+                  guess that it save a *lot* of space if
+                  the assembly file defines a lot of
+                  symbols. [loic] */
+
+               /* The debug entry (def_symbol_in_progress)
+                  is merged into the previous definition. */
+
+               c_symbol_merge(def_symbol_in_progress, symbolP);
+               /* FIXME-SOON Should *def_symbol_in_progress be free'd? xoxorich. */
+               def_symbol_in_progress = symbolP;
+
+               if (SF_GET_FUNCTION(def_symbol_in_progress)
+                   || SF_GET_TAG(def_symbol_in_progress)) {
+                       /* For functions, and tags, the symbol *must* be where the debug symbol
+                          appears.  Move the existing symbol to the current place. */
+                       /* If it already is at the end of the symbol list, do nothing */
+                       if (def_symbol_in_progress != symbol_lastP) {
+                               symbol_remove(def_symbol_in_progress, &symbol_rootP, &symbol_lastP);
+                               symbol_append(def_symbol_in_progress, symbol_lastP, &symbol_rootP, &symbol_lastP);
+                       } /* if not already in place */
+               } /* if function */
+       } /* normal or mergable */
+
+       if (SF_GET_TAG(def_symbol_in_progress)
+           && symbol_find_base(S_GET_NAME(def_symbol_in_progress), DO_NOT_STRIP) == NULL) {
+               tag_insert(S_GET_NAME(def_symbol_in_progress), def_symbol_in_progress);
+       } /* If symbol is a {structure,union} tag, associate symbol to its name. */
+
+       if (SF_GET_FUNCTION(def_symbol_in_progress)) {
+               know(sizeof(def_symbol_in_progress) <= sizeof(long));
+               function_lineoff = c_line_new((long) def_symbol_in_progress,0, 0, &zero_address_frag);
+               SF_SET_PROCESS(def_symbol_in_progress);
+
+               if (symbolP == NULL) {
+                       /* That is, if this is the first
+                          time we've seen the function... */
+                       symbol_table_insert(def_symbol_in_progress);
+               } /* definition follows debug */
+       } /* Create the line number entry pointing to the function being defined */
+
+       def_symbol_in_progress = NULL;
+       demand_empty_rest_of_line();
+       return;
+} /* obj_coff_endef() */
+
+static void obj_coff_dim() 
+{
+    register int dim_index;
+
+    if (def_symbol_in_progress == NULL) {
+       as_warn(".dim pseudo-op used outside of .def/.endef: ignored.");
+       demand_empty_rest_of_line();
+       return;
+    } /* if not inside .def/.endef */
+
+    S_SET_NUMBER_AUXILIARY(def_symbol_in_progress, 1);
+
+    for (dim_index = 0; dim_index < DIMNUM; dim_index++) {
+       SKIP_WHITESPACES();
+       SA_SET_SYM_DIMEN(def_symbol_in_progress, dim_index, get_absolute_expression());
+
+       switch (*input_line_pointer) {
+
+          case ',':
+           input_line_pointer++;
+           break;
+
+          default:
+           as_warn("badly formed .dim directive ignored");
+           /* intentional fallthrough */
+          case '\n':
+          case ';':
+           dim_index = DIMNUM;
+           break;
+       } /* switch on following character */
+    } /* for each dimension */
+
+    demand_empty_rest_of_line();
+    return;
+} /* obj_coff_dim() */
+
+static void obj_coff_line() {
+       if (def_symbol_in_progress == NULL) {
+               obj_coff_ln();
+               return;
+       } /* if it looks like a stabs style line */
+
+       S_SET_NUMBER_AUXILIARY(def_symbol_in_progress, 1);
+       SA_SET_SYM_LNNO(def_symbol_in_progress, get_absolute_expression());
+
+       demand_empty_rest_of_line();
+       return;
+} /* obj_coff_line() */
+
+static void obj_coff_size() {
+       if (def_symbol_in_progress == NULL) {
+               as_warn(".size pseudo-op used outside of .def/.endef ignored.");
+               demand_empty_rest_of_line();
+               return;
+       } /* if not inside .def/.endef */
+
+       S_SET_NUMBER_AUXILIARY(def_symbol_in_progress, 1);
+       SA_SET_SYM_SIZE(def_symbol_in_progress, get_absolute_expression());
+       demand_empty_rest_of_line();
+       return;
+} /* obj_coff_size() */
+
+static void obj_coff_scl() {
+       if (def_symbol_in_progress == NULL) {
+               as_warn(".scl pseudo-op used outside of .def/.endef ignored.");
+               demand_empty_rest_of_line();
+               return;
+       } /* if not inside .def/.endef */
+
+       S_SET_STORAGE_CLASS(def_symbol_in_progress, get_absolute_expression());
+       demand_empty_rest_of_line();
+       return;
+} /* obj_coff_scl() */
+
+static void obj_coff_tag() {
+       char *symbol_name;
+       char name_end;
+
+       if (def_symbol_in_progress == NULL) {
+               as_warn(".tag pseudo-op used outside of .def/.endef ignored.");
+               demand_empty_rest_of_line();
+               return;
+       } /* if not inside .def/.endef */
+
+       S_SET_NUMBER_AUXILIARY(def_symbol_in_progress, 1);
+       symbol_name = input_line_pointer;
+       name_end = get_symbol_end();
+
+       /* Assume that the symbol referred to by .tag is always defined. */
+       /* This was a bad assumption.  I've added find_or_make. xoxorich. */
+       SA_SET_SYM_TAGNDX(def_symbol_in_progress, (long) tag_find_or_make(symbol_name));
+       if (SA_GET_SYM_TAGNDX(def_symbol_in_progress) == 0L) {
+               as_warn("tag not found for .tag %s", symbol_name);
+       } /* not defined */
+
+       SF_SET_TAGGED(def_symbol_in_progress);
+       *input_line_pointer = name_end;
+
+       demand_empty_rest_of_line();
+       return;
+} /* obj_coff_tag() */
+
+static void obj_coff_type() {
+       if (def_symbol_in_progress == NULL) {
+               as_warn(".type pseudo-op used outside of .def/.endef ignored.");
+               demand_empty_rest_of_line();
+               return;
+       } /* if not inside .def/.endef */
+
+       S_SET_DATA_TYPE(def_symbol_in_progress, get_absolute_expression());
+
+       if (ISFCN(S_GET_DATA_TYPE(def_symbol_in_progress)) &&
+           S_GET_STORAGE_CLASS(def_symbol_in_progress) != C_TPDEF) {
+               SF_SET_FUNCTION(def_symbol_in_progress);
+       } /* is a function */
+
+       demand_empty_rest_of_line();
+       return;
+} /* obj_coff_type() */
+
+static void obj_coff_val() {
+       if (def_symbol_in_progress == NULL) {
+               as_warn(".val pseudo-op used outside of .def/.endef ignored.");
+               demand_empty_rest_of_line();
+               return;
+       } /* if not inside .def/.endef */
+
+       if (is_name_beginner(*input_line_pointer)) {
+               char *symbol_name = input_line_pointer;
+               char name_end = get_symbol_end();
+
+               if (!strcmp(symbol_name, ".")) {
+                       def_symbol_in_progress->sy_frag = frag_now;
+                       S_SET_VALUE(def_symbol_in_progress, obstack_next_free(&frags) - frag_now->fr_literal);
+                       /* If the .val is != from the .def (e.g. statics) */
+               } else if (strcmp(S_GET_NAME(def_symbol_in_progress), symbol_name)) {
+                       def_symbol_in_progress->sy_forward = symbol_find_or_make(symbol_name);
+
+                       /* If the segment is undefined when the forward
+                          reference is solved, then copy the segment id
+                          from the forward symbol. */
+                       SF_SET_GET_SEGMENT(def_symbol_in_progress);
+               }
+               /* Otherwise, it is the name of a non debug symbol and its value will be calculated later. */
+               *input_line_pointer = name_end;
+       } else {
+               S_SET_VALUE(def_symbol_in_progress, get_absolute_expression());
+       } /* if symbol based */
+
+       demand_empty_rest_of_line();
+       return;
+} /* obj_coff_val() */
+
+/*
+ * Maintain a list of the tagnames of the structres.
+ */
+
+static void tag_init() {
+    tag_hash = hash_new();
+    return ;
+} /* tag_init() */
+
+static void tag_insert(name, symbolP)
+char *name;
+symbolS *symbolP;
+{
+       register char * error_string;
+
+       if (*(error_string = hash_jam(tag_hash, name, (char *)symbolP))) {
+               as_fatal("Inserting \"%s\" into structure table failed: %s",
+                        name, error_string);
+       }
+       return ;
+} /* tag_insert() */
+
+static symbolS *tag_find_or_make(name)
+char *name;
+{
+       symbolS *symbolP;
+
+       if ((symbolP = tag_find(name)) == NULL) {
+               symbolP = symbol_new(name,
+                                    SEG_UNKNOWN,
+                                    0,
+                                    &zero_address_frag);
+
+               tag_insert(S_GET_NAME(symbolP), symbolP);
+               symbol_table_insert(symbolP);
+       } /* not found */
+
+       return(symbolP);
+} /* tag_find_or_make() */
+
+static symbolS *tag_find(name)
+char *name;
+{
+#ifdef STRIP_UNDERSCORE
+       if (*name == '_') name++;
+#endif /* STRIP_UNDERSCORE */
+       return((symbolS*)hash_find(tag_hash, name));
+} /* tag_find() */
+
+void obj_read_begin_hook() {
+ /* These had better be the same.  Usually 18 bytes. */
+#ifndef BFD_HEADERS
+       know(sizeof(SYMENT) == sizeof(AUXENT));
+       know(SYMESZ == AUXESZ);
+#endif
+       tag_init();
+
+       return;
+} /* obj_read_begin_hook() */
+
+/* This function runs through the symbol table and puts all the
+   externals onto another chain */
+
+/* The chain of externals */
+symbolS *symbol_externP = NULL;
+symbolS *symbol_extern_lastP = NULL;
+
+stack*block_stack;
+  symbolS *last_functionP = NULL;
+  symbolS *last_tagP;
+
+
+static unsigned int DEFUN_VOID(yank_symbols)
+{
+  symbolS *symbolP;
+  unsigned int symbol_number =0;
+  
+  for (symbolP = symbol_rootP;
+       symbolP;
+       symbolP = symbolP ? symbol_next(symbolP) : symbol_rootP) {
+      if (!SF_GET_DEBUG(symbolP)) {
+         /* Debug symbols do not need all this rubbish */
+         symbolS* real_symbolP;
+
+         /* L* and C_EFCN symbols never merge. */
+         if (!SF_GET_LOCAL(symbolP)
+             && (real_symbolP = symbol_find_base(S_GET_NAME(symbolP), DO_NOT_STRIP))
+             && real_symbolP != symbolP) {
+             /* FIXME-SOON: where do dups come from?
+                Maybe tag references before definitions? xoxorich. */
+             /* Move the debug data from the debug symbol to the
+                real symbol. Do NOT do the oposite (i.e. move from
+                real symbol to debug symbol and remove real symbol from the
+                list.) Because some pointers refer to the real symbol
+                whereas no pointers refer to the debug symbol. */
+             c_symbol_merge(symbolP, real_symbolP);
+             /* Replace the current symbol by the real one */
+             /* The symbols will never be the last or the first
+                because : 1st symbol is .file and 3 last symbols are
+                .text, .data, .bss */
+             symbol_remove(real_symbolP, &symbol_rootP, &symbol_lastP);
+             symbol_insert(real_symbolP, symbolP, &symbol_rootP, &symbol_lastP);
+             symbol_remove(symbolP, &symbol_rootP, &symbol_lastP);
+             symbolP = real_symbolP;
+           }                   /* if not local but dup'd */
+
+         if (flagseen['R'] && (S_GET_SEGMENT(symbolP) == SEG_E1)) {
+             S_SET_SEGMENT(symbolP, SEG_E0);
+           }                   /* push data into text */
+
+         S_SET_VALUE(symbolP,
+                     S_GET_VALUE(symbolP) + symbolP->sy_frag->fr_address);
+
+         if (!S_IS_DEFINED(symbolP) && !SF_GET_LOCAL(symbolP)) 
+         {
+           S_SET_EXTERNAL(symbolP);
+         } 
+         else if (S_GET_STORAGE_CLASS(symbolP) == C_NULL) 
+         {
+           if (S_GET_SEGMENT(symbolP) == SEG_E0)
+           {
+             S_SET_STORAGE_CLASS(symbolP, C_LABEL);
+           } 
+           else 
+           {
+             S_SET_STORAGE_CLASS(symbolP, C_STAT);
+           }
+         }             
+
+         /* Mainly to speed up if not -g */
+         if (SF_GET_PROCESS(symbolP)) 
+         {
+           /* Handle the nested blocks auxiliary info. */
+           if (S_GET_STORAGE_CLASS(symbolP) == C_BLOCK) {
+               if (!strcmp(S_GET_NAME(symbolP), ".bb"))
+                stack_push(block_stack, (char *) &symbolP);
+               else {          /* .eb */
+                   register symbolS* begin_symbolP;
+                   begin_symbolP = *(symbolS**)stack_pop(block_stack);
+                   if (begin_symbolP == (symbolS*)0)
+                    as_warn("mismatched .eb");
+                   else
+                    SA_SET_SYM_ENDNDX(begin_symbolP, symbol_number+2);
+                 }
+             }
+           /* If we are able to identify the type of a function, and we
+              are out of a function (last_functionP == 0) then, the
+              function symbol will be associated with an auxiliary
+              entry. */
+           if (last_functionP == (symbolS*)0 &&
+               SF_GET_FUNCTION(symbolP)) {
+               last_functionP = symbolP;
+
+               if (S_GET_NUMBER_AUXILIARY(symbolP) < 1) {
+                   S_SET_NUMBER_AUXILIARY(symbolP, 1);
+                 }             /* make it at least 1 */
+
+               /* Clobber possible stale .dim information. */
+               bzero(symbolP->sy_symbol.ost_auxent[0].x_sym.x_fcnary.x_ary.x_dimen,
+                     sizeof(symbolP->sy_symbol.ost_auxent[0].x_sym.x_fcnary.x_ary.x_dimen));
+             }
+           /* The C_FCN doesn't need any additional information.
+              I don't even know if this is needed for sdb. But the
+              standard assembler generates it, so...
+              */
+           if (S_GET_STORAGE_CLASS(symbolP) == C_EFCN) {
+               if (last_functionP == (symbolS*)0)
+                as_fatal("C_EFCN symbol out of scope");
+               SA_SET_SYM_FSIZE(last_functionP,
+                                (long)(S_GET_VALUE(symbolP) -
+                                       S_GET_VALUE(last_functionP)));
+               SA_SET_SYM_ENDNDX(last_functionP, symbol_number);
+               last_functionP = (symbolS*)0;
+             }
+         }
+       } else if (SF_GET_TAG(symbolP)) {
+           /* First descriptor of a structure must point to
+              the first slot after the structure description. */
+           last_tagP = symbolP;
+
+         } else if (S_GET_STORAGE_CLASS(symbolP) == C_EOS) {
+             /* +2 take in account the current symbol */
+             SA_SET_SYM_ENDNDX(last_tagP, symbol_number + 2);
+           } else if (S_GET_STORAGE_CLASS(symbolP) == C_FILE) {
+               if (S_GET_VALUE(symbolP)) {
+                   S_SET_VALUE((symbolS *) S_GET_VALUE(symbolP), symbol_number);
+                   S_SET_VALUE(symbolP, 0);
+                 }             /* no one points at the first .file symbol */
+             }                 /* if debug or tag or eos or file */
+
+      /* We must put the external symbols apart. The loader
+        does not bomb if we do not. But the references in
+        the endndx field for a .bb symbol are not corrected
+        if an external symbol is removed between .bb and .be.
+        I.e in the following case :
+        [20] .bb endndx = 22
+        [21] foo external
+        [22] .be
+        ld will move the symbol 21 to the end of the list but
+        endndx will still be 22 instead of 21. */
+
+
+      if (SF_GET_LOCAL(symbolP)) {
+         /* remove C_EFCN and LOCAL (L...) symbols */
+         /* next pointer remains valid */
+         symbol_remove(symbolP, &symbol_rootP, &symbol_lastP);
+
+       } else if (!S_IS_DEFINED(symbolP)
+                  && !S_IS_DEBUG(symbolP) 
+                  && !SF_GET_STATICS(symbolP)) {
+           /* S_GET_STORAGE_CLASS(symbolP) == C_EXT && !SF_GET_FUNCTION(symbolP)) { */
+           /* if external, Remove from the list */
+           symbolS *hold = symbol_previous(symbolP);
+
+           symbol_remove(symbolP, &symbol_rootP, &symbol_lastP);
+           symbol_clear_list_pointers(symbolP);
+           symbol_append(symbolP, symbol_extern_lastP, &symbol_externP, &symbol_extern_lastP);
+           symbolP = hold;
+         } else {
+             if (SF_GET_STRING(symbolP)) {
+                 symbolP->sy_name_offset = string_byte_count;
+                 string_byte_count += strlen(S_GET_NAME(symbolP)) + 1;
+               } else {
+                   symbolP->sy_name_offset = 0;
+                 }             /* fix "long" names */
+
+             symbolP->sy_number = symbol_number;
+             symbol_number += 1 + S_GET_NUMBER_AUXILIARY(symbolP);
+           }                   /* if local symbol */
+    }                          /* traverse the symbol list */
+  return symbol_number;
+  
+}
+
+
+static unsigned int DEFUN_VOID(glue_symbols)
+{
+  unsigned int symbol_number = 0;
+  symbolS *symbolP;    
+  for (symbolP = symbol_externP; symbol_externP;) {
+      symbolS *tmp = symbol_externP;
+
+      /* append */
+      symbol_remove(tmp, &symbol_externP, &symbol_extern_lastP);
+      symbol_append(tmp, symbol_lastP, &symbol_rootP, &symbol_lastP);
+
+      /* and process */
+      if (SF_GET_STRING(tmp)) {
+         tmp->sy_name_offset = string_byte_count;
+         string_byte_count += strlen(S_GET_NAME(tmp)) + 1;
+       } else {
+           tmp->sy_name_offset = 0;
+         }                     /* fix "long" names */
+
+      tmp->sy_number = symbol_number;
+      symbol_number += 1 + S_GET_NUMBER_AUXILIARY(tmp);
+    }                          /* append the entire extern chain */
+  return symbol_number;
+  
+}
+
+static unsigned int DEFUN_VOID(tie_tags)
+{
+  unsigned int symbol_number = 0;
+  
+  symbolS*symbolP;  
+  for (symbolP = symbol_rootP; symbolP; symbolP =
+       symbol_next(symbolP)) 
+  {
+    symbolP->sy_number = symbol_number;
+    if (SF_GET_TAGGED(symbolP)) 
+    {
+      SA_SET_SYM_TAGNDX
+       (symbolP,
+       ((symbolS*) SA_GET_SYM_TAGNDX(symbolP))->sy_number);
+    }          
+
+    symbol_number += 1 + S_GET_NUMBER_AUXILIARY(symbolP);
+  }            
+  return symbol_number;
+  
+}
+
+static void DEFUN(crawl_symbols,(headers, abfd),
+          struct    internal_filehdr *headers AND
+          bfd *abfd)
+{
+
+  unsigned int i;      
+  unsigned int ptr = 0;
+
+
+  symbolS *symbolP;
+
+  /* Initialize the stack used to keep track of the matching .bb .be */
+
+  block_stack = stack_init(512, sizeof(symbolS*));
+  /* JF deal with forward references first... */
+  for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next(symbolP)) {
+
+      if (symbolP->sy_forward) {
+         S_SET_VALUE(symbolP, (S_GET_VALUE(symbolP)
+                               + S_GET_VALUE(symbolP->sy_forward)
+                               + symbolP->sy_forward->sy_frag->fr_address));
+
+         if (SF_GET_GET_SEGMENT(symbolP)) {
+             S_SET_SEGMENT(symbolP, S_GET_SEGMENT(symbolP->sy_forward));
+           }                   /* forward segment also */
+
+         symbolP->sy_forward=0;
+       }                       /* if it has a forward reference */
+    }                          /* walk the symbol chain */
+
+
+  /* The symbol list should be ordered according to the following sequence
+   * order :
+   * . .file symbol
+   * . debug entries for functions
+   * . fake symbols for the sections, including.text .data and .bss
+   * . defined symbols
+   * . undefined symbols
+   * But this is not mandatory. The only important point is to put the
+   * undefined symbols at the end of the list.
+   */
+
+  if (symbol_rootP == NULL
+      || S_GET_STORAGE_CLASS(symbol_rootP) != C_FILE) {
+      c_dot_file_symbol("fake");
+    }
+  /* Is there a .file symbol ? If not insert one at the beginning. */
+
+  /*
+   * Build up static symbols for the sections
+   */
+
+
+  for (i = SEG_E0; i < SEG_E9; i++) 
+  {
+    if (segment_info[i].scnhdr.s_name[0])
+    {
+      segment_info[i].dot = 
+       c_section_symbol(segment_info[i].scnhdr.s_name,
+                       i,
+                       ptr,
+                       i-SEG_E0+1,
+                       segment_info[i].scnhdr.s_size,
+                       segment_info[i].scnhdr.s_paddr,
+                       0,0);
+    }
+  }
+
+
+#if defined(DEBUG)
+  verify_symbol_chain(symbol_rootP, symbol_lastP);
+#endif                         /* DEBUG */
+
+  /* Take all the externals out and put them into another chain */
+headers->f_nsyms =   yank_symbols();
+  /* Take the externals and glue them onto the end.*/
+ headers->f_nsyms +=  glue_symbols();
+
+headers->f_nsyms =   tie_tags();
+  know(symbol_externP == NULL);
+  know(symbol_extern_lastP  == NULL);
+
+#if 0
+  /* FIXME-SOMEDAY 
+     I'm counting line no's here so we know what to put in the section
+     headers, and I'm resolving the addresses since I'm not sure how to
+     do it later. I am NOT resolving the linno's representing functions.
+     Their symbols need a fileptr pointing to this linno when emitted.
+     Thus, I resolve them on emit.  xoxorich. */
+
+  for (lineP = lineno_rootP; lineP; lineP = lineP->next) 
+  {
+      if (lineP->line.l_lnno > 0) {
+         lineP->line.l_addr.l_paddr += ((fragS*)lineP->frag)->fr_address;
+       } else {
+           ;
+         }
+      text_lineno_number++;
+    }                          /* for each line number */
+#endif
+  return;
+}
+
+/*
+ * Find strings by crawling along symbol table chain.
+ */
+
+w_strings(where)
+char *where;
+{
+  symbolS *symbolP;
+
+  /* Gotta do md_ byte-ordering stuff for string_byte_count first - KWK */
+  md_number_to_chars(where, string_byte_count, sizeof(string_byte_count));
+  where += sizeof(string_byte_count);
+  for (symbolP = symbol_rootP;
+       symbolP;
+       symbolP = symbol_next(symbolP)) 
+  {
+    unsigned int size;
+    
+    if (SF_GET_STRING(symbolP)) {
+       size = strlen(S_GET_NAME(symbolP)) + 1;
+           
+       memcpy(where,     S_GET_NAME(symbolP),size);
+       where += size;
+           
+      }        
+  }            
+
+}
+
+
+#if 0
+void obj_pre_write_hook(headers)
+object_headers *headers;
+{
+  register fixS *fixP;
+
+  /* FIXME-SOMEDAY this should be done at
+     fixup_segment time but I'm going to wait until I
+     do multiple segments.  xoxorich. */
+  unsigned int i;
+  unsigned int reloc_size = 0;
+  
+  for (i =0; i < N_SEG; i++) 
+  {
+    seg_info_type *s = &(SEG_INFO_FROM_SEG_NUMBER(i));
+    
+    if (s->real_section) 
+    {
+
+      for (fixP = s->fix_root; fixP; fixP = fixP->fx_next) {
+         if (fixP->fx_addsy) {
+             s->relocation_number++;
+           }   
+       }       
+
+    }
+    headers->relocation_size += s->relocation_number * RELSZ;    
+  }
+  
+  /* filehdr */
+  H_SET_FILE_MAGIC_NUMBER(headers, FILE_HEADER_MAGIC);
+  H_SET_NUMBER_OF_SECTIONS(headers, 3); /* text+data+bss */
+#ifndef OBJ_COFF_OMIT_TIMESTAMP
+  H_SET_TIME_STAMP(headers, (long)time((long*)0));
+#else                          /* OBJ_COFF_OMIT_TIMESTAMP */
+  H_SET_TIME_STAMP(headers, 0);
+#endif                         /* OBJ_COFF_OMIT_TIMESTAMP */
+  H_SET_SYMBOL_TABLE_POINTER(headers, H_GET_SYMBOL_TABLE_FILE_OFFSET(headers));
+#if 0
+  printf("FILHSZ %x\n", FILHSZ);
+  printf("OBJ_COFF_AOUTHDRSZ %x\n", OBJ_COFF_AOUTHDRSZ);
+  printf("section headers %x\n", H_GET_NUMBER_OF_SECTIONS(headers)  * SCNHSZ);
+  printf("get text size %x\n", H_GET_TEXT_SIZE(headers));
+  printf("get data size %x\n", H_GET_DATA_SIZE(headers));
+  printf("get relocation size %x\n", H_GET_RELOCATION_SIZE(headers));
+  printf("get lineno size %x\n", H_GET_LINENO_SIZE(headers));
+#endif
+  /* symbol table size allready set */
+  H_SET_SIZEOF_OPTIONAL_HEADER(headers, OBJ_COFF_AOUTHDRSZ);
+  H_SET_FLAGS(headers, (text_lineno_number == 0 ? F_LNNO : 0)
+             | headers->relocation_size ? F_RELFLG : 0
+             | BYTE_ORDERING);
+
+  /* aouthdr */
+  /* magic number allready set */
+  H_SET_VERSION_STAMP(headers, 0);
+
+}                              /* obj_pre_write_hook() */
+#endif
+/* This is a copy from aout.  All I do is neglect to actually build the symbol. */
+
+static void obj_coff_stab(what)
+int what;
+{
+       char *string;
+       expressionS e;
+       int goof = 0;   /* TRUE if we have aborted. */
+       int length;
+       int saved_type = 0;
+       long longint;
+       symbolS *symbolP = 0;
+
+       if (what == 's') {
+               string = demand_copy_C_string(&length);
+               SKIP_WHITESPACE();
+
+               if (*input_line_pointer == ',') {
+                       input_line_pointer++;
+               } else {
+                       as_bad("I need a comma after symbol's name");
+                       goof = 1;
+               } /* better be a comma */
+       } /* skip the string */
+
+       /*
+        * Input_line_pointer->after ','.  String->symbol name.
+        */
+       if (!goof) {
+               if (get_absolute_expression_and_terminator(&longint) != ',') {
+                       as_bad("I want a comma after the n_type expression");
+                       goof = 1;
+                       input_line_pointer--; /* Backup over a non-',' char. */
+               } /* on error */
+       } /* no error */
+
+       if (!goof) {
+               if (get_absolute_expression_and_terminator(&longint) != ',') {
+                       as_bad("I want a comma after the n_other expression");
+                       goof = 1;
+                       input_line_pointer--; /* Backup over a non-',' char. */
+               } /* on error */
+       } /* no error */
+
+       if (!goof) {
+               get_absolute_expression();
+
+               if (what == 's' || what == 'n') {
+                       if (*input_line_pointer != ',') {
+                               as_bad("I want a comma after the n_desc expression");
+                               goof = 1;
+                       } else {
+                               input_line_pointer++;
+                       } /* on goof */
+               } /* not stabd */
+       } /* no error */
+
+       expression(&e);
+
+       if (goof) {
+               ignore_rest_of_line();
+       } else {
+               demand_empty_rest_of_line();
+       } /* on error */
+} /* obj_coff_stab() */
+
+#ifdef DEBUG
+ /* for debugging */
+char *s_get_name(s)
+symbolS *s;
+{
+       return((s == NULL) ? "(NULL)" : S_GET_NAME(s));
+} /* s_get_name() */
+
+void symbol_dump() {
+       symbolS *symbolP;
+
+       for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next(symbolP)) {
+               printf("%3ld: 0x%lx \"%s\" type = %ld, class = %d, segment = %d\n",
+                      symbolP->sy_number,
+                      (unsigned long) symbolP,
+                      S_GET_NAME(symbolP),
+                      (long) S_GET_DATA_TYPE(symbolP),
+                      S_GET_STORAGE_CLASS(symbolP),
+                      (int) S_GET_SEGMENT(symbolP));
+       } /* traverse symbols */
+
+       return;
+} /* symbol_dump() */
+#endif /* DEBUG */
+
+
+
+static void 
+DEFUN(do_linenos_for,(abfd, file_cursor),
+      bfd *abfd AND
+      unsigned long *file_cursor)
+{
+  unsigned int idx;
+  
+  for (idx = SEG_E0;  idx < SEG_E9; idx++) 
+  {
+    segment_info_type *s =   segment_info + idx;    
+
+    if (s->scnhdr.s_nlnno != 0) 
+    {
+      struct lineno_list *line_ptr ;
+
+      struct external_lineno *buffer = 
+       (struct external_lineno *)alloca(s->scnhdr.s_nlnno * LINESZ);
+
+      struct external_lineno *dst= buffer;
+  
+      /* Run through the table we've built and turn it into its external
+        form */
+
+      for (line_ptr = s->lineno_list_head;
+          line_ptr != (struct lineno_list *)NULL;
+          line_ptr = line_ptr->next) 
+      {
+       if (line_ptr->line.l_lnno == 0) 
+       {
+         /* Turn a pointer to a symbol into the symbols' index */
+         line_ptr->line.l_addr.l_symndx =
+          ( (symbolS *)line_ptr->line.l_addr.l_symndx)->sy_number;
+       }         
+       (void)  bfd_coff_swap_lineno_out(abfd, &(line_ptr->line), dst);
+       dst++;
+      }
+
+      s->scnhdr.s_lnnoptr = *file_cursor;
+      
+      bfd_write(buffer, 1, s->scnhdr.s_nlnno* LINESZ, abfd);
+      *file_cursor += s->scnhdr.s_nlnno * LINESZ;
+    }
+  }
+}
+
+/*
+ * Local Variables:
+ * comment-column: 0
+ * fill-column: 131
+ * End:
+ */
+
+/* end of obj-coff.c */
+
+
+
+extern void DEFUN_VOID(write_object_file)
+{
+  int i;
+  struct frchain *frchain_ptr; 
+  struct frag *frag_ptr;
+  struct internal_filehdr filehdr;
+  struct internal_aouthdr aouthdr;
+unsigned long file_cursor;  
+  bfd *abfd;
+  
+  abfd = bfd_openw(out_file_name, TARGET_FORMAT);
+
+  if (abfd == 0) {
+      as_perror ("FATAL: Can't create %s", out_file_name);
+      exit(42);
+    }
+  bfd_set_format(abfd, bfd_object);
+  bfd_set_arch_mach(abfd, bfd_arch_h8300, 0);
+
+
+  string_byte_count = 4;
+  
+  for (frchain_ptr = frchain_root;
+       frchain_ptr != (struct frchain *)NULL; 
+       frchain_ptr = frchain_ptr->frch_next) {
+      /* Run through all the sub-segments and align them up. Also close any
+        open frags. We tack a .fill onto the end of the frag chain so
+        that any .align's size can be worked by looking at the next
+        frag */
+
+      subseg_new(frchain_ptr->frch_seg, frchain_ptr->frch_subseg);
+#define SUB_SEGMENT_ALIGN 2
+      frag_align(SUB_SEGMENT_ALIGN,0);
+      frag_wane(frag_now);
+      frag_now->fr_fix = 0;
+      know( frag_now->fr_next == NULL );
+    }
+
+  /* Now build one big frag chain for each segment, linked through
+     fr_next. */
+  for (i = SEG_E0; i < SEG_UNKNOWN; i++)
+  { 
+      
+    fragS ** prev_frag_ptr_ptr ;
+    struct frchain *next_frchain_ptr;
+  
+    /* struct frag **head_ptr = segment_info[i].frag_root;*/
+
+    segment_info[i].frag_root =  segment_info[i].frchainP->frch_root;
+#if 0
+    /* Im not sure what this is for */
+    for (frchain_ptr = segment_info[i].frchainP->frch_root;
+        frchain_ptr != (struct frchain *)NULL;
+        frchain_ptr = frchain_ptr->frch_next)
+    {
+      *head_ptr = frchain_ptr;
+      head_ptr = &frchain_ptr->next;
+    }
+     
+
+#endif
+  }
+#if 1
+  for (i = SEG_E0; i < SEG_UNKNOWN; i++) 
+  {
+      relax_segment(segment_info[i].frag_root, i);
+    }
+  
+  for (i = SEG_E0; i < SEG_UNKNOWN; i++) 
+  {
+/*      fixup_segment(segment_info[i].fix_root, i);*/
+   }
+  
+#endif
+
+{
+  unsigned int addr = 0;
+  filehdr.f_nscns = 0;
+  
+  /* Find out how big the sections are */
+  for (i = SEG_E0; i < SEG_UNKNOWN; i++) 
+  {
+
+    if (segment_info[i].scnhdr.s_name[0]) 
+    {
+      filehdr.f_nscns++;
+    }
+    segment_info[i].scnhdr.s_paddr = addr;
+    if (i == SEG_E2) {
+       /* THis is a special case, we leave the size alone, which will have */
+       /* been made up from all and any lcomms seen */
+
+      }
+    else {
+       addr += size_section(abfd, i);
+      }
+  }
+}
+
+  /* Turn the gas native symbol table shape into a coff symbol table */
+  crawl_symbols(&filehdr, abfd);
+
+  file_cursor =   FILHSZ + SCNHSZ * filehdr.f_nscns ;
+
+  bfd_seek(abfd, file_cursor, 0);
+
+  do_relocs_for(abfd, &file_cursor);
+  do_linenos_for(abfd, &file_cursor);
+
+
+  /* Plant the data */
+
+  fill_section(abfd,&filehdr, &file_cursor);
+
+  filehdr.f_magic = 0x8300;
+  filehdr.f_timdat = 0;
+  filehdr.f_flags = 0;
+
+
+
+{
+
+  unsigned int   symtable_size = filehdr.f_nsyms * SYMESZ;
+  char *buffer1 = malloc(symtable_size);
+  char *buffer2 = malloc(string_byte_count+4);
+  char *ptr = buffer1;
+  filehdr.f_symptr = bfd_tell(abfd);
+  w_symbols(abfd,&buffer1, symbol_rootP);
+  bfd_write(ptr, 1, symtable_size, abfd);
+
+  w_strings(buffer2);
+  bfd_write(buffer2, 1, string_byte_count, abfd);
+
+}
+  obj_header_append(abfd, &filehdr, &aouthdr);
+
+  bfd_close_all_done(abfd);
+}
+
+
+static void DEFUN(change_to_section,(name, len),
+ char *name AND
+ unsigned int len)
+{
+  unsigned int i;  
+  /* Find out if we've already got a section of this name etc */
+  for(i = SEG_E0; i < SEG_E9 && segment_info[i].scnhdr.s_name[0] ; i++) 
+  {
+    if (strncmp(segment_info[i].scnhdr.s_name, name, len) == 0) 
+    {
+      subseg_new(i, 0);  
+      return;
+      
+    }
+  }
+  /* No section, add one */
+  strncpy(segment_info[i].scnhdr.s_name, name, 8);
+  subseg_new(i, 0);  
+}
+
+static void 
+DEFUN_VOID(obj_coff_section)
+{
+  /* Strip out the section name */
+  char *section_name ;
+  char *section_name_end;
+  
+  unsigned int len;
+
+  section_name =  input_line_pointer;
+  get_symbol_end();
+  section_name_end =  input_line_pointer;
+  input_line_pointer++;
+  
+  len = section_name_end - section_name ;
+  
+
+  change_to_section(section_name, len);
+  
+}
+
+
+static void obj_coff_text()
+{
+  change_to_section(".text",5);
+}
+
+
+static void obj_coff_data()
+{
+  change_to_section(".data",5);
+}
+
+void c_symbol_merge(debug, normal)
+symbolS *debug;
+symbolS *normal;
+{
+       S_SET_DATA_TYPE(normal, S_GET_DATA_TYPE(debug));
+       S_SET_STORAGE_CLASS(normal, S_GET_STORAGE_CLASS(debug));
+
+       if (S_GET_NUMBER_AUXILIARY(debug) > S_GET_NUMBER_AUXILIARY(normal)) {
+               S_SET_NUMBER_AUXILIARY(normal, S_GET_NUMBER_AUXILIARY(debug));
+       } /* take the most we have */
+
+       if (S_GET_NUMBER_AUXILIARY(debug) > 0) {
+               memcpy((char*)&normal->sy_symbol.ost_auxent[0], (char*)&debug->sy_symbol.ost_auxent[0], S_GET_NUMBER_AUXILIARY(debug) * AUXESZ);
+       } /* Move all the auxiliary information */
+
+       /* Move the debug flags. */
+       SF_SET_DEBUG_FIELD(normal, SF_GET_DEBUG_FIELD(debug));
+} /* c_symbol_merge() */
+
+int
+c_line_new(symbol, paddr, line_number, frag)
+symbolS *symbol;
+long paddr;
+unsigned short line_number;
+fragS* frag;
+{
+  struct lineno_list* new_line = 
+   (struct lineno_list *)xmalloc(sizeof(struct lineno_list));
+    
+  segment_info_type *s =   segment_info + now_seg;
+  new_line->line.l_lnno = line_number;
+  if (line_number == 0) 
+  {
+    new_line->line.l_addr.l_symndx = (long)symbol;
+  }
+  else 
+  {
+    new_line->line.l_addr.l_paddr = paddr;
+  }  
+
+  new_line->frag = (char*)frag;
+  new_line->next = (struct lineno_list*)NULL;
+
+    
+  if (s->lineno_list_head == (struct lineno_list *)NULL) 
+  {
+    s->lineno_list_head = new_line;
+  }
+  else 
+  {
+    s->lineno_list_tail->next = new_line;
+  }
+  s->lineno_list_tail = new_line;
+  return LINESZ *     s->scnhdr.s_nlnno ++;
+}
+
+void c_dot_file_symbol(filename)
+char *filename;
+{
+    symbolS* symbolP;
+
+    symbolP = symbol_new(".file",
+                        SEG_DEBUG,
+                        0,
+                        &zero_address_frag);
+
+    S_SET_STORAGE_CLASS(symbolP, C_FILE);
+    S_SET_NUMBER_AUXILIARY(symbolP, 1);
+    SA_SET_FILE_FNAME(symbolP, filename);
+    SF_SET_DEBUG(symbolP);
+    S_SET_VALUE(symbolP, (long) previous_file_symbol);
+
+    previous_file_symbol = symbolP;
+
+    /* Make sure that the symbol is first on the symbol chain */
+    if (symbol_rootP != symbolP) {
+           if (symbolP == symbol_lastP) {
+                   symbol_lastP = symbol_lastP->sy_previous;
+           } /* if it was the last thing on the list */
+
+           symbol_remove(symbolP, &symbol_rootP, &symbol_lastP);
+           symbol_insert(symbolP, symbol_rootP, &symbol_rootP, &symbol_lastP);
+           symbol_rootP = symbolP;
+    } /* if not first on the list */
+
+} /* c_dot_file_symbol() */
+
+/*
+ * Build a 'section static' symbol.
+ */
+
+symbolS *c_section_symbol(name,idx, value, length, nreloc, nlnno)
+char *name;
+long value;
+long length;
+unsigned short nreloc;
+unsigned short nlnno;
+{
+    symbolS *symbolP;
+
+    symbolP = symbol_new(name,idx,
+                        value,
+                        &zero_address_frag);
+
+    S_SET_STORAGE_CLASS(symbolP, C_STAT);
+    S_SET_NUMBER_AUXILIARY(symbolP, 1);
+
+    SA_SET_SCN_SCNLEN(symbolP, length);
+    SA_SET_SCN_NRELOC(symbolP, nreloc);
+    SA_SET_SCN_NLINNO(symbolP, nlnno);
+
+    SF_SET_STATICS(symbolP);
+
+    return symbolP;
+} /* c_section_symbol() */
+static void 
+DEFUN(w_symbols,(abfd, where, symbol_rootP),
+bfd *abfd AND
+char **where AND
+symbolS *symbol_rootP)
+{
+    symbolS *symbolP;
+    /*
+     * Emit all symbols left in the symbol chain.
+     */
+    for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next(symbolP)) {
+           /* Used to save the offset of the name. It is used to point
+              to the string in memory but must be a file offset. */
+           register char *     temp;
+
+           tc_coff_symbol_emit_hook(symbolP);
+
+           temp = S_GET_NAME(symbolP);
+           if (SF_GET_STRING(symbolP)) {
+                   S_SET_OFFSET(symbolP, symbolP->sy_name_offset);
+                   S_SET_ZEROES(symbolP, 0);
+           } else {
+                   bzero(symbolP->sy_symbol.ost_entry.n_name, SYMNMLEN);
+                   strncpy(symbolP->sy_symbol.ost_entry.n_name, temp, SYMNMLEN);
+           }
+           symbol_to_chars(abfd, where, symbolP);
+           S_SET_NAME(symbolP,temp);
+    }
+} /* w_symbols() */
+
+#if 0
+static long fixup_segment(fixP, this_segment_type)
+register fixS *        fixP;
+segT           this_segment_type; /* N_TYPE bits for segment. */
+{
+  register long seg_reloc_count;
+  register symbolS *add_symbolP;
+  register symbolS *sub_symbolP;
+  register long add_number;
+  register int size;
+  register char *place;
+  register long where;
+  register char pcrel;
+  register fragS *fragP;
+  register segT add_symbol_segment = SEG_ABSOLUTE;
+       
+  /* FIXME: remove this line */ /*     fixS *orig = fixP; */
+  seg_reloc_count = 0;
+       
+  for ( ;  fixP;  fixP = fixP->fx_next) {
+      fragP       = fixP->fx_frag;
+      know(fragP);
+      where      = fixP->fx_where;
+      place       = fragP->fr_literal + where;
+      size       = fixP->fx_size;
+      add_symbolP = fixP->fx_addsy;
+#ifdef TC_I960
+      if (fixP->fx_callj && TC_S_IS_CALLNAME(add_symbolP)) {
+         /* Relocation should be done via the
+            associated 'bal' entry point
+            symbol. */
+
+         if (!TC_S_IS_BALNAME(tc_get_bal_of_call(add_symbolP))) {
+             as_bad("No 'bal' entry point for leafproc %s",
+                    S_GET_NAME(add_symbolP));
+             continue;
+           }
+         fixP->fx_addsy = add_symbolP = tc_get_bal_of_call(add_symbolP);
+       }                       /* callj relocation */
+#endif
+      sub_symbolP = fixP->fx_subsy;
+      add_number  = fixP->fx_offset;
+      pcrel      = fixP->fx_pcrel;
+
+      if (add_symbolP) {
+         add_symbol_segment = S_GET_SEGMENT(add_symbolP);
+       }                       /* if there is an addend */
+               
+      if (sub_symbolP) {
+         if (!add_symbolP) {
+             /* Its just -sym */
+             if (S_GET_SEGMENT(sub_symbolP) != SEG_ABSOLUTE) {
+                 as_bad("Negative of non-absolute symbol %s", S_GET_NAME(sub_symbolP));
+               }               /* not absolute */
+                               
+             add_number -= S_GET_VALUE(sub_symbolP);
+                               
+             /* if sub_symbol is in the same segment that add_symbol
+                and add_symbol is either in DATA, TEXT, BSS or ABSOLUTE */
+           } else if ((S_GET_SEGMENT(sub_symbolP) == add_symbol_segment)
+                      && (SEG_NORMAL(add_symbol_segment)
+                          || (add_symbol_segment == SEG_ABSOLUTE))) {
+               /* Difference of 2 symbols from same segment. */
+               /* Can't make difference of 2 undefineds: 'value' means */
+               /* something different for N_UNDF. */
+#ifdef TC_I960
+               /* Makes no sense to use the difference of 2 arbitrary symbols
+                * as the target of a call instruction.
+                */
+               if (fixP->fx_callj) {
+                   as_bad("callj to difference of 2 symbols");
+                 }
+#endif                         /* TC_I960 */
+               add_number += S_GET_VALUE(add_symbolP) - 
+                S_GET_VALUE(sub_symbolP);
+                               
+               add_symbolP = NULL;
+               fixP->fx_addsy = NULL;
+             } else {
+                 /* Different segments in subtraction. */
+                 know(!(S_IS_EXTERNAL(sub_symbolP) && (S_GET_SEGMENT(sub_symbolP) == SEG_ABSOLUTE)));
+                               
+                 if ((S_GET_SEGMENT(sub_symbolP) == SEG_ABSOLUTE)) {
+                     add_number -= S_GET_VALUE(sub_symbolP);
+                   } else {
+                       as_bad("Can't emit reloc {- %s-seg symbol \"%s\"} @ file address %d.",
+                              segment_name(S_GET_SEGMENT(sub_symbolP)),
+                              S_GET_NAME(sub_symbolP), fragP->fr_address + where);
+                     }         /* if absolute */
+               }
+       }                       /* if sub_symbolP */
+
+      if (add_symbolP) {
+         if (add_symbol_segment == this_segment_type && pcrel) {
+             /*
+              * This fixup was made when the symbol's segment was
+              * SEG_UNKNOWN, but it is now in the local segment.
+              * So we know how to do the address without relocation.
+              */
+#ifdef TC_I960
+             /* reloc_callj() may replace a 'call' with a 'calls' or a 'bal',
+              * in which cases it modifies *fixP as appropriate.  In the case
+              * of a 'calls', no further work is required, and *fixP has been
+              * set up to make the rest of the code below a no-op.
+              */
+             reloc_callj(fixP);
+#endif                         /* TC_I960 */
+                               
+             add_number += S_GET_VALUE(add_symbolP);
+             add_number -= md_pcrel_from (fixP);
+             pcrel = 0;        /* Lie. Don't want further pcrel processing. */
+             fixP->fx_addsy = NULL; /* No relocations please. */
+           } else {
+               switch (add_symbol_segment) {
+                 case SEG_ABSOLUTE:
+#ifdef TC_I960
+                   reloc_callj(fixP); /* See comment about reloc_callj() above*/
+#endif                         /* TC_I960 */
+                   add_number += S_GET_VALUE(add_symbolP);
+                   fixP->fx_addsy = NULL;
+                   add_symbolP = NULL;
+                   break;
+                 default:
+                   seg_reloc_count ++;
+                   add_number += S_GET_VALUE(add_symbolP);
+                   break;
+                                       
+                 case SEG_UNKNOWN:
+#ifdef TC_I960
+                   if ((int)fixP->fx_bit_fixP == 13) {
+                       /* This is a COBR instruction.  They have only a
+                        * 13-bit displacement and are only to be used
+                        * for local branches: flag as error, don't generate
+                        * relocation.
+                        */
+                       as_bad("can't use COBR format with external label");
+                       fixP->fx_addsy = NULL; /* No relocations please. */
+                       continue;
+                     }         /* COBR */
+#endif                         /* TC_I960 */
+                   /* FIXME-SOON: I think this is trash, but I'm not sure.  xoxorich. */
+#ifdef comment
+#ifdef OBJ_COFF
+                   if (S_IS_COMMON(add_symbolP))
+                    add_number += S_GET_VALUE(add_symbolP);
+#endif                         /* OBJ_COFF */
+#endif                         /* comment */
+               
+                   ++seg_reloc_count;
+
+                   break;
+                                       
+
+                 }             /* switch on symbol seg */
+             }                 /* if not in local seg */
+       }                       /* if there was a + symbol */
+
+      if (pcrel) {
+         add_number -= md_pcrel_from(fixP);
+         if (add_symbolP == 0) {
+             fixP->fx_addsy = & abs_symbol;
+             ++seg_reloc_count;
+           }                   /* if there's an add_symbol */
+       }                       /* if pcrel */
+               
+      if (!fixP->fx_bit_fixP) {
+         if ((size==1 &&
+              (add_number& ~0xFF)   && (add_number&~0xFF!=(-1&~0xFF))) ||
+             (size==2 &&
+              (add_number& ~0xFFFF) && (add_number&~0xFFFF!=(-1&~0xFFFF)))) {
+             as_bad("Value of %d too large for field of %d bytes at 0x%x",
+                    add_number, size, fragP->fr_address + where);
+           }                   /* generic error checking */
+       }                       /* not a bit fix */
+               
+      md_apply_fix(fixP, add_number);
+    }                          /* For each fixS in this segment. */
+       
+#ifdef OBJ_COFF
+#ifdef TC_I960
+{
+  fixS *topP = fixP;
+               
+  /* two relocs per callj under coff. */
+  for (fixP = topP; fixP; fixP = fixP->fx_next) {
+      if (fixP->fx_callj && fixP->fx_addsy != 0) {
+         ++seg_reloc_count;
+       }                       /* if callj and not already fixed. */
+    }                          /* for each fix */
+}
+#endif                         /* TC_I960 */
+
+#endif                         /* OBJ_COFF */
+  return(seg_reloc_count);
+}                              /* fixup_segment() */
+#endif
+
+
+void obj_coff_lcomm(void)
+{
+       char *name;
+       char c;
+       int temp;
+       char *p;
+symbolS *symbolP;
+       name = input_line_pointer;
+
+
+
+       c = get_symbol_end();
+       p = input_line_pointer;
+       *p = c;
+       SKIP_WHITESPACE();
+       if (*input_line_pointer != ',') {
+               as_bad("Expected comma after name");
+               ignore_rest_of_line();
+               return;
+       }
+       if (*input_line_pointer == '\n') {
+               as_bad("Missing size expression");
+               return;
+       }
+input_line_pointer++;
+       if ((temp = get_absolute_expression ()) < 0) {
+               as_warn("lcomm length (%d.) <0! Ignored.", temp);
+               ignore_rest_of_line();
+               return;
+       }
+       *p = 0;
+       symbolP = symbol_find_or_make(name);
+       S_SET_VALUE(symbolP, segment_info[SEG_E2].scnhdr.s_size);
+       S_SET_SEGMENT(symbolP, SEG_E2);
+       segment_info[SEG_E2].scnhdr.s_size += temp;
+       S_SET_STORAGE_CLASS(symbolP, C_STAT);
+       demand_empty_rest_of_line();
+}
diff --git a/gas/config/obj-coff-bfd.h b/gas/config/obj-coff-bfd.h
new file mode 100755 (executable)
index 0000000..97a7e0a
--- /dev/null
@@ -0,0 +1,558 @@
+/* coff object file format
+   Copyright (C) 1989, 1990, 1991 Free Software Foundation, Inc.
+
+This file is part of GAS.
+
+GAS is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GAS is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GAS; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* $Id$ */
+
+#define OBJ_COFF 1
+
+#include "targ-cpu.h"
+
+
+#ifdef BFD_HEADERS
+#include "bfd.h"
+
+extern bfd *stdoutput;
+/* This internal_lineno crap is to stop namespace pollution from the
+   bfd internal coff headerfile. */
+
+#define internal_lineno bfd_internal_lineno
+#include "internalcoff.h"
+#undef internal_lineno
+
+#if defined(TC_H8300)
+#include "coff-h8300.h"
+#define TARGET_FORMAT "coff-h8300"
+#elif defined(TC_A29K)
+#include "coff-a29k.h"
+#define TARGET_FORMAT "coff-a29k-big"
+#else
+help me
+#endif
+#else
+#include "coff.gnu.h"
+#endif
+
+#ifdef USE_NATIVE_HEADERS
+#include <filehdr.h>
+#include <aouthdr.h>
+#include <scnhdr.h>
+#include <storclass.h>
+#include <linenum.h>
+#include <syms.h>
+#include <reloc.h>
+#include <sys/types.h>
+#endif /* USE_NATIVE_HEADERS */
+
+/* Define some processor dependent values according to the processor we are
+   on. */
+#if defined(TC_H8300)
+#define BYTE_ORDERING          0
+#define FILE_HEADER_MAGIC      H8300MAGIC
+#elif defined(TC_M68K)
+
+#define BYTE_ORDERING          F_AR32W    /* See filehdr.h for more info. */
+#ifndef FILE_HEADER_MAGIC
+#define FILE_HEADER_MAGIC      MC68MAGIC  /* ... */
+#endif /* FILE_HEADER_MAGIC */
+
+#elif defined(TC_I386)
+
+#define BYTE_ORDERING          F_AR32WR   /* See filehdr.h for more info. */
+#ifndef FILE_HEADER_MAGIC
+#define FILE_HEADER_MAGIC      I386MAGIC  /* ... */
+#endif /* FILE_HEADER_MAGIC */
+
+#elif defined(TC_I960)
+
+#define BYTE_ORDERING          F_AR32WR   /* See filehdr.h for more info. */
+#ifndef FILE_HEADER_MAGIC
+#define FILE_HEADER_MAGIC      I960ROMAGIC  /* ... */
+#endif /* FILE_HEADER_MAGIC */
+
+#elif defined(TC_A29K)
+
+#define BYTE_ORDERING          F_AR32W /* big endian. */
+#ifndef FILE_HEADER_MAGIC
+#define FILE_HEADER_MAGIC      SIPFBOMAGIC
+#endif /* FILE_HEADER_MAGIC */
+
+#else
+you lose
+#endif 
+
+
+#ifndef OBJ_COFF_MAX_AUXENTRIES
+#define OBJ_COFF_MAX_AUXENTRIES 1
+#endif /* OBJ_COFF_MAX_AUXENTRIES */
+
+extern const short seg_N_TYPE[];
+extern const segT  N_TYPE_seg[];
+
+/* Magic number of paged executable. */
+#define DEFAULT_MAGIC_NUMBER_FOR_OBJECT_FILE   0x8300
+
+#ifndef BFD_HEADERS
+
+/* Add these definitions to have a consistent convention for all the
+   types used in COFF format. */
+#define AOUTHDR                        struct aouthdr
+#define AOUTHDRSZ              sizeof(AOUTHDR)
+#endif
+
+/* SYMBOL TABLE */
+
+ /* targets may also set this */
+#ifndef SYMBOLS_NEED_BACKPOINTERS
+#define SYMBOLS_NEED_BACKPOINTERS 1
+#endif /* SYMBOLS_NEED_BACKPOINTERS */
+
+/* Symbol table entry data type */
+
+typedef struct 
+{
+  struct internal_syment  ost_entry; /* Basic symbol */
+  union internal_auxent ost_auxent[OBJ_COFF_MAX_AUXENTRIES]; /* Auxiliary entry. */
+
+  unsigned int ost_flags; /* obj_coff internal use only flags */
+} obj_symbol_type;
+
+#define DO_NOT_STRIP   0
+#define DO_STRIP       1
+
+/* Symbol table macros and constants */
+
+/* Possible and usefull section number in symbol table 
+ * The values of TEXT, DATA and BSS may not be portable.
+ */
+
+#define C_ABS_SECTION          N_ABS
+#define C_UNDEF_SECTION                N_UNDEF
+#define C_DEBUG_SECTION                N_DEBUG
+#define C_NTV_SECTION          N_TV
+#define C_PTV_SECTION          P_TV
+#define C_REGISTER_SECTION     4
+
+/*
+ *  Macros to extract information from a symbol table entry.
+ *  This syntaxic indirection allows independence regarding a.out or coff.
+ *  The argument (s) of all these macros is a pointer to a symbol table entry.
+ */
+
+/* Predicates */
+/* True if the symbol is external */
+#define S_IS_EXTERNAL(s)        ((s)->sy_symbol.ost_entry.n_scnum == C_UNDEF_SECTION)
+/* True if symbol has been defined, ie :
+  section > 0 (DATA, TEXT or BSS)
+  section == 0 and value > 0 (external bss symbol) */
+#define S_IS_DEFINED(s)         ((s)->sy_symbol.ost_entry.n_scnum > C_UNDEF_SECTION || \
+                                ((s)->sy_symbol.ost_entry.n_scnum == C_UNDEF_SECTION && \
+                                 (s)->sy_symbol.ost_entry.n_value > 0))
+/* True if a debug special symbol entry */
+#define S_IS_DEBUG(s)          ((s)->sy_symbol.ost_entry.n_scnum == C_DEBUG_SECTION)
+/* True if a symbol is local symbol name */
+/* A symbol name whose name begin with ^A is a gas internal pseudo symbol */
+#define S_IS_LOCAL(s)          (S_GET_NAME(s)[0] == '\001' || \
+                                (s)->sy_symbol.ost_entry.n_scnum == C_REGISTER_SECTION || \
+                                (S_LOCAL_NAME(s) && !flagseen['L']))
+/* True if a symbol is not defined in this file */
+#define S_IS_EXTERN(s)         ((s)->sy_symbol.ost_entry.n_scnum == 0 && (s)->sy_symbol.ost_entry.n_value == 0)
+/*
+ * True if a symbol can be multiply defined (bss symbols have this def
+ * though it is bad practice)
+ */
+#define S_IS_COMMON(s)         ((s)->sy_symbol.ost_entry.n_scnum == 0 && (s)->sy_symbol.ost_entry.n_value != 0)
+/* True if a symbol name is in the string table, i.e. its length is > 8. */
+#define S_IS_STRING(s)         (strlen(S_GET_NAME(s)) > 8 ? 1 : 0)
+
+/* Accessors */
+/* The name of the symbol */
+#define S_GET_NAME(s)          ((char*)(s)->sy_symbol.ost_entry.n_offset)
+/* The pointer to the string table */
+#define S_GET_OFFSET(s)         ((s)->sy_symbol.ost_entry.n_offset)
+/* The zeroes if symbol name is longer than 8 chars */
+#define S_GET_ZEROES(s)                ((s)->sy_symbol.ost_entry.n_zeroes)
+/* The value of the symbol */
+#define S_GET_VALUE(s)         ((unsigned) ((s)->sy_symbol.ost_entry.n_value)) 
+/* The numeric value of the segment */
+#define S_GET_SEGMENT(s)   s_get_segment(s)
+/* The data type */
+#define S_GET_DATA_TYPE(s)     ((s)->sy_symbol.ost_entry.n_type)
+/* The storage class */
+#define S_GET_STORAGE_CLASS(s) ((s)->sy_symbol.ost_entry.n_sclass)
+/* The number of auxiliary entries */
+#define S_GET_NUMBER_AUXILIARY(s)      ((s)->sy_symbol.ost_entry.n_numaux)
+
+/* Modifiers */
+/* Set the name of the symbol */
+#define S_SET_NAME(s,v)                ((s)->sy_symbol.ost_entry.n_offset = (unsigned long)(v))
+/* Set the offset of the symbol */
+#define S_SET_OFFSET(s,v)      ((s)->sy_symbol.ost_entry.n_offset = (v))
+/* The zeroes if symbol name is longer than 8 chars */
+#define S_SET_ZEROES(s,v)              ((s)->sy_symbol.ost_entry.n_zeroes = (v))
+/* Set the value of the symbol */
+#define S_SET_VALUE(s,v)       ((s)->sy_symbol.ost_entry.n_value = (v))
+/* The numeric value of the segment */
+#define S_SET_SEGMENT(s,v)     ((s)->sy_symbol.ost_entry.n_scnum = SEGMENT_TO_SYMBOL_TYPE(v))
+/* The data type */
+#define S_SET_DATA_TYPE(s,v)   ((s)->sy_symbol.ost_entry.n_type = (v))
+/* The storage class */
+#define S_SET_STORAGE_CLASS(s,v)       ((s)->sy_symbol.ost_entry.n_sclass = (v))
+/* The number of auxiliary entries */
+#define S_SET_NUMBER_AUXILIARY(s,v)    ((s)->sy_symbol.ost_entry.n_numaux = (v))
+
+/* Additional modifiers */
+/* The symbol is external (does not mean undefined) */
+#define S_SET_EXTERNAL(s)       { S_SET_STORAGE_CLASS(s, C_EXT) ; SF_CLEAR_LOCAL(s); }
+
+/* Auxiliary entry macros. SA_ stands for symbol auxiliary */
+/* Omit the tv related fields */
+/* Accessors */
+#ifdef BFD_HEADERS
+#define SA_GET_SYM_TAGNDX(s)   ((s)->sy_symbol.ost_auxent[0].x_sym.x_tagndx.l)
+#else
+#define SA_GET_SYM_TAGNDX(s)   ((s)->sy_symbol.ost_auxent[0].x_sym.x_tagndx)
+#endif
+#define SA_GET_SYM_LNNO(s)     ((s)->sy_symbol.ost_auxent[0].x_sym.x_misc.x_lnsz.x_lnno)
+#define SA_GET_SYM_SIZE(s)     ((s)->sy_symbol.ost_auxent[0].x_sym.x_misc.x_lnsz.x_size)
+#define SA_GET_SYM_FSIZE(s)    ((s)->sy_symbol.ost_auxent[0].x_sym.x_misc.x_fsize)
+#define SA_GET_SYM_LNNOPTR(s)  ((s)->sy_symbol.ost_auxent[0].x_sym.x_fcnary.x_fcn.x_lnnoptr)
+#ifdef BFD_HEADERS
+#define SA_GET_SYM_ENDNDX(s)   ((s)->sy_symbol.ost_auxent[0].x_sym.x_fcnary.x_fcn.x_endndx.l)
+#else
+#define SA_GET_SYM_ENDNDX(s)   ((s)->sy_symbol.ost_auxent[0].x_sym.x_fcnary.x_fcn.x_endndx)
+#endif
+#define SA_GET_SYM_DIMEN(s,i)  ((s)->sy_symbol.ost_auxent[0].x_sym.x_fcnary.x_ary.x_dimen[(i)])
+#define SA_GET_FILE_FNAME(s)   ((s)->sy_symbol.ost_auxent[0].x_file.x_fname)
+#define SA_GET_SCN_SCNLEN(s)   ((s)->sy_symbol.ost_auxent[0].x_scn.x_scnlen)
+#define SA_GET_SCN_NRELOC(s)   ((s)->sy_symbol.ost_auxent[0].x_scn.x_nreloc)
+#define SA_GET_SCN_NLINNO(s)   ((s)->sy_symbol.ost_auxent[0].x_scn.x_nlinno)
+
+/* Modifiers */
+#ifdef BFD_HEADERS
+#define SA_SET_SYM_TAGNDX(s,v) ((s)->sy_symbol.ost_auxent[0].x_sym.x_tagndx.l=(v))
+#else
+#define SA_SET_SYM_TAGNDX(s,v) ((s)->sy_symbol.ost_auxent[0].x_sym.x_tagndx=(v))
+#endif
+#define SA_SET_SYM_LNNO(s,v)   ((s)->sy_symbol.ost_auxent[0].x_sym.x_misc.x_lnsz.x_lnno=(v))
+#define SA_SET_SYM_SIZE(s,v)   ((s)->sy_symbol.ost_auxent[0].x_sym.x_misc.x_lnsz.x_size=(v))
+#define SA_SET_SYM_FSIZE(s,v)  ((s)->sy_symbol.ost_auxent[0].x_sym.x_misc.x_fsize=(v))
+#define SA_SET_SYM_LNNOPTR(s,v)        ((s)->sy_symbol.ost_auxent[0].x_sym.x_fcnary.x_fcn.x_lnnoptr=(v))
+#ifdef BFD_HEADERS
+#define SA_SET_SYM_ENDNDX(s,v) ((s)->sy_symbol.ost_auxent[0].x_sym.x_fcnary.x_fcn.x_endndx.l=(v))
+#else
+#define SA_SET_SYM_ENDNDX(s,v) ((s)->sy_symbol.ost_auxent[0].x_sym.x_fcnary.x_fcn.x_endndx=(v))
+#endif
+#define SA_SET_SYM_DIMEN(s,i,v)        ((s)->sy_symbol.ost_auxent[0].x_sym.x_fcnary.x_ary.x_dimen[(i)]=(v))
+#define SA_SET_FILE_FNAME(s,v) strncpy((s)->sy_symbol.ost_auxent[0].x_file.x_fname,(v),FILNMLEN)
+#define SA_SET_SCN_SCNLEN(s,v) ((s)->sy_symbol.ost_auxent[0].x_scn.x_scnlen=(v))
+#define SA_SET_SCN_NRELOC(s,v) ((s)->sy_symbol.ost_auxent[0].x_scn.x_nreloc=(v))
+#define SA_SET_SCN_NLINNO(s,v) ((s)->sy_symbol.ost_auxent[0].x_scn.x_nlinno=(v))
+
+/*
+ * Internal use only definitions. SF_ stands for symbol flags.
+ *
+ * These values can be assigned to sy_symbol.ost_flags field of a symbolS.
+ *
+ * You'll break i960 if you shift the SYSPROC bits anywhere else.  for
+ * more on the balname/callname hack, see tc-i960.h.  b.out is done
+ * differently.
+ */
+
+#define SF_I960_MASK   (0x000001ff) /* Bits 0-8 are used by the i960 port. */
+#define SF_SYSPROC     (0x0000003f)         /* bits 0-5 are used to store the sysproc number */
+#define SF_IS_SYSPROC  (0x00000040)         /* bit 6 marks symbols that are sysprocs */
+#define SF_BALNAME     (0x00000080)         /* bit 7 marks BALNAME symbols */
+#define SF_CALLNAME    (0x00000100)         /* bit 8 marks CALLNAME symbols */
+
+#define SF_NORMAL_MASK (0x0000ffff) /* bits 12-15 are general purpose. */
+
+#define SF_STATICS     (0x00001000)         /* Mark the .text & all symbols */
+#define SF_DEFINED     (0x00002000)         /* Symbol is defined in this file */
+#define SF_STRING      (0x00004000)         /* Symbol name length > 8 */
+#define SF_LOCAL       (0x00008000)         /* Symbol must not be emitted */
+
+#define SF_DEBUG_MASK  (0xffff0000) /* bits 16-31 are debug info */
+
+#define SF_FUNCTION    (0x00010000)         /* The symbol is a function */
+#define SF_PROCESS     (0x00020000)         /* Process symbol before write */
+#define SF_TAGGED      (0x00040000)         /* Is associated with a tag */
+#define SF_TAG         (0x00080000)         /* Is a tag */
+#define SF_DEBUG       (0x00100000)         /* Is in debug or abs section */
+#define SF_GET_SEGMENT (0x00200000)         /* Get the section of the forward symbol. */
+ /* All other bits are unused. */
+
+/* Accessors */
+#define SF_GET(s)              ((s)->sy_symbol.ost_flags)
+#define SF_GET_NORMAL_FIELD(s) ((s)->sy_symbol.ost_flags & SF_NORMAL_MASK)
+#define SF_GET_DEBUG_FIELD(s)  ((s)->sy_symbol.ost_flags & SF_DEBUG_MASK)
+#define SF_GET_FILE(s)         ((s)->sy_symbol.ost_flags & SF_FILE)
+#define SF_GET_STATICS(s)      ((s)->sy_symbol.ost_flags & SF_STATICS)
+#define SF_GET_DEFINED(s)      ((s)->sy_symbol.ost_flags & SF_DEFINED)
+#define SF_GET_STRING(s)       ((s)->sy_symbol.ost_flags & SF_STRING)
+#define SF_GET_LOCAL(s)                ((s)->sy_symbol.ost_flags & SF_LOCAL)
+#define SF_GET_FUNCTION(s)      ((s)->sy_symbol.ost_flags & SF_FUNCTION)
+#define SF_GET_PROCESS(s)      ((s)->sy_symbol.ost_flags & SF_PROCESS)
+#define SF_GET_DEBUG(s)                ((s)->sy_symbol.ost_flags & SF_DEBUG)
+#define SF_GET_TAGGED(s)       ((s)->sy_symbol.ost_flags & SF_TAGGED)
+#define SF_GET_TAG(s)          ((s)->sy_symbol.ost_flags & SF_TAG)
+#define SF_GET_GET_SEGMENT(s)  ((s)->sy_symbol.ost_flags & SF_GET_SEGMENT)
+#define SF_GET_I960(s)         ((s)->sy_symbol.ost_flags & SF_I960_MASK) /* used by i960 */
+#define SF_GET_BALNAME(s)      ((s)->sy_symbol.ost_flags & SF_BALNAME) /* used by i960 */
+#define SF_GET_CALLNAME(s)     ((s)->sy_symbol.ost_flags & SF_CALLNAME) /* used by i960 */
+#define SF_GET_IS_SYSPROC(s)   ((s)->sy_symbol.ost_flags & SF_IS_SYSPROC) /* used by i960 */
+#define SF_GET_SYSPROC(s)      ((s)->sy_symbol.ost_flags & SF_SYSPROC) /* used by i960 */
+
+/* Modifiers */
+#define SF_SET(s,v)            ((s)->sy_symbol.ost_flags = (v))
+#define SF_SET_NORMAL_FIELD(s,v)((s)->sy_symbol.ost_flags |= ((v) & SF_NORMAL_MASK))
+#define SF_SET_DEBUG_FIELD(s,v)        ((s)->sy_symbol.ost_flags |= ((v) & SF_DEBUG_MASK))
+#define SF_SET_FILE(s)         ((s)->sy_symbol.ost_flags |= SF_FILE)
+#define SF_SET_STATICS(s)      ((s)->sy_symbol.ost_flags |= SF_STATICS)
+#define SF_SET_DEFINED(s)      ((s)->sy_symbol.ost_flags |= SF_DEFINED)
+#define SF_SET_STRING(s)       ((s)->sy_symbol.ost_flags |= SF_STRING)
+#define SF_SET_LOCAL(s)                ((s)->sy_symbol.ost_flags |= SF_LOCAL)
+#define SF_CLEAR_LOCAL(s)      ((s)->sy_symbol.ost_flags &= ~SF_LOCAL)
+#define SF_SET_FUNCTION(s)      ((s)->sy_symbol.ost_flags |= SF_FUNCTION)
+#define SF_SET_PROCESS(s)      ((s)->sy_symbol.ost_flags |= SF_PROCESS)
+#define SF_SET_DEBUG(s)                ((s)->sy_symbol.ost_flags |= SF_DEBUG)
+#define SF_SET_TAGGED(s)       ((s)->sy_symbol.ost_flags |= SF_TAGGED)
+#define SF_SET_TAG(s)          ((s)->sy_symbol.ost_flags |= SF_TAG)
+#define SF_SET_GET_SEGMENT(s)  ((s)->sy_symbol.ost_flags |= SF_GET_SEGMENT)
+#define SF_SET_I960(s,v)       ((s)->sy_symbol.ost_flags |= ((v) & SF_I960_MASK)) /* used by i960 */
+#define SF_SET_BALNAME(s)      ((s)->sy_symbol.ost_flags |= SF_BALNAME) /* used by i960 */
+#define SF_SET_CALLNAME(s)     ((s)->sy_symbol.ost_flags |= SF_CALLNAME) /* used by i960 */
+#define SF_SET_IS_SYSPROC(s)   ((s)->sy_symbol.ost_flags |= SF_IS_SYSPROC) /* used by i960 */
+#define SF_SET_SYSPROC(s,v)    ((s)->sy_symbol.ost_flags |= ((v) & SF_SYSPROC)) /* used by i960 */
+
+/* File header macro and type definition */
+
+/*
+ * File position calculators. Beware to use them when all the
+ * appropriate fields are set in the header.
+ */
+
+#ifdef OBJ_COFF_OMIT_OPTIONAL_HEADER
+#define OBJ_COFF_AOUTHDRSZ (0)
+#else
+#define OBJ_COFF_AOUTHDRSZ (AOUTHDRSZ)
+#endif /* OBJ_COFF_OMIT_OPTIONAL_HEADER */
+
+#define H_GET_FILE_SIZE(h) \
+    (long)(FILHSZ + OBJ_COFF_AOUTHDRSZ + \
+          H_GET_NUMBER_OF_SECTIONS(h) * SCNHSZ + \
+          H_GET_TEXT_SIZE(h) + H_GET_DATA_SIZE(h) + \
+          H_GET_RELOCATION_SIZE(h) + H_GET_LINENO_SIZE(h) + \
+          H_GET_SYMBOL_TABLE_SIZE(h) + \
+          (h)->string_table_size)
+#define H_GET_TEXT_FILE_OFFSET(h) \
+    (long)(FILHSZ + OBJ_COFF_AOUTHDRSZ + \
+          H_GET_NUMBER_OF_SECTIONS(h) * SCNHSZ)
+#define H_GET_DATA_FILE_OFFSET(h) \
+    (long)(FILHSZ + OBJ_COFF_AOUTHDRSZ + \
+          H_GET_NUMBER_OF_SECTIONS(h) * SCNHSZ + \
+          H_GET_TEXT_SIZE(h))
+#define H_GET_BSS_FILE_OFFSET(h) 0
+#define H_GET_RELOCATION_FILE_OFFSET(h) \
+    (long)(FILHSZ + OBJ_COFF_AOUTHDRSZ + \
+          H_GET_NUMBER_OF_SECTIONS(h) * SCNHSZ + \
+          H_GET_TEXT_SIZE(h) + H_GET_DATA_SIZE(h))
+#define H_GET_LINENO_FILE_OFFSET(h) \
+    (long)(FILHSZ + OBJ_COFF_AOUTHDRSZ + \
+          H_GET_NUMBER_OF_SECTIONS(h) * SCNHSZ + \
+          H_GET_TEXT_SIZE(h) + H_GET_DATA_SIZE(h) + \
+          H_GET_RELOCATION_SIZE(h))
+#define H_GET_SYMBOL_TABLE_FILE_OFFSET(h) \
+    (long)(FILHSZ + OBJ_COFF_AOUTHDRSZ + \
+          H_GET_NUMBER_OF_SECTIONS(h) * SCNHSZ + \
+          H_GET_TEXT_SIZE(h) + H_GET_DATA_SIZE(h) + \
+          H_GET_RELOCATION_SIZE(h) + H_GET_LINENO_SIZE(h))
+
+/* Accessors */
+/* aouthdr */
+#define H_GET_MAGIC_NUMBER(h)           ((h)->aouthdr.magic)
+#define H_GET_VERSION_STAMP(h)         ((h)->aouthdr.vstamp)
+#define H_GET_TEXT_SIZE(h)              ((h)->aouthdr.tsize)
+#define H_GET_DATA_SIZE(h)              ((h)->aouthdr.dsize)
+#define H_GET_BSS_SIZE(h)               ((h)->aouthdr.bsize)
+#define H_GET_ENTRY_POINT(h)            ((h)->aouthdr.entry)
+#define H_GET_TEXT_START(h)            ((h)->aouthdr.text_start)
+#define H_GET_DATA_START(h)            ((h)->aouthdr.data_start)
+/* filehdr */
+#define H_GET_FILE_MAGIC_NUMBER(h)     ((h)->filehdr.f_magic)
+#define H_GET_NUMBER_OF_SECTIONS(h)    ((h)->filehdr.f_nscns)
+#define H_GET_TIME_STAMP(h)            ((h)->filehdr.f_timdat)
+#define H_GET_SYMBOL_TABLE_POINTER(h)  ((h)->filehdr.f_symptr)
+#define H_GET_SYMBOL_COUNT(h)          ((h)->filehdr.f_nsyms)
+#define H_GET_SYMBOL_TABLE_SIZE(h)     (H_GET_SYMBOL_COUNT(h) * SYMESZ)
+#define H_GET_SIZEOF_OPTIONAL_HEADER(h)        ((h)->filehdr.f_opthdr)
+#define H_GET_FLAGS(h)                 ((h)->filehdr.f_flags)
+/* Extra fields to achieve bsd a.out compatibility and for convenience */
+#define H_GET_RELOCATION_SIZE(h)       ((h)->relocation_size)
+#define H_GET_STRING_SIZE(h)            ((h)->string_table_size)
+#define H_GET_LINENO_SIZE(h)            ((h)->lineno_size)
+
+#ifndef OBJ_COFF_OMIT_OPTIONAL_HEADER
+#define H_GET_HEADER_SIZE(h)           (sizeof(FILHDR) \
+                                        + sizeof(AOUTHDR)\
+                                        + (H_GET_NUMBER_OF_SECTIONS(h) * SCNHSZ))
+#else /* OBJ_COFF_OMIT_OPTIONAL_HEADER */
+#define H_GET_HEADER_SIZE(h)           (sizeof(FILHDR) \
+                                        + (H_GET_NUMBER_OF_SECTIONS(h) * SCNHSZ))
+#endif /* OBJ_COFF_OMIT_OPTIONAL_HEADER */
+
+#define H_GET_TEXT_RELOCATION_SIZE(h)  (text_section_header.s_nreloc * RELSZ)
+#define H_GET_DATA_RELOCATION_SIZE(h)  (data_section_header.s_nreloc * RELSZ)
+
+/* Modifiers */
+/* aouthdr */
+#define H_SET_MAGIC_NUMBER(h,v)         ((h)->aouthdr.magic = (v))
+#define H_SET_VERSION_STAMP(h,v)       ((h)->aouthdr.vstamp = (v))
+#define H_SET_TEXT_SIZE(h,v)            ((h)->aouthdr.tsize = (v))
+#define H_SET_DATA_SIZE(h,v)            ((h)->aouthdr.dsize = (v))
+#define H_SET_BSS_SIZE(h,v)             ((h)->aouthdr.bsize = (v))
+#define H_SET_ENTRY_POINT(h,v)          ((h)->aouthdr.entry = (v))
+#define H_SET_TEXT_START(h,v)          ((h)->aouthdr.text_start = (v))
+#define H_SET_DATA_START(h,v)          ((h)->aouthdr.data_start = (v))
+/* filehdr */
+#define H_SET_FILE_MAGIC_NUMBER(h,v)   ((h)->filehdr.f_magic = (v))
+#define H_SET_NUMBER_OF_SECTIONS(h,v)  ((h)->filehdr.f_nscns = (v))
+#define H_SET_TIME_STAMP(h,v)          ((h)->filehdr.f_timdat = (v))
+#define H_SET_SYMBOL_TABLE_POINTER(h,v)        ((h)->filehdr.f_symptr = (v))
+#define H_SET_SYMBOL_TABLE_SIZE(h,v)    ((h)->filehdr.f_nsyms = (v))
+#define H_SET_SIZEOF_OPTIONAL_HEADER(h,v) ((h)->filehdr.f_opthdr = (v))
+#define H_SET_FLAGS(h,v)               ((h)->filehdr.f_flags = (v))
+/* Extra fields to achieve bsd a.out compatibility and for convinience */
+#define H_SET_RELOCATION_SIZE(h,t,d)   ((h)->relocation_size = (t)+(d))
+#define H_SET_STRING_SIZE(h,v)          ((h)->string_table_size = (v))
+#define H_SET_LINENO_SIZE(h,v)          ((h)->lineno_size = (v))
+
+ /* Segment flipping */
+#define segment_name(v)        (seg_name[(int) (v)])
+
+typedef struct {
+#ifdef BFD_HEADERS
+    struct internal_aouthdr       aouthdr;             /* a.out header */
+    struct internal_filehdr       filehdr;             /* File header, not machine dep. */
+#else
+    AOUTHDR       aouthdr;             /* a.out header */
+    FILHDR        filehdr;             /* File header, not machine dep. */
+#endif
+    long       string_table_size;   /* names + '\0' + sizeof(int) */
+    long          relocation_size;     /* Cumulated size of relocation
+                                          information for all sections in
+                                          bytes. */
+    long          lineno_size;         /* Size of the line number information
+                                          table in bytes */
+} object_headers;
+
+
+
+struct lineno_list
+{
+  
+  struct bfd_internal_lineno line;
+  char* frag;                  /* Frag to which the line number is related */
+  struct lineno_list* next;    /* Forward chain pointer */
+} ;
+
+
+
+
+ /* stack stuff */
+typedef struct {
+    unsigned long chunk_size;
+    unsigned long element_size;
+    unsigned long size;
+    char*        data;
+    unsigned long pointer;
+} stack;
+
+#ifdef __STDC__
+
+char *stack_pop(stack *st);
+char *stack_push(stack *st, char *element);
+char *stack_top(stack *st);
+stack *stack_init(unsigned long chunk_size, unsigned long element_size);
+void c_dot_file_symbol(char *filename);
+void obj_extra_stuff(object_headers *headers);
+void stack_delete(stack *st);
+
+#ifndef tc_headers_hook
+void tc_headers_hook(object_headers *headers);
+#endif /* tc_headers_hook */
+
+#ifndef tc_coff_symbol_emit_hook
+void tc_coff_symbol_emit_hook(); /* really tc_coff_symbol_emit_hook(symbolS *symbolP) */
+#endif /* tc_coff_symbol_emit_hook */
+
+void c_section_header(
+#ifdef BFD_HEADERS
+                     struct internal_scnhdr *header,
+#else
+                     SCNHDR *header,
+#endif
+
+                     char *name,
+                     long core_address,
+                     long size,
+                     long data_ptr,
+                     long reloc_ptr,
+                     long lineno_ptr,
+                     long reloc_number,
+                     long lineno_number,
+                     long alignment);
+
+#else /* __STDC__ */
+
+char *stack_pop();
+char *stack_push();
+char *stack_top();
+stack *stack_init();
+void c_dot_file_symbol();
+void c_section_header();
+void obj_extra_stuff();
+void stack_delete();
+void tc_headers_hook();
+void tc_coff_symbol_emit_hook();
+
+#endif /* __STDC__ */
+
+
+ /* sanity check */
+
+#ifdef TC_I960
+#ifndef C_LEAFSTAT
+hey!  Where is the C_LEAFSTAT definition?  i960-coff support is depending on it.
+#endif /* no C_LEAFSTAT */
+#endif /* TC_I960 */
+#ifdef BFD_HEADERS
+extern struct internal_scnhdr data_section_header;
+extern struct internal_scnhdr text_section_header;
+#else
+extern SCNHDR data_section_header;
+extern SCNHDR text_section_header;
+#endif
+/*
+ * Local Variables:
+ * comment-column: 0
+ * fill-column: 131
+ * End:
+ */
+
+/* end of obj-coff.h */