* coffgrok.c (do_where): Make data with no type 'int'.
authorSteve Chamberlain <sac@cygnus>
Fri, 15 Jul 1994 08:51:49 +0000 (08:51 +0000)
committerSteve Chamberlain <sac@cygnus>
Fri, 15 Jul 1994 08:51:49 +0000 (08:51 +0000)
(do_define):  Keep info on source file of a symbol.
* coffgrok.h (coff_symbol): New field.
* srconv.c (PROGRAM_VERSION): Now 1.3
(wr_rl): Use external ref number for symbol.
(wr_dus): Only keep one source file per debug unit.
(wr_dln): Always emit line numbers for first source file,
(wr_globals):  Emit globals in the du of their owning source file.

binutils/ChangeLog
binutils/coffgrok.c [new file with mode: 0644]
binutils/srconv.c [new file with mode: 0644]

index 9dddcba35e16da8e5e53ff47689f56f2e85fbd9b..ff68f27ff43c92a170800ad7f64660019c627681 100644 (file)
@@ -1,3 +1,14 @@
+Fri Jul 15 01:41:35 1994  Steve Chamberlain  (sac@jonny.cygnus.com)
+
+       * coffgrok.c (do_where): Make data with no type 'int'.
+       (do_define):  Keep info on source file of a symbol.
+       * coffgrok.h (coff_symbol): New field.
+       * srconv.c (PROGRAM_VERSION): Now 1.3
+       (wr_rl): Use external ref number for symbol.
+       (wr_dus): Only keep one source file per debug unit.
+       (wr_dln): Always emit line numbers for first source file,
+       (wr_globals):  Emit globals in the du of their owning source file.
+
 Mon Jul 11 15:59:03 1994  J.T. Conklin  (jtc@phishhead.cygnus.com)
 
        * nlmheader.y: Null terminate var_hdr->threadName.
diff --git a/binutils/coffgrok.c b/binutils/coffgrok.c
new file mode 100644 (file)
index 0000000..35ccd99
--- /dev/null
@@ -0,0 +1,728 @@
+
+
+/* coffgrok.c
+
+   Copyright (C) 1994 Free Software Foundation, Inc.
+
+This file is part of GNU Binutils.
+
+This program 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 of the License, or
+(at your option) any later version.
+
+This program 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 this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* Written by Steve Chamberlain (sac@cygnus.com)
+
+   This module reads a coff file and builds a really simple type tree
+   which can be read by other programs.  The first application is a
+   coff->sysroff converter.  It can be tested with coffdump.c.
+
+*/
+
+#include <bfd.h>
+#include <stdio.h>
+
+#include "coff/internal.h"
+#include "../bfd/libcoff.h"
+#include "coffgrok.h"
+int lofile = 1;
+static struct coff_scope *top_scope;
+static struct coff_scope *file_scope;
+static struct coff_ofile *ofile;
+
+struct coff_symbol *last_function_symbol;
+struct coff_type *last_function_type;
+struct coff_type *last_struct;
+struct coff_type *last_enum;
+struct coff_sfile *cur_sfile;
+
+static struct coff_symbol **tindex;
+
+
+static asymbol **syms;
+static long symcount;
+
+#define N(x) ((x)->_n._n_nptr[1])
+
+static struct coff_ptr_struct *rawsyms;
+static int rawcount;
+static bfd *abfd;
+extern char *xcalloc ();
+extern char *xmalloc ();
+#define PTR_SIZE       4
+#define SHORT_SIZE     2
+#define INT_SIZE       4
+#define LONG_SIZE      4
+#define FLOAT_SIZE     4
+#define DOUBLE_SIZE    8
+
+#define INDEXOF(p)  ((struct coff_ptr_struct *)(p)-(rawsyms))
+
+static struct coff_scope *
+empty_scope ()
+{
+  struct coff_scope *l;
+  l = (struct coff_scope *) (xcalloc (sizeof (struct coff_scope), 1));
+  return l;
+}
+
+static struct coff_symbol *
+empty_symbol ()
+{
+  return (struct coff_symbol *) (xcalloc (sizeof (struct coff_symbol), 1));
+}
+
+/*int l;*/
+static void
+push_scope (link)
+{
+  struct coff_scope *n = empty_scope ();
+  if (link)
+    {
+      if (top_scope)
+       {
+         if (top_scope->list_tail)
+           {
+             top_scope->list_tail->next = n;
+           }
+         else
+           {
+             top_scope->list_head = n;
+           }
+         top_scope->list_tail = n;
+       }
+    }
+  n->parent = top_scope;
+
+  top_scope = n;
+}
+
+static void
+pop_scope ()
+{
+  top_scope = top_scope->parent;
+}
+
+static void
+do_sections_p1 (head)
+     struct coff_ofile *head;
+{
+  asection *section;
+  int idx;
+  struct coff_section *all = (struct coff_section *) (xcalloc (abfd->section_count + 1,
+                                            sizeof (struct coff_section)));
+  head->nsections = abfd->section_count + 1;
+  head->sections = all;
+
+  for (idx = 0, section = abfd->sections; section; section = section->next, idx++)
+    {
+      long relsize;
+      int i = section->target_index;
+      arelent **relpp;
+      long relcount;
+
+      relsize = bfd_get_reloc_upper_bound (abfd, section);
+      if (relsize < 0)
+       bfd_fatal (bfd_get_filename (abfd));
+      relpp = (arelent **) xmalloc (relsize);
+      relcount = bfd_canonicalize_reloc (abfd, section, relpp, syms);
+      if (relcount < 0)
+       bfd_fatal (bfd_get_filename (abfd));
+
+      head->sections[i].name = (char *) (section->name);
+      head->sections[i].code = section->flags & SEC_CODE;
+      head->sections[i].data = section->flags & SEC_DATA;
+      if (strcmp (section->name, ".bss") == 0)
+       head->sections[i].data = 1;
+      head->sections[i].address = section->vma;
+      head->sections[i].size = section->_raw_size;
+      head->sections[i].number = idx;
+      head->sections[i].nrelocs = section->reloc_count;
+      head->sections[i].relocs =
+       (struct coff_reloc *) (xcalloc (section->reloc_count,
+                                       sizeof (struct coff_reloc)));
+      head->sections[i].bfd_section = section;
+    }
+  head->sections[0].name = "ABSOLUTE";
+  head->sections[0].code = 0;
+  head->sections[0].data = 0;
+  head->sections[0].address = 0;
+  head->sections[0].size = 0;
+  head->sections[0].number = 0;
+}
+
+static void
+do_sections_p2 (head)
+     struct coff_ofile *head;
+{
+  asection *section;
+  for (section = abfd->sections; section; section = section->next)
+    {
+      int j;
+      for (j = 0; j < section->reloc_count; j++)
+       {
+         int idx;
+         int i = section->target_index;
+         struct coff_reloc *r = head->sections[i].relocs + j;
+         arelent *sr = section->relocation + j;
+         r->offset = sr->address;
+         r->addend = sr->addend;
+         idx = ((coff_symbol_type *) (sr->sym_ptr_ptr[0]))->native - rawsyms;
+         r->symbol = tindex[idx];
+       }
+    }
+}
+
+static struct coff_where *
+do_where (i)
+     int i;
+{
+  struct internal_syment *sym = &rawsyms[i].u.syment;
+  struct coff_where *where
+  = (struct coff_where *) (malloc (sizeof (struct coff_where)));
+  where->offset = sym->n_value;
+
+  if (sym->n_scnum == -1)
+    sym->n_scnum = 0;
+
+  switch (sym->n_sclass)
+    {
+    case C_FIELD:
+      where->where = coff_where_member_of_struct;
+      where->offset = sym->n_value / 8;
+      where->bitoffset = sym->n_value % 8;
+      where->bitsize = rawsyms[i + 1].u.auxent.x_sym.x_misc.x_lnsz.x_size;
+      break;
+    case C_MOE:
+      where->where = coff_where_member_of_enum;
+      break;
+    case C_MOS:
+    case C_MOU:
+      where->where = coff_where_member_of_struct;
+      break;
+    case C_AUTO:
+    case C_ARG:
+      where->where = coff_where_stack;
+      break;
+    case C_EXT:
+    case C_STAT:
+    case C_EXTDEF:
+    case C_LABEL:
+      where->where = coff_where_memory;
+      where->section = &ofile->sections[sym->n_scnum];
+      break;
+    case C_REG:
+    case C_REGPARM:
+      where->where = coff_where_register;
+      break;
+    case C_ENTAG:
+      where->where = coff_where_entag;
+      break;
+    case C_STRTAG:
+    case C_UNTAG:
+      where->where = coff_where_strtag;
+      break;
+    case C_TPDEF:
+      where->where = coff_where_typedef;
+      break;
+    default:
+      abort ();
+      break;
+    }
+  return where;
+}
+
+static
+struct coff_line *
+do_lines (i, name)
+     int i;
+     char *name;
+{
+  struct coff_line *res = (struct coff_line *) xcalloc (sizeof (struct coff_line), 1);
+  asection *s;
+  int l;
+  /* Find out if this function has any line numbers in the table */
+  for (s = abfd->sections; s; s = s->next)
+    {
+      for (l = 0; l < s->lineno_count; l++)
+       {
+         if (s->lineno[l].line_number == 0)
+           {
+             if (rawsyms + i == ((coff_symbol_type *) (&(s->lineno[l].u.sym[0])))->native)
+               {
+                 /* These lines are for this function - so count them and stick them on */
+                 int c = 0;
+                 /* Find the linenumber of the top of the function, since coff linenumbers
+                    are relative to the start of the function. */
+                 int start_line = rawsyms[i + 3].u.auxent.x_sym.x_misc.x_lnsz.x_lnno;
+
+                 l++;
+                 for (c = 0; s->lineno[l + c + 1].line_number; c++)
+                   ;
+
+                 /* Add two extra records, one for the prologue and one for the epilogue */
+                 c += 1;
+                 res->nlines = c;
+                 res->lines = (int *) (xcalloc (sizeof (int), c));
+                 res->addresses = (int *) (xcalloc (sizeof (int), c));
+                 res->lines[0] = start_line;
+                 res->addresses[0] = rawsyms[i].u.syment.n_value - s->vma;
+                 for (c = 0; s->lineno[l + c + 1].line_number; c++)
+                   {
+                     res->lines[c + 1] = s->lineno[l + c].line_number + start_line - 1;
+                     res->addresses[c + 1] = s->lineno[l + c].u.offset;
+                   }
+                 return res;
+               }
+           }
+       }
+    }
+  return res;
+}
+
+static
+struct coff_type *
+do_type (i)
+     int i;
+{
+  struct internal_syment *sym = &rawsyms[i].u.syment;
+  union internal_auxent *aux = &rawsyms[i + 1].u.auxent;
+  struct coff_type *res = (struct coff_type *) malloc (sizeof (struct coff_type));
+  int type = sym->n_type;
+  int which_dt = 0;
+
+  res->type = coff_basic_type;
+  res->u.basic = type & 0xf;
+
+  switch (type & 0xf)
+    {
+    case T_NULL:
+    case T_VOID:
+      if (sym->n_numaux && sym->n_sclass == C_STAT)
+       {
+         /* This is probably a section definition */
+         res->type = coff_secdef_type;
+         res->size = aux->x_scn.x_scnlen;
+       }
+      else
+       {
+         if (type == 0)
+           {
+             /* Don't know what this is, let's make it a simple int */
+             res->size = INT_SIZE;
+             res->u.basic = T_UINT;
+           }
+         else
+           {
+             /* Else it could be a function or pointer to void */
+             res->size = 0;
+           }
+       }
+      break;
+
+
+      break;
+    case T_UCHAR:
+    case T_CHAR:
+      res->size = 1;
+      break;
+    case T_USHORT:
+    case T_SHORT:
+      res->size = SHORT_SIZE;
+      break;
+    case T_UINT:
+    case T_INT:
+      res->size = INT_SIZE;
+      break;
+    case T_ULONG:
+    case T_LONG:
+      res->size = LONG_SIZE;
+      break;
+    case T_FLOAT:
+      res->size = FLOAT_SIZE;
+      break;
+    case T_DOUBLE:
+      res->size = DOUBLE_SIZE;
+      break;
+    case T_STRUCT:
+    case T_UNION:
+      if (sym->n_numaux)
+       {
+         if (aux->x_sym.x_tagndx.p)
+           {
+             /* Refering to a struct defined elsewhere */
+             res->type = coff_structref_type;
+             res->u.astructref.ref = tindex[INDEXOF (aux->x_sym.x_tagndx.p)];
+             res->size = res->u.astructref.ref ?
+               res->u.astructref.ref->type->size : 0;
+           }
+         else
+           {
+             /* A definition of a struct */
+             last_struct = res;
+             res->type = coff_structdef_type;
+             res->u.astructdef.elements = empty_scope ();
+             res->u.astructdef.isstruct = (type & 0xf) == T_STRUCT;
+             res->size = aux->x_sym.x_misc.x_lnsz.x_size;
+           }
+       }
+      else
+       {
+         /* No auxents - it's anonynmous */
+         res->type = coff_structref_type;
+         res->u.astructref.ref = 0;
+         res->size = 0;
+       }
+      break;
+    case T_ENUM:
+      if (aux->x_sym.x_tagndx.p)
+       {
+         /* Refering to a enum defined elsewhere */
+         res->type = coff_enumref_type;
+         res->u.aenumref.ref = tindex[INDEXOF (aux->x_sym.x_tagndx.p)];
+         res->size = res->u.aenumref.ref->type->size;
+       }
+      else
+       {
+         /* A definition of an enum */
+         last_enum = res;
+         res->type = coff_enumdef_type;
+         res->u.aenumdef.elements = empty_scope ();
+         res->size = aux->x_sym.x_misc.x_lnsz.x_size;
+       }
+      break;
+    case T_MOE:
+      break;
+    }
+
+  for (which_dt = 5; which_dt >= 0; which_dt--)
+    {
+      switch ((type >> ((which_dt * 2) + 4)) & 0x3)
+       {
+       case 0:
+         break;
+       case DT_ARY:
+         {
+
+           /* Look in the auxent for the dimensions and build lots of dims */
+           int els = aux->x_sym.x_fcnary.x_ary.x_dimen[which_dt];
+           if (els)
+             {
+               struct coff_type *ptr = (struct coff_type *) malloc (sizeof (struct coff_type));
+               ptr->type = coff_array_type;
+               ptr->size = els * res->size;
+               ptr->u.array.dim = els;
+               ptr->u.array.array_of = res;
+               res = ptr;
+             }
+         }
+
+         break;
+       case DT_PTR:
+         {
+           struct coff_type *ptr = (struct coff_type *) malloc (sizeof (struct coff_type));
+           ptr->size = PTR_SIZE;
+           ptr->type = coff_pointer_type;
+           ptr->u.pointer.points_to = res;
+           res = ptr;
+           break;
+         }
+       case DT_FCN:
+         {
+           struct coff_type *ptr = (struct coff_type *) malloc (sizeof (struct coff_type));
+           ptr->size = 0;
+           ptr->type = coff_function_type;
+           ptr->u.function.function_returns = res;
+           ptr->u.function.parameters = empty_scope ();
+           ptr->u.function.lines = do_lines (i, sym->_n._n_nptr[1]);
+           ptr->u.function.code = 0;
+           last_function_type = ptr;
+           res = ptr;
+           break;
+         }
+       }
+    }
+  return res;
+}
+
+static struct coff_visible *
+do_visible (i)
+     int i;
+{
+  struct internal_syment *sym = &rawsyms[i].u.syment;
+  struct coff_visible *visible = (struct coff_visible *) (malloc (sizeof (struct coff_visible)));
+  enum coff_vis_type t;
+  switch (sym->n_sclass)
+    {
+    case C_MOS:
+    case C_MOU:
+    case C_FIELD:
+      t = coff_vis_member_of_struct;
+      break;
+    case C_MOE:
+      t = coff_vis_member_of_enum;
+      break;
+
+    case C_REGPARM:
+      t = coff_vis_regparam;
+      break;
+
+    case C_REG:
+      t = coff_vis_register;
+      break;
+    case C_STRTAG:
+    case C_UNTAG:
+    case C_ENTAG:
+    case C_TPDEF:
+      t = coff_vis_tag;
+      break;
+    case C_AUTOARG:
+    case C_ARG:
+      t = coff_vis_autoparam;
+      break;
+    case C_AUTO:
+
+
+      t = coff_vis_auto;
+      break;
+    case C_LABEL:
+    case C_STAT:
+      t = coff_vis_int_def;
+      break;
+    case C_EXT:
+      if (sym->n_scnum == N_UNDEF)
+       {
+         if (sym->n_value)
+           t = coff_vis_common;
+         else
+           t = coff_vis_ext_ref;
+       }
+      else
+       t = coff_vis_ext_def;
+      break;
+    default:
+      abort ();
+      break;
+
+    }
+  visible->type = t;
+  return visible;
+}
+
+static int
+do_define (i, b)
+     int i;
+     struct coff_scope *b;
+{
+  static int symbol_index;
+  struct internal_syment *sym = &rawsyms[i].u.syment;
+
+  /* Define a symbol and attach to block b */
+  struct coff_symbol *s = empty_symbol ();
+
+  s->number = ++symbol_index;
+  s->name = sym->_n._n_nptr[1];
+  s->sfile = cur_sfile;
+  /* Glue onto the ofile list */
+  if (lofile >= 0)
+    {
+      if (ofile->symbol_list_tail)
+       ofile->symbol_list_tail->next_in_ofile_list = s;
+      else
+       ofile->symbol_list_head = s;
+      ofile->symbol_list_tail = s;
+      /* And the block list */
+    }
+  if (b->vars_tail)
+    b->vars_tail->next = s;
+  else
+    b->vars_head = s;
+
+  b->vars_tail = s;
+  b->nvars++;
+  s->type = do_type (i);
+  s->where = do_where (i);
+  s->visible = do_visible (i);
+
+  tindex[i] = s;
+
+  /* We remember the lowest address in each section for each source file */
+
+  if (s->where->where == coff_where_memory
+      && s->type->type == coff_secdef_type)
+    {
+      struct coff_isection *is = cur_sfile->section + s->where->section->number;
+
+      if (!is->init)
+       {
+         is->low = s->where->offset;
+         is->high = s->where->offset + s->type->size;
+         is->init = 1;
+         is->parent = s->where->section;
+       }
+
+    }
+
+  if (s->type->type == coff_function_type)
+    last_function_symbol = s;
+
+  return i + sym->n_numaux + 1;
+}
+
+
+static
+struct coff_ofile *
+doit ()
+{
+  int i;
+  int infile = 0;
+  struct coff_ofile *head = (struct coff_ofile *) malloc (sizeof (struct coff_ofile));
+  ofile = head;
+  head->source_head = 0;
+  head->source_tail = 0;
+
+  do_sections_p1 (head);
+  push_scope (1);
+
+  for (i = 0; i < rawcount;)
+    {
+      struct internal_syment *sym = &rawsyms[i].u.syment;
+      switch (sym->n_sclass)
+       {
+       case C_FILE:
+         {
+           /* new source file announced */
+           struct coff_sfile *n = (struct coff_sfile *) malloc (sizeof (struct coff_sfile));
+           n->section = (struct coff_isection *) xcalloc (sizeof (struct coff_isection), abfd->section_count + 1);
+           cur_sfile = n;
+           n->name = sym->_n._n_nptr[1];
+           n->next = 0;
+
+           if (infile)
+             {
+               pop_scope ();
+             }
+           infile = 1;
+           push_scope (1);
+           file_scope = n->scope = top_scope;
+
+           if (head->source_tail)
+             head->source_tail->next = n;
+           else
+             head->source_head = n;
+           head->source_tail = n;
+           head->nsources++;
+           i += sym->n_numaux + 1;
+         }
+         break;
+       case C_FCN:
+         {
+           char *name = sym->_n._n_nptr[1];
+           if (name[1] == 'b')
+             {
+               /* Function start */
+               push_scope (0);
+               last_function_type->u.function.code = top_scope;
+               top_scope->sec = ofile->sections + sym->n_scnum;
+               top_scope->offset = sym->n_value;
+             }
+           else
+             {
+               top_scope->size = sym->n_value - top_scope->offset + 1;
+               pop_scope ();
+
+             }
+           i += sym->n_numaux + 1;
+         }
+         break;
+
+       case C_BLOCK:
+         {
+           char *name = sym->_n._n_nptr[1];
+           if (name[1] == 'b')
+             {
+               /* Block start */
+               push_scope (1);
+               top_scope->sec = ofile->sections + sym->n_scnum;
+               top_scope->offset = sym->n_value;
+
+             }
+           else
+             {
+               top_scope->size = sym->n_value - top_scope->offset + 1;
+               pop_scope ();
+             }
+           i += sym->n_numaux + 1;
+         }
+         break;
+       case C_REGPARM:
+       case C_ARG:
+         i = do_define (i, last_function_symbol->type->u.function.parameters);
+         break;
+       case C_MOS:
+       case C_MOU:
+       case C_FIELD:
+         i = do_define (i, last_struct->u.astructdef.elements);
+         break;
+       case C_MOE:
+         i = do_define (i, last_enum->u.aenumdef.elements);
+         break;
+       case C_STRTAG:
+       case C_ENTAG:
+       case C_UNTAG:
+         /* Various definition */
+         i = do_define (i, top_scope);
+         break;
+       case C_EXT:
+       case C_LABEL:
+         i = do_define (i, file_scope);
+         break;
+       case C_STAT:
+       case C_TPDEF:
+       case C_AUTO:
+       case C_REG:
+         i = do_define (i, top_scope);
+         break;
+       default:
+         abort ();
+       case C_EOS:
+         i += sym->n_numaux + 1;
+         break;
+       }
+    }
+  do_sections_p2 (head);
+  return head;
+}
+
+struct coff_ofile *
+coff_grok (inabfd)
+     bfd *inabfd;
+{
+  long storage;
+  struct coff_ofile *p;
+  abfd = inabfd;
+  storage = bfd_get_symtab_upper_bound (abfd);
+
+  if (storage < 0)
+    bfd_fatal (abfd->filename);
+
+  syms = (asymbol **) xmalloc (storage);
+  symcount = bfd_canonicalize_symtab (abfd, syms);
+  if (symcount < 0)
+    bfd_fatal (abfd->filename);
+  rawsyms = obj_raw_syments (abfd);
+  rawcount = obj_raw_syment_count (abfd);;
+  tindex = (struct coff_symbol **) (xcalloc (sizeof (struct coff_symbol *), rawcount));
+
+  p = doit (abfd);
+  return p;
+}
diff --git a/binutils/srconv.c b/binutils/srconv.c
new file mode 100644 (file)
index 0000000..e77a69c
--- /dev/null
@@ -0,0 +1,1908 @@
+/* srconv.c -- Sysroff conversion program
+   Copyright (C) 1994 Free Software Foundation, Inc.
+
+This file is part of GNU Binutils.
+
+This program 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 of the License, or
+(at your option) any later version.
+
+This program 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 this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* Written by Steve Chamberlain (sac@cygnus.com)
+
+   This program can be used to convert a coff object file
+   into a Hitachi OM/LM (Sysroff) format.
+
+   All debugging information is preserved */
+
+#include <bfd.h>
+#include <getopt.h>
+#include <stdio.h>
+#include <time.h>
+#include <libiberty.h>
+#include "sysroff.h"
+#include "coffgrok.h"
+
+#include "coff/internal.h"
+#include "../bfd/libcoff.h"
+
+#define PROGRAM_VERSION "1.3"
+/*#define FOOP1 1*/
+
+static int sh;
+static int h8300;
+static void wr_cs ();
+static void walk_tree_scope ();
+static void wr_globals ();
+
+static FILE *file;
+static bfd *abfd;
+static int debug = 0;
+static int quick = 0;
+
+static struct coff_ofile *tree;
+
+static int absolute_p;
+static int segmented_p;
+static int code;
+
+static int ids1[10000];
+static int ids2[10000];
+
+static int base1 = 0x18;
+static int base2 = 0x2018;
+
+char *
+xcalloc (a, b)
+     int a;
+     int b;
+{
+  char *r = xmalloc (a * b);
+  memset (r, 0, a * b);
+  return r;
+}
+
+static int
+get_member_id (x)
+     int x;
+{
+  if (ids2[x])
+    {
+      return ids2[x];
+    }
+  ids2[x] = base2++;
+  return ids2[x];
+}
+
+static int
+get_ordinary_id (x)
+     int x;
+{
+  if (ids1[x])
+    {
+      return ids1[x];
+    }
+  ids1[x] = base1++;
+  return ids1[x];
+}
+static char *
+section_translate (n)
+     char *n;
+{
+  if (strcmp (n, ".text") == 0)
+    return "P";
+  if (strcmp (n, ".data") == 0)
+    return "D";
+  if (strcmp (n, ".bss") == 0)
+    return "B";
+  return n;
+}
+
+
+
+#define DATE "940201073000";   /* Just a time on my birthday */
+
+
+static
+char *
+strip_suffix (name)
+     char *name;
+{
+  int i;
+  char *res;
+  for (i = 0; name[i] != 0 && name[i] != '.'; i++)
+    ;
+  res = (char *) xmalloc (i + 1);
+  memcpy (res, name, i);
+  res[i] = 0;
+  return res;
+}
+
+
+/* IT LEN stuff CS */
+static void
+checksum (file, ptr, size, code)
+     FILE *file;
+     char *ptr;
+     int size;
+     int code;
+{
+  int j;
+  int last;
+  int sum = 0;
+  int bytes = size / 8;
+  last = !(code & 0xff00);
+  if (size & 0x7)
+    abort ();
+  ptr[0] = code | (last ? 0x80 : 0);
+  ptr[1] = bytes + 1;
+
+  for (j = 0; j < bytes; j++)
+    {
+      sum += ptr[j];
+    }
+  /* Glue on a checksum too */
+  ptr[bytes] = ~sum;
+  fwrite (ptr, bytes + 1, 1, file);
+}
+
+
+
+
+static void
+writeINT (n, ptr, idx, size, file)
+     int n;
+     char *ptr;
+     int *idx;
+     int size;
+     FILE *file;
+{
+  int byte = *idx / 8;
+
+  if (size == -2)
+    size = 4;
+  if (size == -1)
+    size = 0;
+
+  if (byte > 240)
+    {
+      /* Lets write out that record and do another one */
+      checksum (file, ptr, *idx, code | 0x1000);
+      *idx = 16;
+      byte = *idx / 8;
+    }
+  switch (size)
+    {
+    case 0:
+      break;
+    case 1:
+      ptr[byte] = n;
+      break;
+    case 2:
+      ptr[byte + 0] = n >> 8;
+      ptr[byte + 1] = n;
+      break;
+    case 4:
+      ptr[byte + 0] = n >> 24;
+      ptr[byte + 1] = n >> 16;
+      ptr[byte + 2] = n >> 8;
+      ptr[byte + 3] = n >> 0;
+      break;
+    default:
+      abort ();
+    }
+  *idx += size * 8;
+}
+
+
+static void
+writeBITS (val, ptr, idx, size)
+     int val;
+     char *ptr;
+     int *idx;
+     int size;
+{
+  int byte = *idx / 8;
+  int bit = *idx % 8;
+  int old;
+  *idx += size;
+
+  old = ptr[byte];
+  /* Turn off all about to change bits */
+  old &= ~((~0 >> (8 - bit - size)) & ((1 << size) - 1));
+  /* Turn on the bits we want */
+  old |= (val & ((1 << size) - 1)) << (8 - bit - size);
+  ptr[byte] = old;
+}
+
+static void
+writeBARRAY (data, ptr, idx, size, file)
+     barray data;
+     char *ptr;
+     int *idx;
+     int size;
+     FILE *file;
+{
+  int i;
+  writeINT (data.len, ptr, idx, 1, file);
+  for (i = 0; i < data.len; i++)
+    {
+      writeINT (data.data[i], ptr, idx, 1, file);
+    }
+
+
+
+
+}
+static void
+writeCHARS (string, ptr, idx, size, file)
+     char *string;
+     char *ptr;
+     int *idx;
+     int size;
+     FILE *file;
+{
+  int i = *idx / 8;
+
+  if (i > 240)
+    {
+      /* Lets write out that record and do another one */
+      checksum (file, ptr, *idx, code | 0x1000);
+      *idx = 16;
+      i = *idx / 8;
+    }
+
+  if (size == 0)
+    {
+      /* Variable length string */
+      size = strlen (string);
+      ptr[i++] = size;
+    }
+
+
+  memcpy (ptr + i, string, size);
+  i += size;
+  *idx = i * 8;
+}
+
+#define SYSROFF_SWAP_OUT
+#include "sysroff.c"
+
+
+static char *rname_sh[] =
+{
+  "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7", "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15"
+};
+
+static char *rname_h8300[] =
+{
+  "ER0", "ER1", "ER2", "ER3", "ER4", "ER5", "ER6", "ER7", "PC", "CCR"
+};
+
+static void
+wr_tr ()
+{
+  struct IT_tr t;
+  sysroff_swap_tr_out (file, &t);
+}
+
+static void
+wr_un (ptr, sfile, first)
+     struct coff_ofile *ptr;
+     struct coff_sfile *sfile;
+     int first;
+{
+  struct IT_un un;
+  struct coff_symbol *s;
+
+  if (abfd->flags & EXEC_P)
+    un.format = FORMAT_LM;
+  else
+    un.format = FORMAT_OM;
+  un.spare1 = 0;
+  un.nsections = ptr->nsections - 1;   /*  Don't count the abs section */
+  un.nextdefs = 0;
+  un.nextrefs = 0;
+  /* Count all the undefined and defined variables with global scope */
+
+  if (first)
+    {
+      for (s = ptr->symbol_list_head; s; s = s->next_in_ofile_list)
+       {
+         if (s->visible->type == coff_vis_ext_def
+             || s->visible->type == coff_vis_common)
+           un.nextdefs++;
+
+         if (s->visible->type == coff_vis_ext_ref)
+           un.nextrefs++;
+       }
+    }
+  if (sh)
+    {
+      un.tool = "C_SH";
+    }
+  if (h8300)
+    {
+      un.tool = "C_H8/300H";
+    }
+  un.tcd = DATE;
+  un.linker = "L_GX00";
+  un.lcd = DATE;
+  un.name = sfile->name;
+  sysroff_swap_un_out (file, &un, 1);
+}
+
+
+static void
+wr_hd (p)
+     struct coff_ofile *p;
+{
+  struct IT_hd hd;
+
+
+
+  if (abfd->flags & EXEC_P)
+    {
+      hd.mt = MTYPE_ABS_LM;
+    }
+  else
+    {
+      hd.mt = MTYPE_OMS_OR_LMS;
+    }
+  hd.cd = DATE;
+
+  hd.nu = p->nsources;         /* Always one unit */
+  hd.code = 0;                 /* Always ASCII */
+  hd.ver = "0200";             /* Version 2.00 */
+  switch (abfd->arch_info->arch)
+    {
+    case bfd_arch_h8300:
+      hd.au = 8;
+      hd.si = 32;
+      hd.afl = 2;
+      hd.spcsz = 0;
+      hd.segsz = 0;
+      hd.segsh = 0;
+      hd.cpu = "H8300H";
+      h8300 = 1;
+      break;
+    case bfd_arch_sh:
+      hd.au = 8;
+      hd.si = 32;
+      hd.afl = 2;
+      hd.spcsz = 0;
+      hd.segsz = 0;
+      hd.segsh = 0;
+      hd.cpu = "SH";
+      sh = 1;
+      break;
+    }
+
+  if (!abfd->flags & EXEC_P)
+    {
+      hd.ep = 0;
+    }
+  else
+    {
+      hd.ep = 1;
+      hd.uan = 0;
+      hd.sa = 0;
+      hd.sad = 0;
+      hd.address = bfd_get_start_address (abfd);
+    }
+
+  hd.os = "";
+  hd.sys = "";
+  hd.mn = strip_suffix (abfd->filename);
+  sysroff_swap_hd_out (file, &hd);
+}
+
+
+static void
+wr_sh (p, sec)
+     struct coff_ofile *p;
+     struct coff_section *sec;
+{
+  struct IT_sh sh;
+  sh.unit = 0;
+  sh.section = sec->number;
+#ifdef FOOP1
+  sh.section = 0;
+#endif
+  sysroff_swap_sh_out (file, &sh);
+}
+
+
+static void
+wr_ob (p, section)
+     struct coff_ofile *p;
+     struct coff_section *section;
+{
+  int i;
+  int first = 1;
+  unsigned char stuff[200];
+
+  i = 0;
+  while (i < section->size)
+    {
+      struct IT_ob ob;
+      int todo = 200;          /* Copy in 200 byte lumps */
+      if (i + todo > section->size)
+       todo = section->size - i;
+
+      if (first)
+       {
+         ob.saf = 1;
+         if (abfd->flags & EXEC_P)
+           ob.address = section->address;
+         else
+           ob.address = 0;
+
+         first = 0;
+       }
+      else
+       {
+         ob.saf = 0;
+       }
+
+      ob.cpf = 0;              /* Never compress */
+      ob.data.len = todo;
+      bfd_get_section_contents (abfd, section->bfd_section, stuff, i, todo);
+      ob.data.data = stuff;
+      sysroff_swap_ob_out (file, &ob, i + todo < section->size);
+      i += todo;
+    }
+}
+
+static void
+wr_rl (ptr, sec)
+     struct coff_ofile *ptr;
+     struct coff_section *sec;
+{
+  int nr = sec->nrelocs;
+  int i;
+  for (i = 0; i < nr; i++)
+    {
+      struct coff_reloc *r = sec->relocs + i;
+      struct coff_symbol *ref;
+      struct IT_rl rl;
+      rl.apol = 0;
+      rl.boundary = 0;
+      rl.segment = 1;
+      rl.sign = 0;
+      rl.check = 0;
+      rl.addr = r->offset;
+      rl.bitloc = 0;
+      rl.flen = 32;            /* SH Specific */
+      /* What sort of reloc ? Look in the section to find out */
+      ref = r->symbol;
+      if (ref->visible->type == coff_vis_ext_ref)
+       {
+         rl.bcount = 4;        /* Always 4 for us */
+         rl.op = OP_EXT_REF;
+         rl.symn = ref->er_number;
+       }
+      else if (ref->visible->type == coff_vis_common)
+       {
+         rl.bcount = 11;       /* Always 11 for us */
+         rl.op = OP_SEC_REF;
+         rl.secn = ref->where->section->number;
+         rl.copcode_is_3 = 3;
+         rl.alength_is_4 = 4;
+         rl.addend = ref->where->offset - ref->where->section->address;
+         rl.aopcode_is_0x20 = 0x20;
+       }
+
+      else
+       {
+         rl.bcount = 11;       /* Always 11 for us */
+         rl.op = OP_SEC_REF;
+         rl.secn = ref->where->section->number;
+         rl.copcode_is_3 = 3;
+         rl.alength_is_4 = 4;
+         rl.addend = -ref->where->section->address;
+         rl.aopcode_is_0x20 = 0x20;
+       }
+      rl.end = 0xff;
+      if (rl.op == OP_SEC_REF
+         || rl.op == OP_EXT_REF)
+       {
+         sysroff_swap_rl_out (file, &rl);
+       }
+    }
+}
+
+static void
+wr_object_body (p)
+     struct coff_ofile *p;
+{
+  int i;
+  for (i = 1; i < p->nsections; i++)
+    {
+      wr_sh (p, p->sections + i);
+      wr_ob (p, p->sections + i);
+      wr_rl (p, p->sections + i);
+    }
+}
+
+static void
+wr_dps_start (sfile, section, scope, type, nest)
+     struct coff_sfile *sfile;
+     struct coff_section *section;
+     struct coff_scope *scope;
+     int type;
+{
+  struct IT_dps dps;
+  dps.end = 0;
+  dps.opt = 0;
+  dps.type = type;
+  if (scope->sec)
+    {
+      dps.san = scope->sec->number;
+      dps.address = scope->offset - find_base (sfile, scope->sec);
+      dps.block_size = scope->size;
+      if (debug)
+       {
+         printf ("DPS %s %d %x\n",
+                 sfile->name,
+                 nest,
+                 dps.address);
+
+       }
+    }
+
+  dps.nesting = nest;
+  dps.neg = 0x1001;
+  sysroff_swap_dps_out (file, &dps);
+}
+
+static void
+wr_dps_end (section, scope, type)
+     struct coff_section *section;
+     struct coff_scope *scope;
+     int type;
+{
+  struct IT_dps dps;
+  dps.end = 1;
+  dps.type = type;
+  sysroff_swap_dps_out (file, &dps);
+}
+
+static int *
+nints (x)
+     int x;
+{
+  return (int *) (xcalloc (sizeof (int), x));
+}
+
+static void walk_tree_symbol ();
+static void
+walk_tree_type_1 (sfile, symbol, type, nest)
+     struct coff_sfile *sfile;
+     struct coff_symbol *symbol;
+     struct coff_type *type;
+     int nest;
+{
+  switch (type->type)
+    {
+    case coff_secdef_type:
+    case coff_basic_type:
+      {
+       struct IT_dbt dbt;
+
+       switch (type->u.basic)
+         {
+         case T_NULL:
+         case T_VOID:
+           dbt.btype = BTYPE_VOID;
+           dbt.sign = BTYPE_UNSPEC;
+           dbt.fptype = FPTYPE_NOTSPEC;
+           break;
+         case T_CHAR:
+           dbt.btype = BTYPE_CHAR;
+           dbt.sign = BTYPE_UNSPEC;
+           dbt.fptype = FPTYPE_NOTSPEC;
+           break;
+         case T_SHORT:
+         case T_INT:
+         case T_LONG:
+           dbt.btype = BTYPE_INT;
+           dbt.sign = SIGN_SIGNED;
+           dbt.fptype = FPTYPE_NOTSPEC;
+           break;
+         case T_FLOAT:
+           dbt.btype = BTYPE_FLOAT;
+           dbt.fptype = FPTYPE_SINGLE;
+           break;
+         case T_DOUBLE:
+           dbt.btype = BTYPE_FLOAT;
+           dbt.fptype = FPTYPE_DOUBLE;
+           break;
+         case T_LNGDBL:
+           dbt.btype = BTYPE_FLOAT;
+           dbt.fptype = FPTYPE_EXTENDED;
+           break;
+         case T_UCHAR:
+           dbt.btype = BTYPE_CHAR;
+           dbt.sign = SIGN_UNSIGNED;
+           dbt.fptype = FPTYPE_NOTSPEC;
+           break;
+         case T_USHORT:
+         case T_UINT:
+         case T_ULONG:
+           dbt.btype = BTYPE_INT;
+           dbt.sign = SIGN_UNSIGNED;
+           dbt.fptype = FPTYPE_NOTSPEC;
+           break;
+         }
+       dbt.bitsize = type->size;
+       dbt.neg = 0x1001;
+       sysroff_swap_dbt_out (file, &dbt);
+       break;
+      }
+    case coff_pointer_type:
+      {
+       struct IT_dpt dpt;
+       walk_tree_type_1 (sfile, symbol, type->u.pointer.points_to, nest + 1);
+       dpt.neg = 0x1001;
+       sysroff_swap_dpt_out (file, &dpt);
+       break;
+      }
+
+    case coff_function_type:
+      {
+       struct IT_dfp dfp;
+       struct coff_symbol *param;
+       dfp.end = 0;
+       dfp.nparams = type->u.function.parameters->nvars;
+       dfp.neg = 0x1001;
+
+       walk_tree_type_1 (sfile, symbol, type->u.function.function_returns, nest + 1);
+
+       sysroff_swap_dfp_out (file, &dfp);
+
+       for (param = type->u.function.parameters->vars_head;
+            param;
+            param = param->next)
+         {
+           walk_tree_symbol (sfile, 0, param, nest);
+         }
+       dfp.end = 1;
+       sysroff_swap_dfp_out (file, &dfp);
+       break;
+      }
+
+    case coff_structdef_type:
+      {
+       struct IT_dbt dbt;
+       struct IT_dds dds;
+       struct coff_symbol *member;
+       dbt.btype = BTYPE_STRUCT;
+       dbt.bitsize = type->size;
+       dbt.sign = SIGN_UNSPEC;
+       dbt.fptype = FPTYPE_NOTSPEC;
+       dbt.sid = get_member_id (type->u.astructdef.idx);
+       dbt.neg = 0x1001;
+       sysroff_swap_dbt_out (file, &dbt);
+       dds.end = 0;
+       dds.neg = 0x1001;
+       sysroff_swap_dds_out (file, &dds);
+       for (member = type->u.astructdef.elements->vars_head;
+            member;
+            member = member->next)
+         {
+           walk_tree_symbol (sfile, 0, member, nest + 1);
+         }
+
+       dds.end = 1;
+       sysroff_swap_dds_out (file, &dds);
+
+      }
+      break;
+    case coff_structref_type:
+      {
+       struct IT_dbt dbt;
+       dbt.btype = BTYPE_TAG;
+       dbt.bitsize = type->size;
+       dbt.sign = SIGN_UNSPEC;
+       dbt.fptype = FPTYPE_NOTSPEC;
+       if (type->u.astructref.ref)
+         {
+           dbt.sid = get_member_id (type->u.astructref.ref->number);
+         }
+       else
+         {
+           dbt.sid = 0;
+         }
+
+       dbt.neg = 0x1001;
+       sysroff_swap_dbt_out (file, &dbt);
+      }
+      break;
+    case coff_array_type:
+      {
+       struct IT_dar dar;
+       int j;
+       int dims = 1;           /* Only output one dimension at a time */
+       dar.dims = dims;
+       dar.variable = nints (dims);
+       dar.subtype = nints (dims);
+       dar.spare = nints (dims);
+       dar.max_variable = nints (dims);
+       dar.maxspare = nints (dims);
+       dar.max = nints (dims);
+       dar.min_variable = nints (dims);
+       dar.min = nints (dims);
+       dar.minspare = nints (dims);
+       dar.neg = 0x1001;
+       for (j = 0; j < dims; j++)
+         {
+           dar.variable[j] = VARIABLE_FIXED;
+           dar.subtype[j] = SUB_INTEGER;
+           dar.max_variable[j] = 0;
+           dar.max[j] = type->u.array.dim;
+           dar.min_variable[j] = 0;
+           dar.min[j] = 1;     /* Why isn't this 0 ? */
+         }
+       walk_tree_type_1 (sfile, symbol, type->u.array.array_of, nest + 1);
+       sysroff_swap_dar_out (file, &dar);
+      }
+      break;
+    case coff_enumdef_type:
+      {
+       struct IT_dbt dbt;
+       struct IT_den den;
+       struct coff_symbol *member;
+       dbt.btype = BTYPE_ENUM;
+       dbt.bitsize = type->size;
+       dbt.sign = SIGN_UNSPEC;
+       dbt.fptype = FPTYPE_NOTSPEC;
+       dbt.sid = get_member_id (type->u.aenumdef.idx);
+       dbt.neg = 0x1001;
+       sysroff_swap_dbt_out (file, &dbt);
+
+       den.end = 0;
+       den.neg = 0x1001;
+       sysroff_swap_den_out (file, &den);
+       for (member = type->u.aenumdef.elements->vars_head;
+            member;
+            member = member->next)
+         {
+           walk_tree_symbol (sfile, 0, member, nest + 1);
+         }
+
+       den.end = 1;
+       sysroff_swap_den_out (file, &den);
+      }
+      break;
+
+      break;
+    case coff_enumref_type:
+      {
+       struct IT_dbt dbt;
+       dbt.btype = BTYPE_TAG;
+       dbt.bitsize = type->size;
+       dbt.sign = SIGN_UNSPEC;
+       dbt.fptype = FPTYPE_NOTSPEC;
+       dbt.sid = get_member_id (type->u.aenumref.ref->number);
+       dbt.neg = 0x1001;
+       sysroff_swap_dbt_out (file, &dbt);
+      }
+      break;
+    default:
+      abort ();
+    }
+}
+
+static void
+dty_start ()
+{
+  struct IT_dty dty;
+  dty.end = 0;
+  dty.neg = 0x1001;
+  sysroff_swap_dty_out (file, &dty);
+}
+
+static void
+dty_stop ()
+{
+  struct IT_dty dty;
+  dty.end = 0;
+  dty.neg = 0x1001;
+  dty.end = 1;
+  sysroff_swap_dty_out (file, &dty);
+}
+
+
+static void
+dump_tree_structure (sfile, symbol, type, nest)
+     struct coff_sfile *sfile;
+     struct coff_symbol *symbol;
+     struct coff_type *type;
+     int nest;
+{
+  if (symbol->type->type == coff_function_type)
+    {
+
+
+    }
+
+}
+
+
+static void 
+walk_tree_type (sfile, symbol, type, nest)
+
+     struct
+     coff_sfile *sfile;
+     struct coff_symbol *symbol;
+     struct coff_type *type;
+     int nest;
+{
+  if (symbol->type->type == coff_function_type)
+    {
+
+      struct IT_dty dty;
+      dty.end = 0;
+      dty.neg = 0x1001;
+
+      sysroff_swap_dty_out (file, &dty);
+      walk_tree_type_1 (sfile, symbol, type, nest);
+      dty.end = 1;
+      sysroff_swap_dty_out (file, &dty);
+
+      wr_dps_start (sfile, 
+                   symbol->where->section, 
+                   symbol->type->u.function.code, 
+                   BLOCK_TYPE_FUNCTION, nest);
+      wr_dps_start (sfile, symbol->where->section,
+                   symbol->type->u.function.code,
+                   BLOCK_TYPE_BLOCK, nest);
+      walk_tree_scope (symbol->where->section,
+                      sfile,
+                      symbol->type->u.function.code, 
+                      nest + 1, BLOCK_TYPE_BLOCK);
+
+      wr_dps_end (symbol->where->section, 
+                 symbol->type->u.function.code, 
+                 BLOCK_TYPE_BLOCK, nest);
+      wr_dps_end (symbol->where->section, 
+                 symbol->type->u.function.code, BLOCK_TYPE_FUNCTION, nest);
+
+    }
+  else
+    {
+      struct IT_dty dty;
+      dty.end = 0;
+      dty.neg = 0x1001;
+      sysroff_swap_dty_out (file, &dty);
+      walk_tree_type_1 (sfile, symbol, type, nest);
+      dty.end = 1;
+      sysroff_swap_dty_out (file, &dty);
+    }
+
+}
+
+
+
+static void
+walk_tree_symbol (sfile, section, symbol, nest)
+     struct coff_sfile *sfile;
+     struct coff_section *section;
+     struct coff_symbol *symbol;
+     int nest;
+{
+  struct IT_dsy dsy;
+
+
+    dsy.nesting = nest;
+
+    switch (symbol->type->type)
+      {
+      case coff_function_type:
+       dsy.type = STYPE_FUNC;
+       dsy.assign = 1;
+       break;
+      case coff_structref_type:
+      case coff_pointer_type:
+      case coff_array_type:
+      case coff_basic_type:
+      case coff_enumref_type:
+       dsy.type = STYPE_VAR;
+       dsy.assign = 1;
+       break;
+      case coff_enumdef_type:
+       dsy.type = STYPE_TAG;
+       dsy.assign = 0;
+       dsy.magic = 2;
+       break;
+      case coff_structdef_type:
+       dsy.type = STYPE_TAG;
+       dsy.assign = 0;
+       dsy.magic = symbol->type->u.astructdef.isstruct ? 0 : 1;
+       break;
+      case coff_secdef_type:
+       return;
+      default:
+       abort ();
+      }
+
+    if (symbol->where->where == coff_where_member_of_struct)
+      {
+       dsy.assign = 0;
+       dsy.type = STYPE_MEMBER;
+      }
+    if (symbol->where->where == coff_where_member_of_enum)
+      {
+       dsy.type = STYPE_ENUM;
+       dsy.assign = 0;
+       dsy.vallen = 4;
+       dsy.value = symbol->where->offset;
+      }
+
+    if (symbol->type->type == coff_structdef_type
+       || symbol->where->where == coff_where_entag
+       || symbol->where->where == coff_where_strtag)
+      {
+       dsy.snumber = get_member_id (symbol->number);
+      }
+    else
+      {
+       dsy.snumber = get_ordinary_id (symbol->number);
+      }
+
+
+    dsy.sname = symbol->name[0] == '_' ? symbol->name + 1 : symbol->name;
+
+    switch (symbol->visible->type)
+      {
+      case coff_vis_common:
+      case coff_vis_ext_def:
+       dsy.ainfo = AINFO_STATIC_EXT_DEF;
+       break;
+      case coff_vis_ext_ref:
+       dsy.ainfo = AINFO_STATIC_EXT_REF;
+       break;
+      case coff_vis_int_def:
+       dsy.ainfo = AINFO_STATIC_INT;
+       break;
+      case coff_vis_auto:
+      case coff_vis_autoparam:
+       dsy.ainfo = AINFO_AUTO;
+       break;
+      case coff_vis_register:
+      case coff_vis_regparam:
+       dsy.ainfo = AINFO_REG;
+       break;
+       break;
+      case coff_vis_tag:
+      case coff_vis_member_of_struct:
+      case coff_vis_member_of_enum:
+       break;
+      default:
+       abort ();
+      }
+
+    dsy.dlength = symbol->type->size;
+    switch (symbol->where->where)
+      {
+      case coff_where_memory:
+
+       dsy.section = symbol->where->section->number;
+#ifdef FOOP
+       dsy.section = 0;
+#endif
+       break;
+      case coff_where_member_of_struct:
+      case coff_where_member_of_enum:
+      case coff_where_stack:
+      case coff_where_register:
+      case coff_where_unknown:
+      case coff_where_strtag:
+
+      case coff_where_entag:
+      case coff_where_typedef:
+       break;
+      default:
+       abort ();
+      }
+
+    switch (symbol->where->where)
+      {
+      case coff_where_memory:
+       dsy.address = symbol->where->offset - find_base (sfile, symbol->where->section);
+       break;
+      case coff_where_stack:
+       dsy.address = symbol->where->offset;
+       break;
+      case coff_where_member_of_struct:
+
+
+       if (symbol->where->bitsize)
+         {
+           int bits = (symbol->where->offset * 8 + symbol->where->bitoffset);
+           dsy.bitunit = 1;
+           dsy.field_len = symbol->where->bitsize;
+           dsy.field_off = (bits / 32) * 4;
+           dsy.field_bitoff = bits % 32;
+         }
+       else
+         {
+           dsy.bitunit = 0;
+
+           dsy.field_len = symbol->type->size;
+           dsy.field_off = symbol->where->offset;
+         }
+       break;
+      case coff_where_member_of_enum:
+       /*      dsy.bitunit = 0;
+               dsy.field_len  = symbol->type->size;
+               dsy.field_off = symbol->where->offset;*/
+       break;
+      case coff_where_register:
+      case coff_where_unknown:
+      case coff_where_strtag:
+
+      case coff_where_entag:
+      case coff_where_typedef:
+       break;
+      default:
+       abort ();
+      }
+
+    if (symbol->where->where == coff_where_register)
+      {
+       if (sh)
+         dsy.reg = rname_sh[symbol->where->offset];
+       if (h8300)
+         dsy.reg = rname_h8300[symbol->where->offset];
+      }
+
+    switch (symbol->visible->type)
+      {
+      case coff_vis_common:
+       /* We do this 'cause common C symbols are treated as extdefs */
+      case coff_vis_ext_def:
+      case coff_vis_ext_ref:
+
+       dsy.ename = symbol->name;
+       break;
+
+      case coff_vis_regparam:
+      case coff_vis_autoparam:
+       dsy.type = STYPE_PARAMETER;
+       break;
+
+      case coff_vis_int_def:
+
+      case coff_vis_auto:
+      case coff_vis_register:
+      case coff_vis_tag:
+      case coff_vis_member_of_struct:
+      case coff_vis_member_of_enum:
+       break;
+      default:
+       abort ();
+      }
+
+    dsy.sfn = 0;
+    dsy.sln = 2;
+
+    dsy.neg = 0x1001;
+
+
+    sysroff_swap_dsy_out (file, &dsy);
+
+    walk_tree_type (sfile, symbol, symbol->type, nest);
+}
+
+
+static void
+walk_tree_scope (section, sfile, scope, nest, type)
+     struct coff_section *section;
+     struct coff_sfile *sfile;
+     struct coff_scope *scope;
+     int nest;
+     int type;
+{
+  struct coff_symbol *vars;
+  struct coff_scope *child;
+
+  if (scope->vars_head
+      || (scope->list_head && scope->list_head->vars_head))
+    {
+      wr_dps_start (sfile, section, scope, type, nest);
+
+      if (nest == 0)
+       wr_globals (tree, sfile, nest + 1);
+
+      for (vars = scope->vars_head; vars; vars = vars->next)
+       {
+         walk_tree_symbol (sfile, section, vars, nest);
+       }
+
+      for (child = scope->list_head; child; child = child->next)
+       {
+         walk_tree_scope (section, sfile, child, nest + 1, BLOCK_TYPE_BLOCK);
+       }
+
+      wr_dps_end (section, scope, type);
+    }
+}
+static void
+walk_tree_sfile (section, sfile)
+     struct coff_section *section;
+     struct coff_sfile *sfile;
+{
+  walk_tree_scope (section, sfile, sfile->scope, 0, BLOCK_TYPE_COMPUNIT);
+
+}
+
+static void
+wr_program_structure (p, sfile)
+     struct coff_ofile *p;
+     struct coff_sfile *sfile;
+{
+
+  walk_tree_sfile (p->sections + 4, sfile);
+
+}
+
+static void
+wr_du (p, sfile, n)
+     struct coff_ofile *p;
+     struct coff_sfile *sfile;
+     int n;
+{
+  struct IT_du du;
+  int lim;
+  struct coff_symbol *symbol;
+  static int incit = 0x500000;
+  int i;
+  int j;
+  int used = 0;
+  unsigned int *lowest = (unsigned *) nints (p->nsections);
+  unsigned int *highest = (unsigned *) nints (p->nsections);
+  du.format = abfd->flags & EXEC_P ? 0 : 1;
+  du.optimized = 0;
+  du.unit = n;
+  du.sections = p->nsections - 1;
+  du.san = (int *) xcalloc (sizeof (int), du.sections);
+  du.address = nints (du.sections);
+  du.length = nints (du.sections);
+
+  for (i = 0; i < du.sections; i++)
+    {
+      lowest[i] = ~0;
+      highest[i] = 0;
+    }
+
+  /* Look through all the symbols and try and work out the extents in this
+     source file */
+#if 0
+  for (symbol = sfile->scope->vars_head;
+       symbol;
+       symbol = symbol->next)
+    {
+      if (symbol->type->type == coff_secdef_type)
+       {
+         unsigned int low = symbol->where->offset;
+         unsigned int high = symbol->where->offset + symbol->type->size - 1;
+         struct coff_section *section = symbol->where->section;
+
+         int sn = section->number;
+         if (low < lowest[sn])
+           lowest[sn] = low;
+         if (high > highest[sn])
+           highest[sn] = high;
+       }
+    }
+
+
+  for (i = 0; i < du.sections; i++)
+    {
+      if (highest[i] == 0)
+       {
+         lowest[i] = highest[i] = incit;
+       }
+      du.san[used] = i;
+      du.length[used] = highest[i] - lowest[i];
+      du.address[used] = abfd->flags & EXEC_P ? lowest[i] : 0;
+      if (debug)
+       {
+         printf (" section %6s 0x%08x..0x%08x\n",
+                 p->sections[i + 1].name,
+                 lowest[i],
+                 highest[i]);
+       }
+      used++;
+    }
+
+#endif
+  lim = du.sections;
+  for (j = 0; j < lim; j++)
+    {
+      int src = j;
+      int dst = j;
+      du.san[dst] = dst;
+      if (sfile->section[src].init)
+       {
+         du.length[dst] 
+           = sfile->section[src].high - sfile->section[src].low + 1;
+         du.address[dst] 
+           = sfile->section[src].low;
+       }
+      else
+       {
+         du.length[dst] = 0;
+         du.address[dst] = 0;
+       }
+      if (debug)
+       {
+         if (sfile->section[src].parent)
+           {
+             printf (" section %6s 0x%08x..0x%08x\n",
+                     sfile->section[src].parent->name,
+                     du.address[dst],
+                     du.address[dst] + du.length[dst] - 1);
+           }
+       }
+      du.sections = dst + 1;
+    }
+
+  du.tool = "c_gcc";
+  du.date = DATE;
+
+  sysroff_swap_du_out (file, &du);
+}
+
+static void
+wr_dus (p, sfile)
+     struct coff_ofile *p;
+     struct coff_sfile *sfile;
+{
+
+  struct IT_dus dus;
+  int i;
+
+  dus.efn = 0x1001;
+  dus.ns = 1 ; /* p->nsources; sac 14 jul 94 */
+  dus.drb = nints (dus.ns);
+  dus.fname = (char **) xcalloc (sizeof (char *), dus.ns);
+  dus.spare = nints (dus.ns);
+  dus.ndir = 0;
+  /* Find the filenames */
+#if 0
+  i = 0;
+
+  for (sfile = p->source_head;
+       sfile;
+       sfile = sfile->next)
+    {
+      dus.drb[i] = 0;
+      dus.fname[i] = sfile->name;
+      i++;
+    }
+#else
+  dus.drb[0] = 0;
+  dus.fname[0] = sfile->name;
+#endif
+
+  sysroff_swap_dus_out (file, &dus);
+
+}
+
+/* Find the offset of the .text section for this sfile in the
+    .text section for the output file */
+
+static int
+find_base (sfile, section)
+     struct coff_sfile *sfile;
+     struct coff_section *section;
+{
+  return sfile->section[section->number].low;
+}
+static void
+wr_dln (p, sfile, n)
+     struct coff_ofile *p;
+     struct coff_sfile *sfile;
+     int n;
+
+{
+#if 0
+  if (n == 0)
+    {
+      /* Count up all the linenumbers */
+      struct coff_symbol *sy;
+      int lc = 0;
+      struct IT_dln dln;
+
+      int idx;
+
+      for (sy = p->symbol_list_head;
+          sy;
+          sy = sy->next_in_ofile_list)
+       {
+         struct coff_type *t = sy->type;
+         if (t->type == coff_function_type)
+           {
+             struct coff_line *l = t->u.function.lines;
+             lc += l->nlines;
+           }
+       }
+
+      dln.sfn = nints (lc);
+      dln.sln = nints (lc);
+      dln.lln = nints (lc);
+      dln.section = nints (lc);
+
+      dln.from_address = nints (lc);
+      dln.to_address = nints (lc);
+
+
+      dln.neg = 0x1001;
+
+      dln.nln = lc;
+
+      /* Run through once more and fill up the structure */
+      idx = 0;
+      for (sy = p->symbol_list_head;
+          sy;
+          sy = sy->next_in_ofile_list)
+       {
+         if (sy->type->type == coff_function_type)
+           {
+             int i;
+             struct coff_line *l = sy->type->u.function.lines;
+             for (i = 0; i < l->nlines; i++)
+               {
+                 dln.section[idx] = sy->where->section->number;
+                 dln.sfn[idx] = n;
+                 dln.sln[idx] = l->lines[i];
+                 dln.from_address[idx] = l->addresses[i];
+                 if (idx)
+                   dln.to_address[idx - 1] = dln.from_address[idx];
+                 idx++;
+               }
+           }
+         n++;
+       }
+      sysroff_swap_dln_out (file, &dln);
+    }
+
+#endif
+#if 1
+  /* Count up all the linenumbers */
+
+  struct coff_symbol *sy;
+  int lc = 0;
+  struct IT_dln dln;
+
+  int idx;
+
+  for (sy = sfile->scope->vars_head;
+       sy;
+       sy = sy->next)
+    {
+      struct coff_type *t = sy->type;
+      if (t->type == coff_function_type)
+       {
+         struct coff_line *l = t->u.function.lines;
+         if (l)
+           lc += l->nlines;
+       }
+    }
+
+  dln.sfn = nints (lc);
+  dln.sln = nints (lc);
+  dln.cc = nints (lc);
+  dln.section = nints (lc);
+
+  dln.from_address = nints (lc);
+  dln.to_address = nints (lc);
+
+
+  dln.neg = 0x1001;
+
+  dln.nln = lc;
+
+  /* Run through once more and fill up the structure */
+  idx = 0;
+  for (sy = sfile->scope->vars_head;
+       sy;
+       sy = sy->next)
+    {
+      if (sy->type->type == coff_function_type)
+       {
+         int i;
+         struct coff_line *l = sy->type->u.function.lines;
+         if (l) {
+           int base = find_base (sfile, sy->where->section);
+           for (i = 0; i < l->nlines; i++)
+             {
+               dln.section[idx] = sy->where->section->number;
+               dln.sfn[idx] = 0;
+               dln.sln[idx] = l->lines[i];
+               dln.from_address[idx] = 
+                 l->addresses[i] + sy->where->section->address - base;
+               dln.cc[idx] = 0;
+               if (idx)
+                 dln.to_address[idx - 1] = dln.from_address[idx];
+               idx++;
+
+             }
+           dln.to_address[idx - 1] = dln.from_address[idx - 1] + 2;
+         }
+       }
+    }
+  if (lc)
+    sysroff_swap_dln_out (file, &dln);
+#endif
+}
+
+/* Write the global symbols out to the debug info */
+static void
+wr_globals (p, sfile, n)
+     struct coff_ofile *p;
+     struct coff_sfile *sfile;
+     int n;
+{
+  struct coff_symbol *sy;
+  for (sy = p->symbol_list_head;
+       sy;
+       sy = sy->next_in_ofile_list)
+    {
+      if (sy->visible->type == coff_vis_ext_def
+         || sy->visible->type == coff_vis_ext_ref)
+       {
+         /* Only write out symbols if they belong to
+            the current source file */
+         if (sy->sfile == sfile)
+           walk_tree_symbol (sfile, 0, sy, 0);
+
+       }
+    }
+}
+
+static void
+wr_debug (p)
+     struct coff_ofile *p;
+{
+  struct coff_sfile *sfile;
+  int n = 0;
+  for (sfile = p->source_head;
+       sfile;
+       sfile = sfile->next)
+
+    {
+      if (debug)
+       {
+         printf ("%s\n", sfile->name);
+       }
+      wr_du (p, sfile, n);
+      wr_dus (p, sfile);
+      wr_program_structure (p, sfile, n);
+      wr_dln (p, sfile, n);
+      n++;
+    }
+}
+static void
+wr_cs ()
+{
+  /* It seems that the CS struct is not normal - the size is wrong
+     heres one I prepared earlier.. */
+  static char b[] =
+  {0x80, 0x21, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x80, 0x80,
+   0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x80, 0x00,
+   0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0xde};
+  fwrite (b, 1, sizeof (b), file);
+}
+
+/* Write out the SC records for a unit.  Create an SC
+   for all the sections which appear in the output file, even
+   if there isn't an equivalent one on the input */
+
+static void
+wr_sc (ptr, sfile)
+     struct coff_ofile *ptr;
+     struct coff_sfile *sfile;
+{
+  int i;
+  /* First work out the total number of sections */
+
+  int total_sec = ptr->nsections;
+
+  struct myinfo
+    {
+      struct coff_section *sec;
+      struct coff_symbol *symbol;
+    } myinfo;
+  struct coff_symbol *symbol;
+
+  struct myinfo *info
+  = (struct myinfo *) calloc (total_sec, sizeof (struct myinfo));
+
+
+
+  for (i = 0; i < total_sec; i++)
+    {
+      info[i].sec = ptr->sections + i;
+      info[i].symbol = 0;
+    }
+
+  for (symbol = sfile->scope->vars_head;
+       symbol;
+       symbol = symbol->next)
+    {
+
+      if (symbol->type->type == coff_secdef_type)
+       {
+         for (i = 0; i < total_sec; i++)
+           {
+             if (symbol->where->section == info[i].sec)
+               {
+                 info[i].symbol = symbol;
+                 break;
+               }
+           }
+       }
+    }
+
+  /* Now output all the section info, and fake up some stuff for sections
+     we don't have */
+
+  for (i = 1; i < total_sec; i++)
+    {
+      struct IT_sc sc;
+      char *name;
+      symbol = info[i].symbol;
+
+      if (!symbol)
+       {
+         /* Don't have a symbol set aside for this section, which means that nothing
+            in this file does anything for the section. */
+         sc.format = !(abfd->flags & EXEC_P);
+         sc.addr = 0;
+         sc.length = 0;
+         name = info[i].sec->name;
+       }
+      else
+       {
+         unsigned int low = symbol->where->offset;
+         unsigned int high = symbol->where->offset + symbol->type->size - 1;
+
+         if (abfd->flags & EXEC_P)
+           {
+             sc.format = 0;
+             sc.addr = symbol->where->offset;
+           }
+         else
+           {
+             sc.format = 1;
+             sc.addr = 0;
+           }
+         sc.length = symbol->type->size;
+         name = symbol->name;
+       }
+
+      sc.align = 4;
+
+      sc.concat = CONCAT_SIMPLE;
+      sc.read = 3;
+      sc.write = 3;
+      sc.exec = 3;
+      sc.init = 3;
+      sc.mode = 3;
+      sc.spare = 0;
+      sc.spare1 = 0;           /* If not zero, then it doesn't work */
+      sc.name = section_translate (name);
+      if (strlen (sc.name) == 1)
+       {
+         switch (sc.name[0])
+           {
+           case 'D':
+           case 'B':
+             sc.contents = CONTENTS_DATA;
+             break;
+           default:
+             sc.contents = CONTENTS_CODE;
+           }
+       }
+
+
+      sysroff_swap_sc_out (file, &sc);
+
+
+
+    }
+
+}
+
+static void
+wr_er (ptr, sfile, first)
+     struct coff_ofile *ptr;
+     struct coff_sfile *sfile;
+     int first;
+{
+  int idx = 0;
+  struct coff_symbol *sym;
+  if (first)
+    {
+      for (sym = ptr->symbol_list_head; sym; sym = sym->next_in_ofile_list)
+       {
+         if (sym->visible->type == coff_vis_ext_ref)
+           {
+             struct IT_er er;
+             er.type = ER_NOTSPEC;
+             er.name = sym->name;
+             sysroff_swap_er_out (file, &er);
+             sym->er_number = idx++;
+
+           }
+       }
+    }
+}
+
+static void
+wr_ed (ptr, sfile, first)
+     struct coff_ofile *ptr;
+     struct coff_file *sfile;
+     int first;
+{
+  struct coff_symbol *s;
+  if (first)
+    {
+      for (s = ptr->symbol_list_head; s; s = s->next_in_ofile_list)
+       {
+         if (s->visible->type == coff_vis_ext_def
+             || s->visible->type == coff_vis_common)
+           {
+             struct IT_ed ed;
+
+             ed.section = s->where->section->number;
+
+             if (s->where->section->data)
+               {
+                 ed.type = ED_TYPE_DATA;
+               }
+             else if (s->where->section->code & SEC_CODE)
+               {
+                 ed.type = ED_TYPE_ENTRY;
+               }
+             else
+               {
+                 ed.type = ED_TYPE_NOTSPEC;
+                 ed.type = ED_TYPE_DATA;
+               }
+             ed.address = s->where->offset - s->where->section->address;
+             ed.name = s->name;
+             sysroff_swap_ed_out (file, &ed);
+           }
+       }
+    }
+}
+
+static void
+wr_unit_info (ptr)
+     struct coff_ofile *ptr;
+{
+  struct coff_sfile *sfile;
+  int first = 1;
+  for (sfile = ptr->source_head;
+       sfile;
+       sfile = sfile->next)
+    {
+      wr_un (ptr, sfile, first);
+      wr_sc (ptr, sfile, first);
+      wr_er (ptr, sfile, first);
+      wr_ed (ptr, sfile, first);
+      first = 0;
+    }
+}
+
+static void
+wr_module (p)
+     struct coff_ofile *p;
+{
+  wr_cs ();
+  wr_hd (p);
+  wr_unit_info (p);
+  wr_object_body (p);
+  wr_debug (p);
+  wr_tr ();
+}
+
+static int
+align (x)
+     int x;
+{
+  return (x + 3) & ~3;
+}
+
+/* Find all the common variables and turn them into
+   ordinary defs - dunno why, but thats what hitachi does with 'em */
+
+static void
+prescan (tree)
+     struct coff_ofile *tree;
+{
+  struct coff_symbol *s;
+  struct coff_section *common_section;
+  /* Find the common section - always section 3 */
+  common_section = tree->sections + 3;
+  for (s = tree->symbol_list_head;
+       s;
+       s = s->next_in_ofile_list)
+    {
+      if (s->visible->type == coff_vis_common)
+       {
+         struct coff_where *w = s->where;
+         /*      s->visible->type = coff_vis_ext_def; leave it as common */
+         common_section->size = align (common_section->size);
+         w->offset = common_section->size + common_section->address;
+         w->section = common_section;
+         common_section->size += s->type->size;
+         common_section->size = align (common_section->size);
+       }
+    }
+}
+
+char *program_name;
+
+static void
+show_usage (file, status)
+     FILE *file;
+     int status;
+{
+  fprintf (file, "Usage: %s [-dhVq] in-file [out-file]\n", program_name);
+  exit (status);
+}
+
+static void
+show_help ()
+{
+  printf ("%s: Convert a COFF object file into a SYSROFF object file\n",
+         program_name);
+  show_usage (stdout, 0);
+}
+
+
+
+int
+main (ac, av)
+     int ac;
+     char *av[];
+{
+  int opt;
+  static struct option long_options[] =
+  {
+    {"debug", no_argument, 0, 'd'},
+    {"quick", no_argument, 0, 'q'},
+    {"help", no_argument, 0, 'h'},
+    {"version", no_argument, 0, 'V'},
+    {NULL, no_argument, 0, 0}
+  };
+  char **matching;
+  char *input_file;
+
+  char *output_file;
+  program_name = av[0];
+  xmalloc_set_program_name (program_name);
+
+  while ((opt = getopt_long (ac, av, "dhVq", long_options,
+                            (int *) NULL))
+        != EOF)
+    {
+      switch (opt)
+       {
+       case 'q':
+         quick = 1;
+         break;
+       case 'd':
+         debug = 1;
+         break;
+       case 'h':
+         show_help ();
+         /*NOTREACHED*/
+       case 'V':
+         printf ("GNU %s version %s\n", program_name, PROGRAM_VERSION);
+         exit (0);
+         /*NOTREACHED*/
+       case 0:
+         break;
+       default:
+         show_usage (stderr, 1);
+         /*NOTREACHED*/
+       }
+    }
+
+  /* The input and output files may be named on the command line.  */
+  output_file = NULL;
+  if (optind < ac)
+    {
+      input_file = av[optind];
+      ++optind;
+      if (optind < ac)
+       {
+         output_file = av[optind];
+         ++optind;
+         if (optind < ac)
+           show_usage (stderr, 1);
+         if (strcmp (input_file, output_file) == 0)
+           {
+             fprintf (stderr,
+                      "%s: input and output files must be different\n",
+                      program_name);
+             exit (1);
+           }
+       }
+    }
+
+  if (!input_file)
+    {
+      fprintf (stderr, "%s: no input file specified\n",
+              program_name);
+      exit (1);
+    }
+
+  if (!output_file)
+    {
+      /* Take a .o off the input file and stick on a .obj.  If
+        it doesn't end in .o, then stick a .obj on anyway */
+
+      int len = strlen (input_file);
+      output_file = xmalloc (len + 5);
+      strcpy (output_file, input_file);
+      if (len > 3
+         && output_file[len - 2] == '.'
+         && output_file[len - 1] == 'o')
+       {
+         output_file[len] = 'b';
+         output_file[len + 1] = 'j';
+         output_file[len + 2] = 0;
+       }
+      else
+       {
+         strcat (output_file, ".obj");
+       }
+    }
+
+  abfd = bfd_openr (input_file, 0);
+
+  if (!abfd)
+    bfd_fatal (input_file);
+
+  if (!bfd_check_format_matches (abfd, bfd_object, &matching))
+    {
+      bfd_nonfatal (input_file);
+      if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
+       {
+         list_matching_formats (matching);
+         free (matching);
+       }
+      exit (1);
+    }
+
+  file = fopen (output_file, "w");
+
+  if (!file)
+    {
+      fprintf (stderr, "%s: unable to open output file %s\n",
+              program_name, output_file);
+      exit (1);
+    }
+
+  tree = coff_grok (abfd);
+  prescan (tree);
+  wr_module (tree);
+  return 0;
+}