Back to index

cell-binutils  2.17cvs20070401
srconv.c
Go to the documentation of this file.
00001 /* srconv.c -- Sysroff conversion program
00002    Copyright 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
00003    2005, 2007 Free Software Foundation, Inc.
00004 
00005    This file is part of GNU Binutils.
00006 
00007    This program is free software; you can redistribute it and/or modify
00008    it under the terms of the GNU General Public License as published by
00009    the Free Software Foundation; either version 2 of the License, or
00010    (at your option) any later version.
00011 
00012    This program is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015    GNU General Public License for more details.
00016 
00017    You should have received a copy of the GNU General Public License
00018    along with this program; if not, write to the Free Software
00019    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
00020    02110-1301, USA.  */
00021 
00022 /* Written by Steve Chamberlain (sac@cygnus.com)
00023 
00024    This program can be used to convert a coff object file
00025    into a Hitachi OM/LM (Sysroff) format.
00026 
00027    All debugging information is preserved */
00028 
00029 #include "bfd.h"
00030 #include "bucomm.h"
00031 #include "sysroff.h"
00032 #include "coffgrok.h"
00033 #include "libiberty.h"
00034 #include "getopt.h"
00035 
00036 #include "coff/internal.h"
00037 #include "../bfd/libcoff.h"
00038 
00039 /*#define FOOP1 1 */
00040 
00041 static int addrsize;
00042 static char *toolname;
00043 static char **rnames;
00044 
00045 static int get_member_id (int);
00046 static int get_ordinary_id (int);
00047 static char *section_translate (char *);
00048 static char *strip_suffix (char *);
00049 static void checksum (FILE *, unsigned char *, int, int);
00050 static void writeINT (int, unsigned char *, int *, int, FILE *);
00051 static void writeBITS (int, unsigned char *, int *, int);
00052 static void writeBARRAY (barray, unsigned char *, int *, int, FILE *);
00053 static void writeCHARS (char *, unsigned char *, int *, int, FILE *);
00054 static void wr_tr (void);
00055 static void wr_un (struct coff_ofile *, struct coff_sfile *, int, int);
00056 static void wr_hd (struct coff_ofile *);
00057 static void wr_sh (struct coff_ofile *, struct coff_section *);
00058 static void wr_ob (struct coff_ofile *, struct coff_section *);
00059 static void wr_rl (struct coff_ofile *, struct coff_section *);
00060 static void wr_object_body (struct coff_ofile *);
00061 static void wr_dps_start
00062   (struct coff_sfile *, struct coff_section *, struct coff_scope *, int, int);
00063 static void wr_dps_end (struct coff_section *, struct coff_scope *, int);
00064 static int *nints (int);
00065 static void walk_tree_type_1
00066   (struct coff_sfile *, struct coff_symbol *, struct coff_type *, int);
00067 static void walk_tree_type
00068   (struct coff_sfile *, struct coff_symbol *, struct coff_type *, int);
00069 static void walk_tree_symbol
00070   (struct coff_sfile *, struct coff_section *, struct coff_symbol *, int);
00071 static void walk_tree_scope
00072   (struct coff_section *, struct coff_sfile *, struct coff_scope *, int, int);
00073 static void walk_tree_sfile (struct coff_section *, struct coff_sfile *);
00074 static void wr_program_structure (struct coff_ofile *, struct coff_sfile *);
00075 static void wr_du (struct coff_ofile *, struct coff_sfile *, int);
00076 static void wr_dus (struct coff_ofile *, struct coff_sfile *);
00077 static int find_base (struct coff_sfile *, struct coff_section *);
00078 static void wr_dln (struct coff_ofile *, struct coff_sfile *, int);
00079 static void wr_globals (struct coff_ofile *, struct coff_sfile *, int);
00080 static void wr_debug (struct coff_ofile *);
00081 static void wr_cs (void);
00082 static int wr_sc (struct coff_ofile *, struct coff_sfile *);
00083 static void wr_er (struct coff_ofile *, struct coff_sfile *, int);
00084 static void wr_ed (struct coff_ofile *, struct coff_sfile *, int);
00085 static void wr_unit_info (struct coff_ofile *);
00086 static void wr_module (struct coff_ofile *);
00087 static int align (int);
00088 static void prescan (struct coff_ofile *);
00089 static void show_usage (FILE *, int);
00090 extern int main (int, char **);
00091 
00092 static FILE *file;
00093 static bfd *abfd;
00094 static int debug = 0;
00095 static int quick = 0;
00096 static int noprescan = 0;
00097 static struct coff_ofile *tree;
00098 /* Obsolete ??
00099    static int absolute_p;
00100  */
00101 
00102 static int segmented_p;
00103 static int code;
00104 
00105 static int ids1[20000];
00106 static int ids2[20000];
00107 
00108 static int base1 = 0x18;
00109 static int base2 = 0x2018;
00110 
00111 static int
00112 get_member_id (int x)
00113 {
00114   if (ids2[x])
00115     return ids2[x];
00116 
00117   ids2[x] = base2++;
00118   return ids2[x];
00119 }
00120 
00121 static int
00122 get_ordinary_id (int x)
00123 {
00124   if (ids1[x])
00125     return ids1[x];
00126 
00127   ids1[x] = base1++;
00128   return ids1[x];
00129 }
00130 static char *
00131 section_translate (char *n)
00132 {
00133   if (strcmp (n, ".text") == 0)
00134     return "P";
00135   if (strcmp (n, ".data") == 0)
00136     return "D";
00137   if (strcmp (n, ".bss") == 0)
00138     return "B";
00139   return n;
00140 }
00141 
00142 #define DATE "940201073000";       /* Just a time on my birthday */
00143 
00144 static
00145 char *
00146 strip_suffix (char *name)
00147 {
00148   int i;
00149   char *res;
00150 
00151   for (i = 0; name[i] != 0 && name[i] != '.'; i++)
00152     ;
00153   res = (char *) xmalloc (i + 1);
00154   memcpy (res, name, i);
00155   res[i] = 0;
00156   return res;
00157 }
00158 
00159 /* IT LEN stuff CS */
00160 static void
00161 checksum (FILE *file, unsigned char *ptr, int size, int code)
00162 {
00163   int j;
00164   int last;
00165   int sum = 0;
00166   int bytes = size / 8;
00167 
00168   last = !(code & 0xff00);
00169   if (size & 0x7)
00170     abort ();
00171   ptr[0] = code | (last ? 0x80 : 0);
00172   ptr[1] = bytes + 1;
00173 
00174   for (j = 0; j < bytes; j++)
00175     sum += ptr[j];
00176 
00177   /* Glue on a checksum too.  */
00178   ptr[bytes] = ~sum;
00179   fwrite (ptr, bytes + 1, 1, file);
00180 }
00181 
00182 
00183 static void
00184 writeINT (int n, unsigned char *ptr, int *idx, int size, FILE *file)
00185 {
00186   int byte = *idx / 8;
00187 
00188   if (size == -2)
00189     size = addrsize;
00190   else if (size == -1)
00191     size = 0;
00192 
00193   if (byte > 240)
00194     {
00195       /* Lets write out that record and do another one.  */
00196       checksum (file, ptr, *idx, code | 0x1000);
00197       *idx = 16;
00198       byte = *idx / 8;
00199     }
00200 
00201   switch (size)
00202     {
00203     case 0:
00204       break;
00205     case 1:
00206       ptr[byte] = n;
00207       break;
00208     case 2:
00209       ptr[byte + 0] = n >> 8;
00210       ptr[byte + 1] = n;
00211       break;
00212     case 4:
00213       ptr[byte + 0] = n >> 24;
00214       ptr[byte + 1] = n >> 16;
00215       ptr[byte + 2] = n >> 8;
00216       ptr[byte + 3] = n >> 0;
00217       break;
00218     default:
00219       abort ();
00220     }
00221   *idx += size * 8;
00222 }
00223 
00224 static void
00225 writeBITS (int val, unsigned char *ptr, int *idx, int size)
00226 {
00227   int byte = *idx / 8;
00228   int bit = *idx % 8;
00229   int old;
00230 
00231   *idx += size;
00232 
00233   old = ptr[byte];
00234   /* Turn off all about to change bits.  */
00235   old &= ~((~0 >> (8 - bit - size)) & ((1 << size) - 1));
00236   /* Turn on the bits we want.  */
00237   old |= (val & ((1 << size) - 1)) << (8 - bit - size);
00238   ptr[byte] = old;
00239 }
00240 
00241 static void
00242 writeBARRAY (barray data, unsigned char *ptr, int *idx,
00243             int size ATTRIBUTE_UNUSED, FILE *file)
00244 {
00245   int i;
00246 
00247   writeINT (data.len, ptr, idx, 1, file);
00248   for (i = 0; i < data.len; i++)
00249     writeINT (data.data[i], ptr, idx, 1, file);
00250 }
00251 
00252 static void
00253 writeCHARS (char *string, unsigned char *ptr, int *idx, int size, FILE *file)
00254 {
00255   int i = *idx / 8;
00256 
00257   if (i > 240)
00258     {
00259       /* Lets write out that record and do another one.  */
00260       checksum (file, ptr, *idx, code | 0x1000);
00261       *idx = 16;
00262       i = *idx / 8;
00263     }
00264 
00265   if (size == 0)
00266     {
00267       /* Variable length string.  */
00268       size = strlen (string);
00269       ptr[i++] = size;
00270     }
00271 
00272   /* BUG WAITING TO HAPPEN.  */
00273   memcpy (ptr + i, string, size);
00274   i += size;
00275   *idx = i * 8;
00276 }
00277 
00278 #define SYSROFF_SWAP_OUT
00279 #include "sysroff.c"
00280 
00281 static char *rname_sh[] =
00282 {
00283   "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7", "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15"
00284 };
00285 
00286 static char *rname_h8300[] =
00287 {
00288   "ER0", "ER1", "ER2", "ER3", "ER4", "ER5", "ER6", "ER7", "PC", "CCR"
00289 };
00290 
00291 static void
00292 wr_tr (void)
00293 {
00294   /* The TR block is not normal - it doesn't have any contents.  */
00295 
00296   static char b[] =
00297     {
00298       0xff,                 /* IT */
00299       0x03,                 /* RL */
00300       0xfd,                 /* CS */
00301     };
00302   fwrite (b, 1, sizeof (b), file);
00303 }
00304 
00305 static void
00306 wr_un (struct coff_ofile *ptr, struct coff_sfile *sfile, int first,
00307        int nsecs ATTRIBUTE_UNUSED)
00308 {
00309   struct IT_un un;
00310   struct coff_symbol *s;
00311 
00312   un.spare1 = 0;
00313 
00314   if (bfd_get_file_flags (abfd) & EXEC_P)
00315     un.format = FORMAT_LM;
00316   else
00317     un.format = FORMAT_OM;
00318   un.spare1 = 0;
00319 
00320   /* Don't count the abs section.  */
00321   un.nsections = ptr->nsections - 1;
00322 
00323   un.nextdefs = 0;
00324   un.nextrefs = 0;
00325   /* Count all the undefined and defined variables with global scope.  */
00326 
00327   if (first)
00328     {
00329       for (s = ptr->symbol_list_head; s; s = s->next_in_ofile_list)
00330        {
00331          if (s->visible->type == coff_vis_ext_def
00332              || s->visible->type == coff_vis_common)
00333            un.nextdefs++;
00334 
00335          if (s->visible->type == coff_vis_ext_ref)
00336            un.nextrefs++;
00337        }
00338     }
00339   un.tool = toolname;
00340   un.tcd = DATE;
00341   un.linker = "L_GX00";
00342   un.lcd = DATE;
00343   un.name = sfile->name;
00344   sysroff_swap_un_out (file, &un);
00345 }
00346 
00347 static void
00348 wr_hd (struct coff_ofile *p)
00349 {
00350   struct IT_hd hd;
00351 
00352   hd.spare1 = 0;
00353   if (bfd_get_file_flags (abfd) & EXEC_P)
00354     hd.mt = MTYPE_ABS_LM;
00355   else
00356     hd.mt = MTYPE_OMS_OR_LMS;
00357 
00358   hd.cd = DATE;
00359 
00360   hd.nu = p->nsources;             /* Always one unit */
00361   hd.code = 0;                     /* Always ASCII */
00362   hd.ver = "0200";          /* Version 2.00 */
00363 
00364   switch (bfd_get_arch (abfd))
00365     {
00366     case bfd_arch_h8300:
00367       hd.au = 8;
00368       hd.si = 0;
00369       hd.spcsz = 32;
00370       hd.segsz = 0;
00371       hd.segsh = 0;
00372       switch (bfd_get_mach (abfd))
00373        {
00374        case bfd_mach_h8300:
00375          hd.cpu = "H8300";
00376          hd.afl = 2;
00377          addrsize = 2;
00378          toolname = "C_H8/300";
00379          break;
00380        case bfd_mach_h8300h:
00381          hd.cpu = "H8300H";
00382          hd.afl = 4;
00383          addrsize = 4;
00384          toolname = "C_H8/300H";
00385          break;
00386        case bfd_mach_h8300s:
00387          hd.cpu = "H8300S";
00388          hd.afl = 4;
00389          addrsize = 4;
00390          toolname = "C_H8/300S";
00391          break;
00392        default:
00393          abort();
00394        }
00395       rnames = rname_h8300;
00396       break;
00397     case bfd_arch_sh:
00398       hd.au = 8;
00399       hd.si = 0;
00400       hd.afl = 4;
00401       hd.spcsz = 32;
00402       hd.segsz = 0;
00403       hd.segsh = 0;
00404       hd.cpu = "SH";
00405       addrsize = 4;
00406       toolname = "C_SH";
00407       rnames = rname_sh;
00408       break;
00409     default:
00410       abort ();
00411     }
00412 
00413   if (! bfd_get_file_flags(abfd) & EXEC_P)
00414     {
00415       hd.ep = 0;
00416     }
00417   else
00418     {
00419       hd.ep = 1;
00420       hd.uan = 0;
00421       hd.sa = 0;
00422       hd.sad = 0;
00423       hd.address = bfd_get_start_address (abfd);
00424     }
00425 
00426   hd.os = "";
00427   hd.sys = "";
00428   hd.mn = strip_suffix (bfd_get_filename (abfd));
00429 
00430   sysroff_swap_hd_out (file, &hd);
00431 }
00432 
00433 
00434 static void
00435 wr_sh (struct coff_ofile *p ATTRIBUTE_UNUSED, struct coff_section *sec)
00436 {
00437   struct IT_sh sh;
00438   sh.unit = 0;
00439   sh.section = sec->number;
00440 #ifdef FOOP1
00441   sh.section = 0;
00442 #endif
00443   sysroff_swap_sh_out (file, &sh);
00444 }
00445 
00446 
00447 static void
00448 wr_ob (struct coff_ofile *p ATTRIBUTE_UNUSED, struct coff_section *section)
00449 {
00450   bfd_size_type i;
00451   int first = 1;
00452   unsigned char stuff[200];
00453 
00454   i = 0;
00455   while (i < bfd_get_section_size (section->bfd_section))
00456     {
00457       struct IT_ob ob;
00458       int todo = 200;              /* Copy in 200 byte lumps.  */
00459 
00460       ob.spare = 0;
00461       if (i + todo > bfd_get_section_size (section->bfd_section))
00462        todo = bfd_get_section_size (section->bfd_section) - i;
00463 
00464       if (first)
00465        {
00466          ob.saf = 1;
00467          if (bfd_get_file_flags (abfd) & EXEC_P)
00468            ob.address = section->address;
00469          else
00470            ob.address = 0;
00471 
00472          first = 0;
00473        }
00474       else
00475        {
00476          ob.saf = 0;
00477        }
00478 
00479       ob.cpf = 0;           /* Never compress.  */
00480       ob.data.len = todo;
00481       bfd_get_section_contents (abfd, section->bfd_section, stuff, i, todo);
00482       ob.data.data = stuff;
00483       sysroff_swap_ob_out (file, &ob /*, i + todo < section->size */ );
00484       i += todo;
00485     }
00486 
00487   /* Now fill the rest with blanks.  */
00488   while (i < (bfd_size_type) section->size)
00489     {
00490       struct IT_ob ob;
00491       int todo = 200;              /* Copy in 200 byte lumps.  */
00492 
00493       ob.spare = 0;
00494       if (i + todo > (bfd_size_type) section->size)
00495        todo = section->size - i;
00496       ob.saf = 0;
00497 
00498       ob.cpf = 0;           /* Never compress.  */
00499       ob.data.len = todo;
00500       memset (stuff, 0, todo);
00501       ob.data.data = stuff;
00502       sysroff_swap_ob_out (file, &ob);
00503       i += todo;
00504     }
00505   /* Now fill the rest with blanks.  */
00506 }
00507 
00508 static void
00509 wr_rl (struct coff_ofile *ptr ATTRIBUTE_UNUSED, struct coff_section *sec)
00510 {
00511   int nr = sec->nrelocs;
00512   int i;
00513 
00514   for (i = 0; i < nr; i++)
00515     {
00516       struct coff_reloc *r = sec->relocs + i;
00517       struct coff_symbol *ref;
00518       struct IT_rl rl;
00519 
00520       rl.apol = 0;
00521       rl.boundary = 0;
00522       rl.segment = 1;
00523       rl.sign = 0;
00524       rl.check = 0;
00525       rl.addr = r->offset;
00526       rl.bitloc = 0;
00527       rl.flen = 32;         /* SH Specific.  */
00528 
00529       /* What sort of reloc ? Look in the section to find out.  */
00530       ref = r->symbol;
00531       if (ref->visible->type == coff_vis_ext_ref)
00532        {
00533          rl.bcount = 4;     /* Always 4 for us.  */
00534          rl.op = OP_EXT_REF;
00535          rl.symn = ref->er_number;
00536        }
00537       else if (ref->visible->type == coff_vis_common)
00538        {
00539          rl.bcount = 11;    /* Always 11 for us.  */
00540          rl.op = OP_SEC_REF;
00541          rl.secn = ref->where->section->number;
00542          rl.copcode_is_3 = 3;
00543          rl.alength_is_4 = 4;
00544          rl.addend = ref->where->offset - ref->where->section->address;
00545          rl.aopcode_is_0x20 = 0x20;
00546        }
00547       else
00548        {
00549          rl.bcount = 11;    /* Always 11 for us.  */
00550          rl.op = OP_SEC_REF;
00551          rl.secn = ref->where->section->number;
00552          rl.copcode_is_3 = 3;
00553          rl.alength_is_4 = 4;
00554          rl.addend = -ref->where->section->address;
00555          rl.aopcode_is_0x20 = 0x20;
00556        }
00557 
00558       rl.end = 0xff;
00559 
00560       if (   rl.op == OP_SEC_REF
00561          || rl.op == OP_EXT_REF)
00562        sysroff_swap_rl_out (file, &rl);
00563     }
00564 }
00565 
00566 static void
00567 wr_object_body (struct coff_ofile *p)
00568 {
00569   int i;
00570 
00571   for (i = 1; i < p->nsections; i++)
00572     {
00573       wr_sh (p, p->sections + i);
00574       wr_ob (p, p->sections + i);
00575       wr_rl (p, p->sections + i);
00576     }
00577 }
00578 
00579 static void
00580 wr_dps_start (struct coff_sfile *sfile,
00581              struct coff_section *section ATTRIBUTE_UNUSED,
00582              struct coff_scope *scope, int type, int nest)
00583 {
00584   struct IT_dps dps;
00585 
00586   dps.end = 0;
00587   dps.opt = 0;
00588   dps.type = type;
00589 
00590   if (scope->sec)
00591     {
00592       dps.san = scope->sec->number;
00593       dps.address = scope->offset - find_base (sfile, scope->sec);
00594       dps.block_size = scope->size;
00595 
00596       if (debug)
00597        {
00598          printf ("DPS %s %d %x\n",
00599                 sfile->name,
00600                 nest,
00601                 dps.address);
00602        }
00603     }
00604   else
00605     {
00606       dps.san = 0;
00607       dps.address = 0;
00608       dps.block_size = 0;
00609     }
00610 
00611   dps.nesting = nest;
00612   dps.neg = 0x1001;
00613   sysroff_swap_dps_out (file, &dps);
00614 }
00615 
00616 static void
00617 wr_dps_end (struct coff_section *section ATTRIBUTE_UNUSED,
00618            struct coff_scope *scope ATTRIBUTE_UNUSED, int type)
00619 {
00620   struct IT_dps dps;
00621 
00622   dps.end = 1;
00623   dps.type = type;
00624   sysroff_swap_dps_out (file, &dps);
00625 }
00626 
00627 static int *
00628 nints (int x)
00629 {
00630   return (int *) (xcalloc (sizeof (int), x));
00631 }
00632 
00633 static void
00634 walk_tree_type_1 (struct coff_sfile *sfile, struct coff_symbol *symbol,
00635                 struct coff_type *type, int nest)
00636 {
00637   switch (type->type)
00638     {
00639     case coff_secdef_type:
00640     case coff_basic_type:
00641       {
00642        struct IT_dbt dbt;
00643 
00644        switch (type->u.basic)
00645          {
00646          case T_NULL:
00647          case T_VOID:
00648            dbt.btype = BTYPE_VOID;
00649            dbt.sign = BTYPE_UNSPEC;
00650            dbt.fptype = FPTYPE_NOTSPEC;
00651            break;
00652 
00653          case T_CHAR:
00654            dbt.btype = BTYPE_CHAR;
00655            dbt.sign = BTYPE_UNSPEC;
00656            dbt.fptype = FPTYPE_NOTSPEC;
00657            break;
00658 
00659          case T_SHORT:
00660          case T_INT:
00661          case T_LONG:
00662            dbt.btype = BTYPE_INT;
00663            dbt.sign = SIGN_SIGNED;
00664            dbt.fptype = FPTYPE_NOTSPEC;
00665            break;
00666 
00667          case T_FLOAT:
00668            dbt.btype = BTYPE_FLOAT;
00669            dbt.fptype = FPTYPE_SINGLE;
00670            break;
00671 
00672          case T_DOUBLE:
00673            dbt.btype = BTYPE_FLOAT;
00674            dbt.fptype = FPTYPE_DOUBLE;
00675            break;
00676 
00677          case T_LNGDBL:
00678            dbt.btype = BTYPE_FLOAT;
00679            dbt.fptype = FPTYPE_EXTENDED;
00680            break;
00681 
00682          case T_UCHAR:
00683            dbt.btype = BTYPE_CHAR;
00684            dbt.sign = SIGN_UNSIGNED;
00685            dbt.fptype = FPTYPE_NOTSPEC;
00686            break;
00687 
00688          case T_USHORT:
00689          case T_UINT:
00690          case T_ULONG:
00691            dbt.btype = BTYPE_INT;
00692            dbt.sign = SIGN_UNSIGNED;
00693            dbt.fptype = FPTYPE_NOTSPEC;
00694            break;
00695          }
00696 
00697        dbt.bitsize = type->size;
00698        dbt.neg = 0x1001;
00699        sysroff_swap_dbt_out (file, &dbt);
00700        break;
00701       }
00702 
00703     case coff_pointer_type:
00704       {
00705        struct IT_dpt dpt;
00706 
00707        walk_tree_type_1 (sfile, symbol, type->u.pointer.points_to, nest + 1);
00708        dpt.neg = 0x1001;
00709        sysroff_swap_dpt_out (file, &dpt);
00710        break;
00711       }
00712 
00713     case coff_function_type:
00714       {
00715        struct IT_dfp dfp;
00716        struct coff_symbol *param;
00717 
00718        dfp.end = 0;
00719        dfp.spare = 0;
00720        dfp.nparams = type->u.function.parameters->nvars;
00721        dfp.neg = 0x1001;
00722 
00723        walk_tree_type_1 (sfile, symbol, type->u.function.function_returns, nest + 1);
00724 
00725        sysroff_swap_dfp_out (file, &dfp);
00726 
00727        for (param = type->u.function.parameters->vars_head;
00728             param;
00729             param = param->next)
00730          walk_tree_symbol (sfile, 0, param, nest);
00731 
00732        dfp.end = 1;
00733        sysroff_swap_dfp_out (file, &dfp);
00734        break;
00735       }
00736 
00737     case coff_structdef_type:
00738       {
00739        struct IT_dbt dbt;
00740        struct IT_dds dds;
00741        struct coff_symbol *member;
00742 
00743        dds.spare = 0;
00744        dbt.btype = BTYPE_STRUCT;
00745        dbt.bitsize = type->size;
00746        dbt.sign = SIGN_UNSPEC;
00747        dbt.fptype = FPTYPE_NOTSPEC;
00748        dbt.sid = get_member_id (type->u.astructdef.idx);
00749        dbt.neg = 0x1001;
00750        sysroff_swap_dbt_out (file, &dbt);
00751        dds.end = 0;
00752        dds.neg = 0x1001;
00753        sysroff_swap_dds_out (file, &dds);
00754 
00755        for (member = type->u.astructdef.elements->vars_head;
00756             member;
00757             member = member->next)
00758          walk_tree_symbol (sfile, 0, member, nest + 1);
00759 
00760        dds.end = 1;
00761        sysroff_swap_dds_out (file, &dds);
00762 
00763       }
00764       break;
00765 
00766     case coff_structref_type:
00767       {
00768        struct IT_dbt dbt;
00769 
00770        dbt.btype = BTYPE_TAG;
00771        dbt.bitsize = type->size;
00772        dbt.sign = SIGN_UNSPEC;
00773        dbt.fptype = FPTYPE_NOTSPEC;
00774 
00775        if (type->u.astructref.ref)
00776          dbt.sid = get_member_id (type->u.astructref.ref->number);
00777        else
00778          dbt.sid = 0;
00779 
00780        dbt.neg = 0x1001;
00781        sysroff_swap_dbt_out (file, &dbt);
00782       }
00783       break;
00784 
00785     case coff_array_type:
00786       {
00787        struct IT_dar dar;
00788        int j;
00789        int dims = 1;        /* Only output one dimension at a time.  */
00790 
00791        dar.dims = dims;
00792        dar.variable = nints (dims);
00793        dar.subtype = nints (dims);
00794        dar.spare = nints (dims);
00795        dar.max_variable = nints (dims);
00796        dar.maxspare = nints (dims);
00797        dar.max = nints (dims);
00798        dar.min_variable = nints (dims);
00799        dar.min = nints (dims);
00800        dar.minspare = nints (dims);
00801        dar.neg = 0x1001;
00802        dar.length = type->size / type->u.array.dim;
00803 
00804        for (j = 0; j < dims; j++)
00805          {
00806            dar.variable[j] = VARIABLE_FIXED;
00807            dar.subtype[j] = SUB_INTEGER;
00808            dar.spare[j] = 0;
00809            dar.max_variable[j] = 0;
00810            dar.max[j] = type->u.array.dim;
00811            dar.min_variable[j] = 0;
00812            dar.min[j] = 1;  /* Why isn't this 0 ? */
00813          }
00814        walk_tree_type_1 (sfile, symbol, type->u.array.array_of, nest + 1);
00815        sysroff_swap_dar_out (file, &dar);
00816       }
00817       break;
00818 
00819     case coff_enumdef_type:
00820       {
00821        struct IT_dbt dbt;
00822        struct IT_den den;
00823        struct coff_symbol *member;
00824 
00825        dbt.btype = BTYPE_ENUM;
00826        dbt.bitsize = type->size;
00827        dbt.sign = SIGN_UNSPEC;
00828        dbt.fptype = FPTYPE_NOTSPEC;
00829        dbt.sid = get_member_id (type->u.aenumdef.idx);
00830        dbt.neg = 0x1001;
00831        sysroff_swap_dbt_out (file, &dbt);
00832 
00833        den.end = 0;
00834        den.neg = 0x1001;
00835        den.spare = 0;
00836        sysroff_swap_den_out (file, &den);
00837 
00838        for (member = type->u.aenumdef.elements->vars_head;
00839             member;
00840             member = member->next)
00841          walk_tree_symbol (sfile, 0, member, nest + 1);
00842 
00843        den.end = 1;
00844        sysroff_swap_den_out (file, &den);
00845       }
00846       break;
00847 
00848     case coff_enumref_type:
00849       {
00850        struct IT_dbt dbt;
00851 
00852        dbt.btype = BTYPE_TAG;
00853        dbt.bitsize = type->size;
00854        dbt.sign = SIGN_UNSPEC;
00855        dbt.fptype = FPTYPE_NOTSPEC;
00856        dbt.sid = get_member_id (type->u.aenumref.ref->number);
00857        dbt.neg = 0x1001;
00858        sysroff_swap_dbt_out (file, &dbt);
00859       }
00860       break;
00861 
00862     default:
00863       abort ();
00864     }
00865 }
00866 
00867 /* Obsolete ?
00868    static void
00869    dty_start ()
00870    {
00871    struct IT_dty dty;
00872    dty.end = 0;
00873    dty.neg = 0x1001;
00874    dty.spare = 0;
00875    sysroff_swap_dty_out (file, &dty);
00876    }
00877 
00878    static void
00879    dty_stop ()
00880    {
00881    struct IT_dty dty;
00882    dty.end = 0;
00883    dty.neg = 0x1001;
00884    dty.end = 1;
00885    sysroff_swap_dty_out (file, &dty);
00886    }
00887 
00888 
00889    static void
00890    dump_tree_structure (sfile, symbol, type, nest)
00891    struct coff_sfile *sfile;
00892    struct coff_symbol *symbol;
00893    struct coff_type *type;
00894    int nest;
00895    {
00896    if (symbol->type->type == coff_function_type)
00897    {
00898 
00899 
00900    }
00901 
00902    }
00903  */
00904 
00905 static void
00906 walk_tree_type (struct coff_sfile *sfile, struct coff_symbol *symbol,
00907               struct coff_type *type, int nest)
00908 {
00909   if (symbol->type->type == coff_function_type)
00910     {
00911       struct IT_dty dty;
00912 
00913       dty.end = 0;
00914       dty.neg = 0x1001;
00915 
00916       sysroff_swap_dty_out (file, &dty);
00917       walk_tree_type_1 (sfile, symbol, type, nest);
00918       dty.end = 1;
00919       sysroff_swap_dty_out (file, &dty);
00920 
00921       wr_dps_start (sfile,
00922                   symbol->where->section,
00923                   symbol->type->u.function.code,
00924                   BLOCK_TYPE_FUNCTION, nest);
00925       wr_dps_start (sfile, symbol->where->section,
00926                   symbol->type->u.function.code,
00927                   BLOCK_TYPE_BLOCK, nest);
00928       walk_tree_scope (symbol->where->section,
00929                      sfile,
00930                      symbol->type->u.function.code,
00931                      nest + 1, BLOCK_TYPE_BLOCK);
00932 
00933       wr_dps_end (symbol->where->section,
00934                 symbol->type->u.function.code,
00935                 BLOCK_TYPE_BLOCK);
00936       wr_dps_end (symbol->where->section,
00937                 symbol->type->u.function.code, BLOCK_TYPE_FUNCTION);
00938     }
00939   else
00940     {
00941       struct IT_dty dty;
00942 
00943       dty.end = 0;
00944       dty.neg = 0x1001;
00945       sysroff_swap_dty_out (file, &dty);
00946       walk_tree_type_1 (sfile, symbol, type, nest);
00947       dty.end = 1;
00948       sysroff_swap_dty_out (file, &dty);
00949     }
00950 }
00951 
00952 static void
00953 walk_tree_symbol (struct coff_sfile *sfile, struct coff_section *section ATTRIBUTE_UNUSED, struct coff_symbol *symbol, int nest)
00954 {
00955   struct IT_dsy dsy;
00956 
00957   memset (&dsy, 0, sizeof(dsy));
00958   dsy.nesting = nest;
00959 
00960   switch (symbol->type->type)
00961     {
00962     case coff_function_type:
00963       dsy.type = STYPE_FUNC;
00964       dsy.assign = 1;
00965       break;
00966 
00967     case coff_structref_type:
00968     case coff_pointer_type:
00969     case coff_array_type:
00970     case coff_basic_type:
00971     case coff_enumref_type:
00972       dsy.type = STYPE_VAR;
00973       dsy.assign = 1;
00974       break;
00975 
00976     case coff_enumdef_type:
00977       dsy.type = STYPE_TAG;
00978       dsy.assign = 0;
00979       dsy.magic = 2;
00980       break;
00981 
00982     case coff_structdef_type:
00983       dsy.type = STYPE_TAG;
00984       dsy.assign = 0;
00985       dsy.magic = symbol->type->u.astructdef.isstruct ? 0 : 1;
00986       break;
00987 
00988     case coff_secdef_type:
00989       return;
00990 
00991     default:
00992       abort ();
00993     }
00994 
00995   if (symbol->where->where == coff_where_member_of_struct)
00996     {
00997       dsy.assign = 0;
00998       dsy.type = STYPE_MEMBER;
00999     }
01000 
01001   if (symbol->where->where == coff_where_member_of_enum)
01002     {
01003       dsy.type = STYPE_ENUM;
01004       dsy.assign = 0;
01005       dsy.evallen = 4;
01006       dsy.evalue = symbol->where->offset;
01007     }
01008 
01009   if (symbol->type->type == coff_structdef_type
01010       || symbol->where->where == coff_where_entag
01011       || symbol->where->where == coff_where_strtag)
01012     {
01013       dsy.snumber = get_member_id (symbol->number);
01014     }
01015   else
01016     {
01017       dsy.snumber = get_ordinary_id (symbol->number);
01018     }
01019 
01020   dsy.sname = symbol->name[0] == '_' ? symbol->name + 1 : symbol->name;
01021 
01022   switch (symbol->visible->type)
01023     {
01024     case coff_vis_common:
01025     case coff_vis_ext_def:
01026       dsy.ainfo = AINFO_STATIC_EXT_DEF;
01027       break;
01028 
01029     case coff_vis_ext_ref:
01030       dsy.ainfo = AINFO_STATIC_EXT_REF;
01031       break;
01032 
01033     case coff_vis_int_def:
01034       dsy.ainfo = AINFO_STATIC_INT;
01035       break;
01036 
01037     case coff_vis_auto:
01038     case coff_vis_autoparam:
01039       dsy.ainfo = AINFO_AUTO;
01040       break;
01041 
01042     case coff_vis_register:
01043     case coff_vis_regparam:
01044       dsy.ainfo = AINFO_REG;
01045       break;
01046       break;
01047 
01048     case coff_vis_tag:
01049     case coff_vis_member_of_struct:
01050     case coff_vis_member_of_enum:
01051       break;
01052 
01053     default:
01054       abort ();
01055     }
01056 
01057   dsy.dlength = symbol->type->size;
01058 
01059   switch (symbol->where->where)
01060     {
01061     case coff_where_memory:
01062 
01063       dsy.section = symbol->where->section->number;
01064 #ifdef FOOP
01065       dsy.section = 0;
01066 #endif
01067       break;
01068 
01069     case coff_where_member_of_struct:
01070     case coff_where_member_of_enum:
01071     case coff_where_stack:
01072     case coff_where_register:
01073     case coff_where_unknown:
01074     case coff_where_strtag:
01075     case coff_where_entag:
01076     case coff_where_typedef:
01077       break;
01078 
01079     default:
01080       abort ();
01081     }
01082 
01083   switch (symbol->where->where)
01084     {
01085     case coff_where_memory:
01086       dsy.address = symbol->where->offset - find_base (sfile, symbol->where->section);
01087       break;
01088 
01089     case coff_where_stack:
01090       dsy.address = symbol->where->offset;
01091       break;
01092 
01093     case coff_where_member_of_struct:
01094       if (symbol->where->bitsize)
01095        {
01096          int bits = (symbol->where->offset * 8 + symbol->where->bitoffset);
01097          dsy.bitunit = 1;
01098          dsy.field_len = symbol->where->bitsize;
01099          dsy.field_off = (bits / 32) * 4;
01100          dsy.field_bitoff = bits % 32;
01101        }
01102       else
01103        {
01104          dsy.bitunit = 0;
01105 
01106          dsy.field_len = symbol->type->size;
01107          dsy.field_off = symbol->where->offset;
01108        }
01109       break;
01110 
01111     case coff_where_member_of_enum:
01112       /*      dsy.bitunit = 0;
01113          dsy.field_len  = symbol->type->size;
01114          dsy.field_off = symbol->where->offset; */
01115       break;
01116 
01117     case coff_where_register:
01118     case coff_where_unknown:
01119     case coff_where_strtag:
01120     case coff_where_entag:
01121     case coff_where_typedef:
01122       break;
01123 
01124     default:
01125       abort ();
01126     }
01127 
01128   if (symbol->where->where == coff_where_register)
01129     dsy.reg = rnames[symbol->where->offset];
01130 
01131   switch (symbol->visible->type)
01132     {
01133     case coff_vis_common:
01134       /* We do this 'cause common C symbols are treated as extdefs.  */
01135     case coff_vis_ext_def:
01136     case coff_vis_ext_ref:
01137       dsy.ename = symbol->name;
01138       break;
01139 
01140     case coff_vis_regparam:
01141     case coff_vis_autoparam:
01142       dsy.type = STYPE_PARAMETER;
01143       break;
01144 
01145     case coff_vis_int_def:
01146     case coff_vis_auto:
01147     case coff_vis_register:
01148     case coff_vis_tag:
01149     case coff_vis_member_of_struct:
01150     case coff_vis_member_of_enum:
01151       break;
01152 
01153     default:
01154       abort ();
01155     }
01156 
01157   dsy.sfn = 0;
01158   dsy.sln = 2;
01159   dsy.neg = 0x1001;
01160 
01161   sysroff_swap_dsy_out (file, &dsy);
01162 
01163   walk_tree_type (sfile, symbol, symbol->type, nest);
01164 }
01165 
01166 static void
01167 walk_tree_scope (struct coff_section *section, struct coff_sfile *sfile, struct coff_scope *scope, int nest, int type)
01168 {
01169   struct coff_symbol *vars;
01170   struct coff_scope *child;
01171 
01172   if (scope->vars_head
01173       || (scope->list_head && scope->list_head->vars_head))
01174     {
01175       wr_dps_start (sfile, section, scope, type, nest);
01176 
01177       if (nest == 0)
01178        wr_globals (tree, sfile, nest + 1);
01179 
01180       for (vars = scope->vars_head; vars; vars = vars->next)
01181        walk_tree_symbol (sfile, section, vars, nest);
01182 
01183       for (child = scope->list_head; child; child = child->next)
01184        walk_tree_scope (section, sfile, child, nest + 1, BLOCK_TYPE_BLOCK);
01185 
01186       wr_dps_end (section, scope, type);
01187     }
01188 }
01189 
01190 static void
01191 walk_tree_sfile (struct coff_section *section, struct coff_sfile *sfile)
01192 {
01193   walk_tree_scope (section, sfile, sfile->scope, 0, BLOCK_TYPE_COMPUNIT);
01194 }
01195 
01196 static void
01197 wr_program_structure (struct coff_ofile *p, struct coff_sfile *sfile)
01198 {
01199   walk_tree_sfile (p->sections + 4, sfile);
01200 }
01201 
01202 static void
01203 wr_du (struct coff_ofile *p, struct coff_sfile *sfile, int n)
01204 {
01205   struct IT_du du;
01206   int lim;
01207   int i;
01208   int j;
01209   unsigned int *lowest = (unsigned *) nints (p->nsections);
01210   unsigned int *highest = (unsigned *) nints (p->nsections);
01211 
01212   du.format = bfd_get_file_flags (abfd) & EXEC_P ? 0 : 1;
01213   du.optimized = 0;
01214   du.stackfrmt = 0;
01215   du.spare = 0;
01216   du.unit = n;
01217   du.sections = p->nsections - 1;
01218   du.san = (int *) xcalloc (sizeof (int), du.sections);
01219   du.address = nints (du.sections);
01220   du.length = nints (du.sections);
01221 
01222   for (i = 0; i < du.sections; i++)
01223     {
01224       lowest[i] = ~0;
01225       highest[i] = 0;
01226     }
01227 
01228   lim = du.sections;
01229   for (j = 0; j < lim; j++)
01230     {
01231       int src = j;
01232       int dst = j;
01233 
01234       du.san[dst] = dst;
01235 
01236       if (sfile->section[src].init)
01237        {
01238          du.length[dst]
01239            = sfile->section[src].high - sfile->section[src].low + 1;
01240          du.address[dst]
01241            = sfile->section[src].low;
01242        }
01243       else
01244        {
01245          du.length[dst] = 0;
01246          du.address[dst] = 0;
01247        }
01248 
01249       if (debug)
01250        {
01251          if (sfile->section[src].parent)
01252            {
01253              printf (" section %6s 0x%08x..0x%08x\n",
01254                     sfile->section[src].parent->name,
01255                     du.address[dst],
01256                     du.address[dst] + du.length[dst] - 1);
01257            }
01258        }
01259 
01260       du.sections = dst + 1;
01261     }
01262 
01263   du.tool = "c_gcc";
01264   du.date = DATE;
01265 
01266   sysroff_swap_du_out (file, &du);
01267 }
01268 
01269 static void
01270 wr_dus (struct coff_ofile *p ATTRIBUTE_UNUSED, struct coff_sfile *sfile)
01271 {
01272   struct IT_dus dus;
01273 
01274   dus.efn = 0x1001;
01275   dus.ns = 1;               /* p->nsources; sac 14 jul 94 */
01276   dus.drb = nints (dus.ns);
01277   dus.fname = (char **) xcalloc (sizeof (char *), dus.ns);
01278   dus.spare = nints (dus.ns);
01279   dus.ndir = 0;
01280   /* Find the filenames.  */
01281   dus.drb[0] = 0;
01282   dus.fname[0] = sfile->name;
01283 
01284   sysroff_swap_dus_out (file, &dus);
01285 
01286 }
01287 
01288 /* Find the offset of the .text section for this sfile in the
01289    .text section for the output file.  */
01290 
01291 static int
01292 find_base (struct coff_sfile *sfile, struct coff_section *section)
01293 {
01294   return sfile->section[section->number].low;
01295 }
01296 
01297 static void
01298 wr_dln (struct coff_ofile *p ATTRIBUTE_UNUSED, struct coff_sfile *sfile,
01299        int n ATTRIBUTE_UNUSED)
01300 {
01301   /* Count up all the linenumbers */
01302 
01303   struct coff_symbol *sy;
01304   int lc = 0;
01305   struct IT_dln dln;
01306 
01307   int idx;
01308 
01309   for (sy = sfile->scope->vars_head;
01310        sy;
01311        sy = sy->next)
01312     {
01313       struct coff_type *t = sy->type;
01314       if (t->type == coff_function_type)
01315        {
01316          struct coff_line *l = t->u.function.lines;
01317          if (l)
01318            lc += l->nlines;
01319        }
01320     }
01321 
01322   dln.sfn = nints (lc);
01323   dln.sln = nints (lc);
01324   dln.cc = nints (lc);
01325   dln.section = nints (lc);
01326 
01327   dln.from_address = nints (lc);
01328   dln.to_address = nints (lc);
01329 
01330 
01331   dln.neg = 0x1001;
01332 
01333   dln.nln = lc;
01334 
01335   /* Run through once more and fill up the structure */
01336   idx = 0;
01337   for (sy = sfile->scope->vars_head;
01338        sy;
01339        sy = sy->next)
01340     {
01341       if (sy->type->type == coff_function_type)
01342        {
01343          int i;
01344          struct coff_line *l = sy->type->u.function.lines;
01345          if (l)
01346            {
01347              int base = find_base (sfile, sy->where->section);
01348              for (i = 0; i < l->nlines; i++)
01349               {
01350                 dln.section[idx] = sy->where->section->number;
01351                 dln.sfn[idx] = 0;
01352                 dln.sln[idx] = l->lines[i];
01353                 dln.from_address[idx] =
01354                   l->addresses[i] + sy->where->section->address - base;
01355                 dln.cc[idx] = 0;
01356                 if (idx)
01357                   dln.to_address[idx - 1] = dln.from_address[idx];
01358                 idx++;
01359 
01360               }
01361              dln.to_address[idx - 1] = dln.from_address[idx - 1] + 2;
01362            }
01363        }
01364     }
01365   if (lc)
01366     sysroff_swap_dln_out (file, &dln);
01367 }
01368 
01369 /* Write the global symbols out to the debug info.  */
01370 
01371 static void
01372 wr_globals (struct coff_ofile *p, struct coff_sfile *sfile,
01373            int n ATTRIBUTE_UNUSED)
01374 {
01375   struct coff_symbol *sy;
01376 
01377   for (sy = p->symbol_list_head;
01378        sy;
01379        sy = sy->next_in_ofile_list)
01380     {
01381       if (sy->visible->type == coff_vis_ext_def
01382          || sy->visible->type == coff_vis_ext_ref)
01383        {
01384          /* Only write out symbols if they belong to
01385             the current source file.  */
01386          if (sy->sfile == sfile)
01387            walk_tree_symbol (sfile, 0, sy, 0);
01388        }
01389     }
01390 }
01391 
01392 static void
01393 wr_debug (struct coff_ofile *p)
01394 {
01395   struct coff_sfile *sfile;
01396   int n = 0;
01397 
01398   for (sfile = p->source_head;
01399        sfile;
01400        sfile = sfile->next)
01401     {
01402       if (debug)
01403        printf ("%s\n", sfile->name);
01404 
01405       wr_du (p, sfile, n);
01406       wr_dus (p, sfile);
01407       wr_program_structure (p, sfile);
01408       wr_dln (p, sfile, n);
01409       n++;
01410     }
01411 }
01412 
01413 static void
01414 wr_cs (void)
01415 {
01416   /* It seems that the CS struct is not normal - the size is wrong
01417      heres one I prepared earlier.  */
01418   static char b[] =
01419     {
01420     0x80,                   /* IT */
01421     0x21,                   /* RL */
01422     0x00,                   /* number of chars in variable length part */
01423     0x80,                   /* hd */
01424     0x00,                   /* hs */
01425     0x80,                   /* un */
01426     0x00,                   /* us */
01427     0x80,                   /* sc */
01428     0x00,                   /* ss */
01429     0x80,                   /* er */
01430     0x80,                   /* ed */
01431     0x80,                   /* sh */
01432     0x80,                   /* ob */
01433     0x80,                   /* rl */
01434     0x80,                   /* du */
01435     0x80,                   /* dps */
01436     0x80,                   /* dsy */
01437     0x80,                   /* dty */
01438     0x80,                   /* dln */
01439     0x80,                   /* dso */
01440     0x80,                   /* dus */
01441     0x00,                   /* dss */
01442     0x80,                   /* dbt */
01443     0x00,                   /* dpp */
01444     0x80,                   /* dfp */
01445     0x80,                   /* den */
01446     0x80,                   /* dds */
01447     0x80,                   /* dar */
01448     0x80,                   /* dpt */
01449     0x00,                   /* dul */
01450     0x00,                   /* dse */
01451     0x00,                   /* dot */
01452     0xDE                    /* CS */
01453   };
01454   fwrite (b, 1, sizeof (b), file);
01455 }
01456 
01457 /* Write out the SC records for a unit.  Create an SC
01458    for all the sections which appear in the output file, even
01459    if there isn't an equivalent one on the input.  */
01460 
01461 static int
01462 wr_sc (struct coff_ofile *ptr, struct coff_sfile *sfile)
01463 {
01464   int i;
01465   int scount = 0;
01466   /* First work out the total number of sections.  */
01467   int total_sec = ptr->nsections;
01468   struct myinfo
01469     {
01470       struct coff_section *sec;
01471       struct coff_symbol *symbol;
01472     };
01473   struct coff_symbol *symbol;
01474   struct myinfo *info
01475     = (struct myinfo *) calloc (total_sec, sizeof (struct myinfo));
01476 
01477 
01478   for (i = 0; i < total_sec; i++)
01479     {
01480       info[i].sec = ptr->sections + i;
01481       info[i].symbol = 0;
01482     }
01483 
01484   for (symbol = sfile->scope->vars_head;
01485        symbol;
01486        symbol = symbol->next)
01487     {
01488 
01489       if (symbol->type->type == coff_secdef_type)
01490        {
01491          for (i = 0; i < total_sec; i++)
01492            {
01493              if (symbol->where->section == info[i].sec)
01494               {
01495                 info[i].symbol = symbol;
01496                 break;
01497               }
01498            }
01499        }
01500     }
01501 
01502   /* Now output all the section info, and fake up some stuff for sections
01503      we don't have.  */
01504   for (i = 1; i < total_sec; i++)
01505     {
01506       struct IT_sc sc;
01507       char *name;
01508 
01509       symbol = info[i].symbol;
01510       sc.spare = 0;
01511       sc.spare1 = 0;
01512 
01513       if (!symbol)
01514        {
01515          /* Don't have a symbol set aside for this section, which means
01516             that nothing in this file does anything for the section.  */
01517          sc.format = !(bfd_get_file_flags (abfd) & EXEC_P);
01518          sc.addr = 0;
01519          sc.length = 0;
01520          name = info[i].sec->name;
01521        }
01522       else
01523        {
01524          if (bfd_get_file_flags (abfd) & EXEC_P)
01525            {
01526              sc.format = 0;
01527              sc.addr = symbol->where->offset;
01528            }
01529          else
01530            {
01531              sc.format = 1;
01532              sc.addr = 0;
01533            }
01534          sc.length = symbol->type->size;
01535          name = symbol->name;
01536        }
01537 
01538       sc.align = 4;
01539       sc.concat = CONCAT_SIMPLE;
01540       sc.read = 3;
01541       sc.write = 3;
01542       sc.exec = 3;
01543       sc.init = 3;
01544       sc.mode = 3;
01545       sc.spare = 0;
01546       sc.segadd = 0;
01547       sc.spare1 = 0;        /* If not zero, then it doesn't work.  */
01548       sc.name = section_translate (name);
01549 
01550       if (strlen (sc.name) == 1)
01551        {
01552          switch (sc.name[0])
01553            {
01554            case 'D':
01555            case 'B':
01556              sc.contents = CONTENTS_DATA;
01557              break;
01558 
01559            default:
01560              sc.contents = CONTENTS_CODE;
01561            }
01562        }
01563       else
01564        {
01565          sc.contents = CONTENTS_CODE;
01566        }
01567 
01568       sysroff_swap_sc_out (file, &sc);
01569       scount++;
01570     }
01571   return scount;
01572 }
01573 
01574 /* Write out the ER records for a unit.  */
01575 
01576 static void
01577 wr_er (struct coff_ofile *ptr, struct coff_sfile *sfile ATTRIBUTE_UNUSED,
01578        int first)
01579 {
01580   int idx = 0;
01581   struct coff_symbol *sym;
01582 
01583   if (first)
01584     {
01585       for (sym = ptr->symbol_list_head; sym; sym = sym->next_in_ofile_list)
01586        {
01587          if (sym->visible->type == coff_vis_ext_ref)
01588            {
01589              struct IT_er er;
01590 
01591              er.spare = 0;
01592              er.type = ER_NOTSPEC;
01593              er.name = sym->name;
01594              sysroff_swap_er_out (file, &er);
01595              sym->er_number = idx++;
01596            }
01597        }
01598     }
01599 }
01600 
01601 /* Write out the ED records for a unit.  */
01602 
01603 static void
01604 wr_ed (struct coff_ofile *ptr, struct coff_sfile *sfile ATTRIBUTE_UNUSED,
01605        int first)
01606 {
01607   struct coff_symbol *s;
01608 
01609   if (first)
01610     {
01611       for (s = ptr->symbol_list_head; s; s = s->next_in_ofile_list)
01612        {
01613          if (s->visible->type == coff_vis_ext_def
01614              || s->visible->type == coff_vis_common)
01615            {
01616              struct IT_ed ed;
01617 
01618              ed.section = s->where->section->number;
01619              ed.spare = 0;
01620 
01621              if (s->where->section->data)
01622               {
01623                 ed.type = ED_TYPE_DATA;
01624               }
01625              else if (s->where->section->code & SEC_CODE)
01626               {
01627                 ed.type = ED_TYPE_ENTRY;
01628               }
01629              else
01630               {
01631                 ed.type = ED_TYPE_NOTSPEC;
01632                 ed.type = ED_TYPE_DATA;
01633               }
01634 
01635              ed.address = s->where->offset - s->where->section->address;
01636              ed.name = s->name;
01637              sysroff_swap_ed_out (file, &ed);
01638            }
01639        }
01640     }
01641 }
01642 
01643 static void
01644 wr_unit_info (struct coff_ofile *ptr)
01645 {
01646   struct coff_sfile *sfile;
01647   int first = 1;
01648 
01649   for (sfile = ptr->source_head;
01650        sfile;
01651        sfile = sfile->next)
01652     {
01653       long p1;
01654       long p2;
01655       int nsecs;
01656 
01657       p1 = ftell (file);
01658       wr_un (ptr, sfile, first, 0);
01659       nsecs = wr_sc (ptr, sfile);
01660       p2 = ftell (file);
01661       fseek (file, p1, SEEK_SET);
01662       wr_un (ptr, sfile, first, nsecs);
01663       fseek (file, p2, SEEK_SET);
01664       wr_er (ptr, sfile, first);
01665       wr_ed (ptr, sfile, first);
01666       first = 0;
01667     }
01668 }
01669 
01670 static void
01671 wr_module (struct coff_ofile *p)
01672 {
01673   wr_cs ();
01674   wr_hd (p);
01675   wr_unit_info (p);
01676   wr_object_body (p);
01677   wr_debug (p);
01678   wr_tr ();
01679 }
01680 
01681 static int
01682 align (int x)
01683 {
01684   return (x + 3) & ~3;
01685 }
01686 
01687 /* Find all the common variables and turn them into
01688    ordinary defs - dunno why, but thats what hitachi does with 'em.  */
01689 
01690 static void
01691 prescan (struct coff_ofile *tree)
01692 {
01693   struct coff_symbol *s;
01694   struct coff_section *common_section;
01695 
01696   /* Find the common section - always section 3.  */
01697   common_section = tree->sections + 3;
01698 
01699   for (s = tree->symbol_list_head;
01700        s;
01701        s = s->next_in_ofile_list)
01702     {
01703       if (s->visible->type == coff_vis_common)
01704        {
01705          struct coff_where *w = s->where;
01706          /*      s->visible->type = coff_vis_ext_def; leave it as common */
01707          common_section->size = align (common_section->size);
01708          w->offset = common_section->size + common_section->address;
01709          w->section = common_section;
01710          common_section->size += s->type->size;
01711          common_section->size = align (common_section->size);
01712        }
01713     }
01714 }
01715 
01716 char *program_name;
01717 
01718 static void
01719 show_usage (FILE *file, int status)
01720 {
01721   fprintf (file, _("Usage: %s [option(s)] in-file [out-file]\n"), program_name);
01722   fprintf (file, _("Convert a COFF object file into a SYSROFF object file\n"));
01723   fprintf (file, _(" The options are:\n\
01724   -q --quick       (Obsolete - ignored)\n\
01725   -n --noprescan   Do not perform a scan to convert commons into defs\n\
01726   -d --debug       Display information about what is being done\n\
01727   @<file>          Read options from <file>\n\
01728   -h --help        Display this information\n\
01729   -v --version     Print the program's version number\n"));
01730 
01731   if (REPORT_BUGS_TO[0] && status == 0)
01732     fprintf (file, _("Report bugs to %s\n"), REPORT_BUGS_TO);
01733   exit (status);
01734 }
01735 
01736 int
01737 main (int ac, char **av)
01738 {
01739   int opt;
01740   static struct option long_options[] =
01741   {
01742     {"debug", no_argument, 0, 'd'},
01743     {"quick", no_argument, 0, 'q'},
01744     {"noprescan", no_argument, 0, 'n'},
01745     {"help", no_argument, 0, 'h'},
01746     {"version", no_argument, 0, 'V'},
01747     {NULL, no_argument, 0, 0}
01748   };
01749   char **matching;
01750   char *input_file;
01751   char *output_file;
01752 
01753 #if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
01754   setlocale (LC_MESSAGES, "");
01755 #endif
01756 #if defined (HAVE_SETLOCALE)
01757   setlocale (LC_CTYPE, "");
01758 #endif
01759   bindtextdomain (PACKAGE, LOCALEDIR);
01760   textdomain (PACKAGE);
01761 
01762   program_name = av[0];
01763   xmalloc_set_program_name (program_name);
01764 
01765   expandargv (&ac, &av);
01766 
01767   while ((opt = getopt_long (ac, av, "dHhVvqn", long_options,
01768                           (int *) NULL))
01769         != EOF)
01770     {
01771       switch (opt)
01772        {
01773        case 'q':
01774          quick = 1;
01775          break;
01776        case 'n':
01777          noprescan = 1;
01778          break;
01779        case 'd':
01780          debug = 1;
01781          break;
01782        case 'H':
01783        case 'h':
01784          show_usage (stdout, 0);
01785          /*NOTREACHED */
01786        case 'v':
01787        case 'V':
01788          print_version ("srconv");
01789          exit (0);
01790          /*NOTREACHED */
01791        case 0:
01792          break;
01793        default:
01794          show_usage (stderr, 1);
01795          /*NOTREACHED */
01796        }
01797     }
01798 
01799   /* The input and output files may be named on the command line.  */
01800   output_file = NULL;
01801   if (optind < ac)
01802     {
01803       input_file = av[optind];
01804       ++optind;
01805       if (optind < ac)
01806        {
01807          output_file = av[optind];
01808          ++optind;
01809          if (optind < ac)
01810            show_usage (stderr, 1);
01811          if (strcmp (input_file, output_file) == 0)
01812            {
01813              fatal (_("input and output files must be different"));
01814            }
01815        }
01816     }
01817   else
01818     input_file = 0;
01819 
01820   if (!input_file)
01821     {
01822       fatal (_("no input file specified"));
01823     }
01824 
01825   if (!output_file)
01826     {
01827       /* Take a .o off the input file and stick on a .obj.  If
01828          it doesn't end in .o, then stick a .obj on anyway */
01829 
01830       int len = strlen (input_file);
01831 
01832       output_file = xmalloc (len + 5);
01833       strcpy (output_file, input_file);
01834 
01835       if (len > 3
01836          && output_file[len - 2] == '.'
01837          && output_file[len - 1] == 'o')
01838        {
01839          output_file[len] = 'b';
01840          output_file[len + 1] = 'j';
01841          output_file[len + 2] = 0;
01842        }
01843       else
01844        {
01845          strcat (output_file, ".obj");
01846        }
01847     }
01848 
01849   abfd = bfd_openr (input_file, 0);
01850 
01851   if (!abfd)
01852     bfd_fatal (input_file);
01853 
01854   if (!bfd_check_format_matches (abfd, bfd_object, &matching))
01855     {
01856       bfd_nonfatal (input_file);
01857 
01858       if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
01859        {
01860          list_matching_formats (matching);
01861          free (matching);
01862        }
01863       exit (1);
01864     }
01865 
01866   file = fopen (output_file, FOPEN_WB);
01867 
01868   if (!file)
01869     fatal (_("unable to open output file %s"), output_file);
01870 
01871   if (debug)
01872     printf ("ids %d %d\n", base1, base2);
01873 
01874   tree = coff_grok (abfd);
01875 
01876   if (!noprescan)
01877     prescan (tree);
01878 
01879   wr_module (tree);
01880   return 0;
01881 }