srconv.c revision 78828
1/* srconv.c -- Sysroff conversion program
2   Copyright 1994, 1995, 1996, 1998, 1999, 2000
3   Free Software Foundation, Inc.
4
5   This file is part of GNU Binutils.
6
7   This program is free software; you can redistribute it and/or modify
8   it under the terms of the GNU General Public License as published by
9   the Free Software Foundation; either version 2 of the License, or
10   (at your option) any later version.
11
12   This program is distributed in the hope that it will be useful,
13   but WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   GNU General Public License for more details.
16
17   You should have received a copy of the GNU General Public License
18   along with this program; if not, write to the Free Software
19   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20   02111-1307, USA.  */
21
22/* Written by Steve Chamberlain (sac@cygnus.com)
23
24   This program can be used to convert a coff object file
25   into a Hitachi OM/LM (Sysroff) format.
26
27   All debugging information is preserved */
28
29#include <bfd.h>
30#include "bucomm.h"
31#include "sysroff.h"
32#include "coffgrok.h"
33#include <libiberty.h>
34#include <getopt.h>
35
36#include "coff/internal.h"
37#include "../bfd/libcoff.h"
38
39#define PROGRAM_VERSION "1.5"
40/*#define FOOP1 1 */
41
42static int addrsize;
43static char *toolname;
44static char **rnames;
45
46static void wr_cs ();
47static void walk_tree_scope ();
48static void wr_globals ();
49static int find_base ();
50
51static FILE *file;
52static bfd *abfd;
53static int debug = 0;
54static int quick = 0;
55static int noprescan = 0;
56static struct coff_ofile *tree;
57/* Obsolete ??
58   static int absolute_p;
59 */
60
61static int segmented_p;
62static int code;
63
64static int ids1[20000];
65static int ids2[20000];
66
67static int base1 = 0x18;
68static int base2 = 0x2018;
69
70static int
71get_member_id (x)
72     int x;
73{
74  if (ids2[x])
75    {
76      return ids2[x];
77    }
78  ids2[x] = base2++;
79  return ids2[x];
80}
81
82static int
83get_ordinary_id (x)
84     int x;
85{
86  if (ids1[x])
87    {
88      return ids1[x];
89    }
90  ids1[x] = base1++;
91  return ids1[x];
92}
93static char *
94section_translate (n)
95     char *n;
96{
97  if (strcmp (n, ".text") == 0)
98    return "P";
99  if (strcmp (n, ".data") == 0)
100    return "D";
101  if (strcmp (n, ".bss") == 0)
102    return "B";
103  return n;
104}
105
106
107
108#define DATE "940201073000";	/* Just a time on my birthday */
109
110
111static
112char *
113strip_suffix (name)
114     char *name;
115{
116  int i;
117  char *res;
118  for (i = 0; name[i] != 0 && name[i] != '.'; i++)
119    ;
120  res = (char *) xmalloc (i + 1);
121  memcpy (res, name, i);
122  res[i] = 0;
123  return res;
124}
125
126
127/* IT LEN stuff CS */
128static void
129checksum (file, ptr, size, code)
130     FILE *file;
131     char *ptr;
132     int size;
133     int code;
134{
135  int j;
136  int last;
137  int sum = 0;
138  int bytes = size / 8;
139  last = !(code & 0xff00);
140  if (size & 0x7)
141    abort ();
142  ptr[0] = code | (last ? 0x80 : 0);
143  ptr[1] = bytes + 1;
144
145  for (j = 0; j < bytes; j++)
146    {
147      sum += ptr[j];
148    }
149  /* Glue on a checksum too */
150  ptr[bytes] = ~sum;
151  fwrite (ptr, bytes + 1, 1, file);
152}
153
154
155
156
157static void
158writeINT (n, ptr, idx, size, file)
159     int n;
160     char *ptr;
161     int *idx;
162     int size;
163     FILE *file;
164{
165  int byte = *idx / 8;
166
167  if (size == -2)
168    size = addrsize;
169  else if (size == -1)
170    size = 0;
171
172  if (byte > 240)
173    {
174      /* Lets write out that record and do another one */
175      checksum (file, ptr, *idx, code | 0x1000);
176      *idx = 16;
177      byte = *idx / 8;
178    }
179  switch (size)
180    {
181    case 0:
182      break;
183    case 1:
184      ptr[byte] = n;
185      break;
186    case 2:
187      ptr[byte + 0] = n >> 8;
188      ptr[byte + 1] = n;
189      break;
190    case 4:
191      ptr[byte + 0] = n >> 24;
192      ptr[byte + 1] = n >> 16;
193      ptr[byte + 2] = n >> 8;
194      ptr[byte + 3] = n >> 0;
195      break;
196    default:
197      abort ();
198    }
199  *idx += size * 8;
200}
201
202
203static void
204writeBITS (val, ptr, idx, size)
205     int val;
206     char *ptr;
207     int *idx;
208     int size;
209{
210  int byte = *idx / 8;
211  int bit = *idx % 8;
212  int old;
213  *idx += size;
214
215  old = ptr[byte];
216  /* Turn off all about to change bits */
217  old &= ~((~0 >> (8 - bit - size)) & ((1 << size) - 1));
218  /* Turn on the bits we want */
219  old |= (val & ((1 << size) - 1)) << (8 - bit - size);
220  ptr[byte] = old;
221}
222
223static void
224writeBARRAY (data, ptr, idx, size, file)
225     barray data;
226     char *ptr;
227     int *idx;
228     int size ATTRIBUTE_UNUSED;
229     FILE *file;
230{
231  int i;
232  writeINT (data.len, ptr, idx, 1, file);
233  for (i = 0; i < data.len; i++)
234    {
235      writeINT (data.data[i], ptr, idx, 1, file);
236    }
237}
238
239
240static void
241writeCHARS (string, ptr, idx, size, file)
242     char *string;
243     char *ptr;
244     int *idx;
245     int size;
246     FILE *file;
247{
248  int i = *idx / 8;
249
250  if (i > 240)
251    {
252      /* Lets write out that record and do another one */
253      checksum (file, ptr, *idx, code | 0x1000);
254      *idx = 16;
255      i = *idx / 8;
256    }
257
258  if (size == 0)
259    {
260      /* Variable length string */
261      size = strlen (string);
262      ptr[i++] = size;
263    }
264
265  /* BUG WAITING TO HAPPEN */
266  memcpy (ptr + i, string, size);
267  i += size;
268  *idx = i * 8;
269}
270
271#define SYSROFF_SWAP_OUT
272#include "sysroff.c"
273
274
275static char *rname_sh[] =
276{
277  "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7", "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15"
278};
279
280static char *rname_h8300[] =
281{
282  "ER0", "ER1", "ER2", "ER3", "ER4", "ER5", "ER6", "ER7", "PC", "CCR"
283};
284
285static void
286wr_tr ()
287{
288  /* The TR block is not normal - it doesn't have any contents. */
289
290  static char b[] = {
291    0xff,			/* IT */
292    0x03,			/* RL */
293    0xfd,			/* CS */
294  };
295  fwrite (b, 1, sizeof (b), file);
296}
297
298static void
299wr_un (ptr, sfile, first, nsecs)
300     struct coff_ofile *ptr;
301     struct coff_sfile *sfile;
302     int first;
303     int nsecs ATTRIBUTE_UNUSED;
304{
305  struct IT_un un;
306
307  struct coff_symbol *s;
308
309  un.spare1 = 0;
310
311  if (bfd_get_file_flags (abfd) & EXEC_P)
312    un.format = FORMAT_LM;
313  else
314    un.format = FORMAT_OM;
315  un.spare1 = 0;
316
317
318#if 1
319  un.nsections = ptr->nsections - 1;	/*  Don't count the abs section */
320#else
321  /*NEW - only count sections with size */
322  un.nsections = nsecs;
323#endif
324
325  un.nextdefs = 0;
326  un.nextrefs = 0;
327  /* Count all the undefined and defined variables with global scope */
328
329  if (first)
330    {
331      for (s = ptr->symbol_list_head; s; s = s->next_in_ofile_list)
332	{
333	  if (s->visible->type == coff_vis_ext_def
334	      || s->visible->type == coff_vis_common)
335	    un.nextdefs++;
336
337	  if (s->visible->type == coff_vis_ext_ref)
338	    un.nextrefs++;
339	}
340    }
341  un.tool = toolname;
342  un.tcd = DATE;
343  un.linker = "L_GX00";
344  un.lcd = DATE;
345  un.name = sfile->name;
346  sysroff_swap_un_out (file, &un);
347}
348
349
350static void
351wr_hd (p)
352     struct coff_ofile *p;
353{
354  struct IT_hd hd;
355
356  hd.spare1 = 0;
357  if (bfd_get_file_flags (abfd) & EXEC_P)
358    {
359      hd.mt = MTYPE_ABS_LM;
360    }
361  else
362    {
363      hd.mt = MTYPE_OMS_OR_LMS;
364    }
365  hd.cd = DATE;
366
367  hd.nu = p->nsources;		/* Always one unit */
368  hd.code = 0;			/* Always ASCII */
369  hd.ver = "0200";		/* Version 2.00 */
370  switch (bfd_get_arch (abfd))
371    {
372    case bfd_arch_h8300:
373      hd.au = 8;
374      hd.si = 0;
375      hd.spcsz = 32;
376      hd.segsz = 0;
377      hd.segsh = 0;
378      switch (bfd_get_mach (abfd))
379	{
380	case bfd_mach_h8300:
381	  hd.cpu = "H8300";
382	  hd.afl = 2;
383	  addrsize = 2;
384	  toolname = "C_H8/300";
385	  break;
386	case bfd_mach_h8300h:
387	  hd.cpu = "H8300H";
388	  hd.afl = 4;
389	  addrsize = 4;
390	  toolname = "C_H8/300H";
391	  break;
392	case bfd_mach_h8300s:
393	  hd.cpu = "H8300S";
394	  hd.afl = 4;
395	  addrsize = 4;
396	  toolname = "C_H8/300S";
397	  break;
398	default:
399	  abort();
400	}
401      rnames = rname_h8300;
402      break;
403    case bfd_arch_sh:
404      hd.au = 8;
405      hd.si = 0;
406      hd.afl = 4;
407      hd.spcsz = 32;
408      hd.segsz = 0;
409      hd.segsh = 0;
410      hd.cpu = "SH";
411      addrsize = 4;
412      toolname = "C_SH";
413      rnames = rname_sh;
414      break;
415    default:
416      abort ();
417    }
418
419  if (! bfd_get_file_flags(abfd) & EXEC_P)
420    {
421      hd.ep = 0;
422    }
423  else
424    {
425      hd.ep = 1;
426      hd.uan = 0;
427      hd.sa = 0;
428      hd.sad = 0;
429      hd.address = bfd_get_start_address (abfd);
430    }
431
432  hd.os = "";
433  hd.sys = "";
434  hd.mn = strip_suffix (bfd_get_filename (abfd));
435
436  sysroff_swap_hd_out (file, &hd);
437}
438
439
440static void
441wr_sh (p, sec)
442     struct coff_ofile *p ATTRIBUTE_UNUSED;
443     struct coff_section *sec;
444{
445  struct IT_sh sh;
446  sh.unit = 0;
447  sh.section = sec->number;
448#ifdef FOOP1
449  sh.section = 0;
450#endif
451  sysroff_swap_sh_out (file, &sh);
452}
453
454
455static void
456wr_ob (p, section)
457     struct coff_ofile *p ATTRIBUTE_UNUSED;
458     struct coff_section *section;
459{
460  bfd_size_type i;
461  int first = 1;
462  unsigned char stuff[200];
463
464  i = 0;
465  while (i < section->bfd_section->_raw_size)
466    {
467      struct IT_ob ob;
468      int todo = 200;		/* Copy in 200 byte lumps */
469      ob.spare = 0;
470      if (i + todo > section->bfd_section->_raw_size)
471	todo = section->bfd_section->_raw_size - i;
472
473      if (first)
474	{
475	  ob.saf = 1;
476	  if (bfd_get_file_flags (abfd) & EXEC_P)
477	    ob.address = section->address;
478	  else
479	    ob.address = 0;
480
481	  first = 0;
482	}
483      else
484	{
485	  ob.saf = 0;
486	}
487
488      ob.cpf = 0;		/* Never compress */
489      ob.data.len = todo;
490      bfd_get_section_contents (abfd, section->bfd_section, stuff, i, todo);
491      ob.data.data = stuff;
492      sysroff_swap_ob_out (file, &ob /*, i + todo < section->size */ );
493      i += todo;
494    }
495  /* Now fill the rest with blanks */
496  while (i < (bfd_size_type) section->size)
497    {
498      struct IT_ob ob;
499      int todo = 200;		/* Copy in 200 byte lumps */
500      ob.spare = 0;
501      if (i + todo > (bfd_size_type) section->size)
502	todo = section->size - i;
503      ob.saf = 0;
504
505      ob.cpf = 0;		/* Never compress */
506      ob.data.len = todo;
507      memset (stuff, 0, todo);
508      ob.data.data = stuff;
509      sysroff_swap_ob_out (file, &ob);
510      i += todo;
511    }
512  /* Now fill the rest with blanks */
513
514}
515
516static void
517wr_rl (ptr, sec)
518     struct coff_ofile *ptr ATTRIBUTE_UNUSED;
519     struct coff_section *sec;
520{
521  int nr = sec->nrelocs;
522  int i;
523  for (i = 0; i < nr; i++)
524    {
525      struct coff_reloc *r = sec->relocs + i;
526      struct coff_symbol *ref;
527      struct IT_rl rl;
528      rl.apol = 0;
529      rl.boundary = 0;
530      rl.segment = 1;
531      rl.sign = 0;
532      rl.check = 0;
533      rl.addr = r->offset;
534      rl.bitloc = 0;
535      rl.flen = 32;		/* SH Specific */
536      /* What sort of reloc ? Look in the section to find out */
537      ref = r->symbol;
538      if (ref->visible->type == coff_vis_ext_ref)
539	{
540	  rl.bcount = 4;	/* Always 4 for us */
541	  rl.op = OP_EXT_REF;
542	  rl.symn = ref->er_number;
543	}
544      else if (ref->visible->type == coff_vis_common)
545	{
546	  rl.bcount = 11;	/* Always 11 for us */
547	  rl.op = OP_SEC_REF;
548	  rl.secn = ref->where->section->number;
549	  rl.copcode_is_3 = 3;
550	  rl.alength_is_4 = 4;
551	  rl.addend = ref->where->offset - ref->where->section->address;
552	  rl.aopcode_is_0x20 = 0x20;
553	}
554
555      else
556	{
557	  rl.bcount = 11;	/* Always 11 for us */
558	  rl.op = OP_SEC_REF;
559	  rl.secn = ref->where->section->number;
560	  rl.copcode_is_3 = 3;
561	  rl.alength_is_4 = 4;
562	  rl.addend = -ref->where->section->address;
563	  rl.aopcode_is_0x20 = 0x20;
564	}
565      rl.end = 0xff;
566      if (rl.op == OP_SEC_REF
567	  || rl.op == OP_EXT_REF)
568	{
569	  sysroff_swap_rl_out (file, &rl);
570	}
571    }
572}
573
574static void
575wr_object_body (p)
576     struct coff_ofile *p;
577{
578  int i;
579  for (i = 1; i < p->nsections; i++)
580    {
581      wr_sh (p, p->sections + i);
582      wr_ob (p, p->sections + i);
583      wr_rl (p, p->sections + i);
584    }
585}
586
587static void
588wr_dps_start (sfile, section, scope, type, nest)
589     struct coff_sfile *sfile;
590     struct coff_section *section ATTRIBUTE_UNUSED;
591     struct coff_scope *scope;
592     int type;
593     int nest;
594{
595  struct IT_dps dps;
596  dps.end = 0;
597  dps.opt = 0;
598  dps.type = type;
599  if (scope->sec)
600    {
601      dps.san = scope->sec->number;
602      dps.address = scope->offset - find_base (sfile, scope->sec);
603      dps.block_size = scope->size;
604      if (debug)
605	{
606	  printf ("DPS %s %d %x\n",
607		  sfile->name,
608		  nest,
609		  dps.address);
610
611	}
612    }
613  else
614    {
615      dps.san = 0;
616      dps.address = 0;
617      dps.block_size = 0;
618    }
619
620  dps.nesting = nest;
621  dps.neg = 0x1001;
622  sysroff_swap_dps_out (file, &dps);
623}
624
625static void
626wr_dps_end (section, scope, type)
627     struct coff_section *section ATTRIBUTE_UNUSED;
628     struct coff_scope *scope ATTRIBUTE_UNUSED;
629     int type;
630{
631  struct IT_dps dps;
632  dps.end = 1;
633  dps.type = type;
634  sysroff_swap_dps_out (file, &dps);
635}
636
637static int *
638nints (x)
639     int x;
640{
641  return (int *) (xcalloc (sizeof (int), x));
642}
643
644static void walk_tree_symbol ();
645static void
646walk_tree_type_1 (sfile, symbol, type, nest)
647     struct coff_sfile *sfile;
648     struct coff_symbol *symbol;
649     struct coff_type *type;
650     int nest;
651{
652  switch (type->type)
653    {
654    case coff_secdef_type:
655    case coff_basic_type:
656      {
657	struct IT_dbt dbt;
658
659	switch (type->u.basic)
660	  {
661	  case T_NULL:
662	  case T_VOID:
663	    dbt.btype = BTYPE_VOID;
664	    dbt.sign = BTYPE_UNSPEC;
665	    dbt.fptype = FPTYPE_NOTSPEC;
666	    break;
667	  case T_CHAR:
668	    dbt.btype = BTYPE_CHAR;
669	    dbt.sign = BTYPE_UNSPEC;
670	    dbt.fptype = FPTYPE_NOTSPEC;
671	    break;
672	  case T_SHORT:
673	  case T_INT:
674	  case T_LONG:
675	    dbt.btype = BTYPE_INT;
676	    dbt.sign = SIGN_SIGNED;
677	    dbt.fptype = FPTYPE_NOTSPEC;
678	    break;
679	  case T_FLOAT:
680	    dbt.btype = BTYPE_FLOAT;
681	    dbt.fptype = FPTYPE_SINGLE;
682	    break;
683	  case T_DOUBLE:
684	    dbt.btype = BTYPE_FLOAT;
685	    dbt.fptype = FPTYPE_DOUBLE;
686	    break;
687	  case T_LNGDBL:
688	    dbt.btype = BTYPE_FLOAT;
689	    dbt.fptype = FPTYPE_EXTENDED;
690	    break;
691	  case T_UCHAR:
692	    dbt.btype = BTYPE_CHAR;
693	    dbt.sign = SIGN_UNSIGNED;
694	    dbt.fptype = FPTYPE_NOTSPEC;
695	    break;
696	  case T_USHORT:
697	  case T_UINT:
698	  case T_ULONG:
699	    dbt.btype = BTYPE_INT;
700	    dbt.sign = SIGN_UNSIGNED;
701	    dbt.fptype = FPTYPE_NOTSPEC;
702	    break;
703	  }
704	dbt.bitsize = type->size;
705	dbt.neg = 0x1001;
706	sysroff_swap_dbt_out (file, &dbt);
707	break;
708      }
709    case coff_pointer_type:
710      {
711	struct IT_dpt dpt;
712	walk_tree_type_1 (sfile, symbol, type->u.pointer.points_to, nest + 1);
713	dpt.neg = 0x1001;
714	sysroff_swap_dpt_out (file, &dpt);
715	break;
716      }
717
718    case coff_function_type:
719      {
720	struct IT_dfp dfp;
721	struct coff_symbol *param;
722	dfp.end = 0;
723	dfp.spare = 0;
724	dfp.nparams = type->u.function.parameters->nvars;
725	dfp.neg = 0x1001;
726
727	walk_tree_type_1 (sfile, symbol, type->u.function.function_returns, nest + 1);
728
729	sysroff_swap_dfp_out (file, &dfp);
730
731	for (param = type->u.function.parameters->vars_head;
732	     param;
733	     param = param->next)
734	  {
735	    walk_tree_symbol (sfile, 0, param, nest);
736	  }
737	dfp.end = 1;
738	sysroff_swap_dfp_out (file, &dfp);
739	break;
740      }
741
742    case coff_structdef_type:
743      {
744	struct IT_dbt dbt;
745	struct IT_dds dds;
746	struct coff_symbol *member;
747	dds.spare = 0;
748	dbt.btype = BTYPE_STRUCT;
749	dbt.bitsize = type->size;
750	dbt.sign = SIGN_UNSPEC;
751	dbt.fptype = FPTYPE_NOTSPEC;
752	dbt.sid = get_member_id (type->u.astructdef.idx);
753	dbt.neg = 0x1001;
754	sysroff_swap_dbt_out (file, &dbt);
755	dds.end = 0;
756	dds.neg = 0x1001;
757	sysroff_swap_dds_out (file, &dds);
758	for (member = type->u.astructdef.elements->vars_head;
759	     member;
760	     member = member->next)
761	  {
762	    walk_tree_symbol (sfile, 0, member, nest + 1);
763	  }
764
765	dds.end = 1;
766	sysroff_swap_dds_out (file, &dds);
767
768      }
769      break;
770    case coff_structref_type:
771      {
772	struct IT_dbt dbt;
773	dbt.btype = BTYPE_TAG;
774	dbt.bitsize = type->size;
775	dbt.sign = SIGN_UNSPEC;
776	dbt.fptype = FPTYPE_NOTSPEC;
777	if (type->u.astructref.ref)
778	  {
779	    dbt.sid = get_member_id (type->u.astructref.ref->number);
780	  }
781	else
782	  {
783	    dbt.sid = 0;
784	  }
785
786	dbt.neg = 0x1001;
787	sysroff_swap_dbt_out (file, &dbt);
788      }
789      break;
790    case coff_array_type:
791      {
792	struct IT_dar dar;
793	int j;
794	int dims = 1;		/* Only output one dimension at a time */
795	dar.dims = dims;
796	dar.variable = nints (dims);
797	dar.subtype = nints (dims);
798	dar.spare = nints (dims);
799	dar.max_variable = nints (dims);
800	dar.maxspare = nints (dims);
801	dar.max = nints (dims);
802	dar.min_variable = nints (dims);
803	dar.min = nints (dims);
804	dar.minspare = nints (dims);
805	dar.neg = 0x1001;
806	dar.length = type->size / type->u.array.dim;
807	for (j = 0; j < dims; j++)
808	  {
809	    dar.variable[j] = VARIABLE_FIXED;
810	    dar.subtype[j] = SUB_INTEGER;
811	    dar.spare[j] = 0;
812	    dar.max_variable[j] = 0;
813	    dar.max[j] = type->u.array.dim;
814	    dar.min_variable[j] = 0;
815	    dar.min[j] = 1;	/* Why isn't this 0 ? */
816	  }
817	walk_tree_type_1 (sfile, symbol, type->u.array.array_of, nest + 1);
818	sysroff_swap_dar_out (file, &dar);
819      }
820      break;
821    case coff_enumdef_type:
822      {
823	struct IT_dbt dbt;
824	struct IT_den den;
825	struct coff_symbol *member;
826	dbt.btype = BTYPE_ENUM;
827	dbt.bitsize = type->size;
828	dbt.sign = SIGN_UNSPEC;
829	dbt.fptype = FPTYPE_NOTSPEC;
830	dbt.sid = get_member_id (type->u.aenumdef.idx);
831	dbt.neg = 0x1001;
832	sysroff_swap_dbt_out (file, &dbt);
833
834	den.end = 0;
835	den.neg = 0x1001;
836	den.spare = 0;
837	sysroff_swap_den_out (file, &den);
838	for (member = type->u.aenumdef.elements->vars_head;
839	     member;
840	     member = member->next)
841	  {
842	    walk_tree_symbol (sfile, 0, member, nest + 1);
843	  }
844
845	den.end = 1;
846	sysroff_swap_den_out (file, &den);
847      }
848      break;
849
850      break;
851    case coff_enumref_type:
852      {
853	struct IT_dbt dbt;
854	dbt.btype = BTYPE_TAG;
855	dbt.bitsize = type->size;
856	dbt.sign = SIGN_UNSPEC;
857	dbt.fptype = FPTYPE_NOTSPEC;
858	dbt.sid = get_member_id (type->u.aenumref.ref->number);
859	dbt.neg = 0x1001;
860	sysroff_swap_dbt_out (file, &dbt);
861      }
862      break;
863    default:
864      abort ();
865    }
866}
867
868/* Obsolete ?
869   static void
870   dty_start ()
871   {
872   struct IT_dty dty;
873   dty.end = 0;
874   dty.neg = 0x1001;
875   dty.spare = 0;
876   sysroff_swap_dty_out (file, &dty);
877   }
878
879   static void
880   dty_stop ()
881   {
882   struct IT_dty dty;
883   dty.end = 0;
884   dty.neg = 0x1001;
885   dty.end = 1;
886   sysroff_swap_dty_out (file, &dty);
887   }
888
889
890   static void
891   dump_tree_structure (sfile, symbol, type, nest)
892   struct coff_sfile *sfile;
893   struct coff_symbol *symbol;
894   struct coff_type *type;
895   int nest;
896   {
897   if (symbol->type->type == coff_function_type)
898   {
899
900
901   }
902
903   }
904 */
905
906static void
907walk_tree_type (sfile, symbol, type, nest)
908
909     struct
910     coff_sfile *sfile;
911     struct coff_symbol *symbol;
912     struct coff_type *type;
913     int nest;
914{
915  if (symbol->type->type == coff_function_type)
916    {
917
918      struct IT_dty dty;
919      dty.end = 0;
920      dty.neg = 0x1001;
921
922      sysroff_swap_dty_out (file, &dty);
923      walk_tree_type_1 (sfile, symbol, type, nest);
924      dty.end = 1;
925      sysroff_swap_dty_out (file, &dty);
926
927      wr_dps_start (sfile,
928		    symbol->where->section,
929		    symbol->type->u.function.code,
930		    BLOCK_TYPE_FUNCTION, nest);
931      wr_dps_start (sfile, symbol->where->section,
932		    symbol->type->u.function.code,
933		    BLOCK_TYPE_BLOCK, nest);
934      walk_tree_scope (symbol->where->section,
935		       sfile,
936		       symbol->type->u.function.code,
937		       nest + 1, BLOCK_TYPE_BLOCK);
938
939      wr_dps_end (symbol->where->section,
940		  symbol->type->u.function.code,
941		  BLOCK_TYPE_BLOCK);
942      wr_dps_end (symbol->where->section,
943		  symbol->type->u.function.code, BLOCK_TYPE_FUNCTION);
944
945    }
946  else
947    {
948      struct IT_dty dty;
949      dty.end = 0;
950      dty.neg = 0x1001;
951      sysroff_swap_dty_out (file, &dty);
952      walk_tree_type_1 (sfile, symbol, type, nest);
953      dty.end = 1;
954      sysroff_swap_dty_out (file, &dty);
955    }
956
957}
958
959
960
961static void
962walk_tree_symbol (sfile, section, symbol, nest)
963     struct coff_sfile *sfile;
964     struct coff_section *section ATTRIBUTE_UNUSED;
965     struct coff_symbol *symbol;
966     int nest;
967{
968  struct IT_dsy dsy;
969
970  memset(&dsy, 0, sizeof(dsy));
971  dsy.nesting = nest;
972
973  switch (symbol->type->type)
974    {
975    case coff_function_type:
976      dsy.type = STYPE_FUNC;
977      dsy.assign = 1;
978      break;
979    case coff_structref_type:
980    case coff_pointer_type:
981    case coff_array_type:
982    case coff_basic_type:
983    case coff_enumref_type:
984      dsy.type = STYPE_VAR;
985      dsy.assign = 1;
986      break;
987    case coff_enumdef_type:
988      dsy.type = STYPE_TAG;
989      dsy.assign = 0;
990      dsy.magic = 2;
991      break;
992    case coff_structdef_type:
993      dsy.type = STYPE_TAG;
994      dsy.assign = 0;
995      dsy.magic = symbol->type->u.astructdef.isstruct ? 0 : 1;
996      break;
997    case coff_secdef_type:
998      return;
999    default:
1000      abort ();
1001    }
1002
1003  if (symbol->where->where == coff_where_member_of_struct)
1004    {
1005      dsy.assign = 0;
1006      dsy.type = STYPE_MEMBER;
1007    }
1008  if (symbol->where->where == coff_where_member_of_enum)
1009    {
1010      dsy.type = STYPE_ENUM;
1011      dsy.assign = 0;
1012      dsy.evallen = 4;
1013      dsy.evalue = symbol->where->offset;
1014    }
1015
1016  if (symbol->type->type == coff_structdef_type
1017      || symbol->where->where == coff_where_entag
1018      || symbol->where->where == coff_where_strtag)
1019    {
1020      dsy.snumber = get_member_id (symbol->number);
1021    }
1022  else
1023    {
1024      dsy.snumber = get_ordinary_id (symbol->number);
1025    }
1026
1027
1028  dsy.sname = symbol->name[0] == '_' ? symbol->name + 1 : symbol->name;
1029
1030  switch (symbol->visible->type)
1031    {
1032    case coff_vis_common:
1033    case coff_vis_ext_def:
1034      dsy.ainfo = AINFO_STATIC_EXT_DEF;
1035      break;
1036    case coff_vis_ext_ref:
1037      dsy.ainfo = AINFO_STATIC_EXT_REF;
1038      break;
1039    case coff_vis_int_def:
1040      dsy.ainfo = AINFO_STATIC_INT;
1041      break;
1042    case coff_vis_auto:
1043    case coff_vis_autoparam:
1044      dsy.ainfo = AINFO_AUTO;
1045      break;
1046    case coff_vis_register:
1047    case coff_vis_regparam:
1048      dsy.ainfo = AINFO_REG;
1049      break;
1050      break;
1051    case coff_vis_tag:
1052    case coff_vis_member_of_struct:
1053    case coff_vis_member_of_enum:
1054      break;
1055    default:
1056      abort ();
1057    }
1058
1059  dsy.dlength = symbol->type->size;
1060  switch (symbol->where->where)
1061    {
1062    case coff_where_memory:
1063
1064      dsy.section = symbol->where->section->number;
1065#ifdef FOOP
1066      dsy.section = 0;
1067#endif
1068      break;
1069    case coff_where_member_of_struct:
1070    case coff_where_member_of_enum:
1071    case coff_where_stack:
1072    case coff_where_register:
1073    case coff_where_unknown:
1074    case coff_where_strtag:
1075
1076    case coff_where_entag:
1077    case coff_where_typedef:
1078      break;
1079    default:
1080      abort ();
1081    }
1082
1083  switch (symbol->where->where)
1084    {
1085    case coff_where_memory:
1086      dsy.address = symbol->where->offset - find_base (sfile, symbol->where->section);
1087      break;
1088    case coff_where_stack:
1089      dsy.address = symbol->where->offset;
1090      break;
1091    case coff_where_member_of_struct:
1092
1093
1094      if (symbol->where->bitsize)
1095	{
1096	  int bits = (symbol->where->offset * 8 + symbol->where->bitoffset);
1097	  dsy.bitunit = 1;
1098	  dsy.field_len = symbol->where->bitsize;
1099	  dsy.field_off = (bits / 32) * 4;
1100	  dsy.field_bitoff = bits % 32;
1101	}
1102      else
1103	{
1104	  dsy.bitunit = 0;
1105
1106	  dsy.field_len = symbol->type->size;
1107	  dsy.field_off = symbol->where->offset;
1108	}
1109      break;
1110    case coff_where_member_of_enum:
1111      /*      dsy.bitunit = 0;
1112         dsy.field_len  = symbol->type->size;
1113         dsy.field_off = symbol->where->offset; */
1114      break;
1115    case coff_where_register:
1116    case coff_where_unknown:
1117    case coff_where_strtag:
1118
1119    case coff_where_entag:
1120    case coff_where_typedef:
1121      break;
1122    default:
1123      abort ();
1124    }
1125
1126  if (symbol->where->where == coff_where_register)
1127    dsy.reg = rnames[symbol->where->offset];
1128
1129  switch (symbol->visible->type)
1130    {
1131    case coff_vis_common:
1132      /* We do this 'cause common C symbols are treated as extdefs */
1133    case coff_vis_ext_def:
1134    case coff_vis_ext_ref:
1135
1136      dsy.ename = symbol->name;
1137      break;
1138
1139    case coff_vis_regparam:
1140    case coff_vis_autoparam:
1141      dsy.type = STYPE_PARAMETER;
1142      break;
1143
1144    case coff_vis_int_def:
1145
1146    case coff_vis_auto:
1147    case coff_vis_register:
1148    case coff_vis_tag:
1149    case coff_vis_member_of_struct:
1150    case coff_vis_member_of_enum:
1151      break;
1152    default:
1153      abort ();
1154    }
1155
1156  dsy.sfn = 0;
1157  dsy.sln = 2;
1158
1159  dsy.neg = 0x1001;
1160
1161
1162  sysroff_swap_dsy_out (file, &dsy);
1163
1164  walk_tree_type (sfile, symbol, symbol->type, nest);
1165}
1166
1167
1168static void
1169walk_tree_scope (section, sfile, scope, nest, type)
1170     struct coff_section *section;
1171     struct coff_sfile *sfile;
1172     struct coff_scope *scope;
1173     int nest;
1174     int type;
1175{
1176  struct coff_symbol *vars;
1177  struct coff_scope *child;
1178
1179  if (scope->vars_head
1180      || (scope->list_head && scope->list_head->vars_head))
1181    {
1182      wr_dps_start (sfile, section, scope, type, nest);
1183
1184      if (nest == 0)
1185	wr_globals (tree, sfile, nest + 1);
1186
1187      for (vars = scope->vars_head; vars; vars = vars->next)
1188	{
1189	  walk_tree_symbol (sfile, section, vars, nest);
1190	}
1191
1192      for (child = scope->list_head; child; child = child->next)
1193	{
1194	  walk_tree_scope (section, sfile, child, nest + 1, BLOCK_TYPE_BLOCK);
1195	}
1196
1197      wr_dps_end (section, scope, type);
1198    }
1199}
1200static void
1201walk_tree_sfile (section, sfile)
1202     struct coff_section *section;
1203     struct coff_sfile *sfile;
1204{
1205  walk_tree_scope (section, sfile, sfile->scope, 0, BLOCK_TYPE_COMPUNIT);
1206
1207}
1208
1209static void
1210wr_program_structure (p, sfile)
1211     struct coff_ofile *p;
1212     struct coff_sfile *sfile;
1213{
1214
1215  walk_tree_sfile (p->sections + 4, sfile);
1216
1217}
1218
1219static void
1220wr_du (p, sfile, n)
1221     struct coff_ofile *p;
1222     struct coff_sfile *sfile;
1223     int n;
1224{
1225  struct IT_du du;
1226  int lim;
1227#if 0
1228  struct coff_symbol *symbol;
1229  static int incit = 0x500000;
1230  int used = 0;
1231#endif
1232  int i;
1233  int j;
1234  unsigned int *lowest = (unsigned *) nints (p->nsections);
1235  unsigned int *highest = (unsigned *) nints (p->nsections);
1236  du.format = bfd_get_file_flags (abfd) & EXEC_P ? 0 : 1;
1237  du.optimized = 0;
1238  du.stackfrmt = 0;
1239  du.spare = 0;
1240  du.unit = n;
1241  du.sections = p->nsections - 1;
1242  du.san = (int *) xcalloc (sizeof (int), du.sections);
1243  du.address = nints (du.sections);
1244  du.length = nints (du.sections);
1245
1246  for (i = 0; i < du.sections; i++)
1247    {
1248      lowest[i] = ~0;
1249      highest[i] = 0;
1250    }
1251
1252  /* Look through all the symbols and try and work out the extents in this
1253     source file */
1254#if 0
1255  for (symbol = sfile->scope->vars_head;
1256       symbol;
1257       symbol = symbol->next)
1258    {
1259      if (symbol->type->type == coff_secdef_type)
1260	{
1261	  unsigned int low = symbol->where->offset;
1262	  unsigned int high = symbol->where->offset + symbol->type->size - 1;
1263	  struct coff_section *section = symbol->where->section;
1264
1265	  int sn = section->number;
1266	  if (low < lowest[sn])
1267	    lowest[sn] = low;
1268	  if (high > highest[sn])
1269	    highest[sn] = high;
1270	}
1271    }
1272
1273
1274  for (i = 0; i < du.sections; i++)
1275    {
1276      if (highest[i] == 0)
1277	{
1278	  lowest[i] = highest[i] = incit;
1279	}
1280      du.san[used] = i;
1281      du.length[used] = highest[i] - lowest[i];
1282      du.address[used] = bfd_get_file_flags (abfd) & EXEC_P ? lowest[i] : 0;
1283      if (debug)
1284	{
1285	  printf (" section %6s 0x%08x..0x%08x\n",
1286		  p->sections[i + 1].name,
1287		  lowest[i],
1288		  highest[i]);
1289	}
1290      used++;
1291    }
1292
1293#endif
1294  lim = du.sections;
1295  for (j = 0; j < lim; j++)
1296    {
1297      int src = j;
1298      int dst = j;
1299      du.san[dst] = dst;
1300      if (sfile->section[src].init)
1301	{
1302	  du.length[dst]
1303	    = sfile->section[src].high - sfile->section[src].low + 1;
1304	  du.address[dst]
1305	    = sfile->section[src].low;
1306	}
1307      else
1308	{
1309	  du.length[dst] = 0;
1310	  du.address[dst] = 0;
1311	}
1312      if (debug)
1313	{
1314	  if (sfile->section[src].parent)
1315	    {
1316	      printf (" section %6s 0x%08x..0x%08x\n",
1317		      sfile->section[src].parent->name,
1318		      du.address[dst],
1319		      du.address[dst] + du.length[dst] - 1);
1320	    }
1321	}
1322      du.sections = dst + 1;
1323    }
1324
1325  du.tool = "c_gcc";
1326  du.date = DATE;
1327
1328  sysroff_swap_du_out (file, &du);
1329}
1330
1331static void
1332wr_dus (p, sfile)
1333     struct coff_ofile *p ATTRIBUTE_UNUSED;
1334     struct coff_sfile *sfile;
1335{
1336
1337  struct IT_dus dus;
1338
1339  dus.efn = 0x1001;
1340  dus.ns = 1;			/* p->nsources; sac 14 jul 94 */
1341  dus.drb = nints (dus.ns);
1342  dus.fname = (char **) xcalloc (sizeof (char *), dus.ns);
1343  dus.spare = nints (dus.ns);
1344  dus.ndir = 0;
1345  /* Find the filenames */
1346#if 0
1347  i = 0;
1348
1349  for (sfile = p->source_head;
1350       sfile;
1351       sfile = sfile->next)
1352    {
1353      dus.drb[i] = 0;
1354      dus.spare[i] = 0;
1355      dus.fname[i] = sfile->name;
1356      i++;
1357    }
1358#else
1359  dus.drb[0] = 0;
1360  dus.fname[0] = sfile->name;
1361#endif
1362
1363  sysroff_swap_dus_out (file, &dus);
1364
1365}
1366
1367/* Find the offset of the .text section for this sfile in the
1368   .text section for the output file */
1369
1370static int
1371find_base (sfile, section)
1372     struct coff_sfile *sfile;
1373     struct coff_section *section;
1374{
1375  return sfile->section[section->number].low;
1376}
1377
1378static void
1379wr_dln (p, sfile, n)
1380     struct coff_ofile *p ATTRIBUTE_UNUSED;
1381     struct coff_sfile *sfile;
1382     int n ATTRIBUTE_UNUSED;
1383
1384{
1385#if 0
1386  if (n == 0)
1387    {
1388      /* Count up all the linenumbers */
1389      struct coff_symbol *sy;
1390      int lc = 0;
1391      struct IT_dln dln;
1392
1393      int idx;
1394
1395      for (sy = p->symbol_list_head;
1396	   sy;
1397	   sy = sy->next_in_ofile_list)
1398	{
1399	  struct coff_type *t = sy->type;
1400	  if (t->type == coff_function_type)
1401	    {
1402	      struct coff_line *l = t->u.function.lines;
1403	      lc += l->nlines;
1404	    }
1405	}
1406
1407      dln.sfn = nints (lc);
1408      dln.sln = nints (lc);
1409      dln.lln = nints (lc);
1410      dln.section = nints (lc);
1411
1412      dln.from_address = nints (lc);
1413      dln.to_address = nints (lc);
1414
1415
1416      dln.neg = 0x1001;
1417
1418      dln.nln = lc;
1419
1420      /* Run through once more and fill up the structure */
1421      idx = 0;
1422      for (sy = p->symbol_list_head;
1423	   sy;
1424	   sy = sy->next_in_ofile_list)
1425	{
1426	  if (sy->type->type == coff_function_type)
1427	    {
1428	      int i;
1429	      struct coff_line *l = sy->type->u.function.lines;
1430	      for (i = 0; i < l->nlines; i++)
1431		{
1432		  dln.section[idx] = sy->where->section->number;
1433		  dln.sfn[idx] = n;
1434		  dln.sln[idx] = l->lines[i];
1435		  dln.from_address[idx] = l->addresses[i];
1436		  if (idx)
1437		    dln.to_address[idx - 1] = dln.from_address[idx];
1438		  idx++;
1439		}
1440	    }
1441	  n++;
1442	}
1443      sysroff_swap_dln_out (file, &dln);
1444    }
1445
1446#endif
1447#if 1
1448  /* Count up all the linenumbers */
1449
1450  struct coff_symbol *sy;
1451  int lc = 0;
1452  struct IT_dln dln;
1453
1454  int idx;
1455
1456  for (sy = sfile->scope->vars_head;
1457       sy;
1458       sy = sy->next)
1459    {
1460      struct coff_type *t = sy->type;
1461      if (t->type == coff_function_type)
1462	{
1463	  struct coff_line *l = t->u.function.lines;
1464	  if (l)
1465	    lc += l->nlines;
1466	}
1467    }
1468
1469  dln.sfn = nints (lc);
1470  dln.sln = nints (lc);
1471  dln.cc = nints (lc);
1472  dln.section = nints (lc);
1473
1474  dln.from_address = nints (lc);
1475  dln.to_address = nints (lc);
1476
1477
1478  dln.neg = 0x1001;
1479
1480  dln.nln = lc;
1481
1482  /* Run through once more and fill up the structure */
1483  idx = 0;
1484  for (sy = sfile->scope->vars_head;
1485       sy;
1486       sy = sy->next)
1487    {
1488      if (sy->type->type == coff_function_type)
1489	{
1490	  int i;
1491	  struct coff_line *l = sy->type->u.function.lines;
1492	  if (l)
1493	    {
1494	      int base = find_base (sfile, sy->where->section);
1495	      for (i = 0; i < l->nlines; i++)
1496		{
1497		  dln.section[idx] = sy->where->section->number;
1498		  dln.sfn[idx] = 0;
1499		  dln.sln[idx] = l->lines[i];
1500		  dln.from_address[idx] =
1501		    l->addresses[i] + sy->where->section->address - base;
1502		  dln.cc[idx] = 0;
1503		  if (idx)
1504		    dln.to_address[idx - 1] = dln.from_address[idx];
1505		  idx++;
1506
1507		}
1508	      dln.to_address[idx - 1] = dln.from_address[idx - 1] + 2;
1509	    }
1510	}
1511    }
1512  if (lc)
1513    sysroff_swap_dln_out (file, &dln);
1514#endif
1515}
1516
1517/* Write the global symbols out to the debug info */
1518static void
1519wr_globals (p, sfile, n)
1520     struct coff_ofile *p;
1521     struct coff_sfile *sfile;
1522     int n ATTRIBUTE_UNUSED;
1523{
1524  struct coff_symbol *sy;
1525  for (sy = p->symbol_list_head;
1526       sy;
1527       sy = sy->next_in_ofile_list)
1528    {
1529      if (sy->visible->type == coff_vis_ext_def
1530	  || sy->visible->type == coff_vis_ext_ref)
1531	{
1532	  /* Only write out symbols if they belong to
1533	     the current source file */
1534	  if (sy->sfile == sfile)
1535	    walk_tree_symbol (sfile, 0, sy, 0);
1536
1537	}
1538    }
1539}
1540
1541static void
1542wr_debug (p)
1543     struct coff_ofile *p;
1544{
1545  struct coff_sfile *sfile;
1546  int n = 0;
1547  for (sfile = p->source_head;
1548       sfile;
1549       sfile = sfile->next)
1550
1551    {
1552      if (debug)
1553	{
1554	  printf ("%s\n", sfile->name);
1555	}
1556      wr_du (p, sfile, n);
1557      wr_dus (p, sfile);
1558      wr_program_structure (p, sfile);
1559      wr_dln (p, sfile, n);
1560      n++;
1561    }
1562}
1563
1564static void
1565wr_cs ()
1566{
1567  /* It seems that the CS struct is not normal - the size is wrong
1568     heres one I prepared earlier.. */
1569  static char b[] = {
1570    0x80,			/* IT */
1571    0x21,			/* RL */
1572    0x00,			/* number of chars in variable length part */
1573    0x80,			/* hd */
1574    0x00,			/* hs */
1575    0x80,			/* un */
1576    0x00,			/* us */
1577    0x80,			/* sc */
1578    0x00,			/* ss */
1579    0x80,			/* er */
1580    0x80,			/* ed */
1581    0x80,			/* sh */
1582    0x80,			/* ob */
1583    0x80,			/* rl */
1584    0x80,			/* du */
1585    0x80,			/* dps */
1586    0x80,			/* dsy */
1587    0x80,			/* dty */
1588    0x80,			/* dln */
1589    0x80,			/* dso */
1590    0x80,			/* dus */
1591    0x00,			/* dss */
1592    0x80,			/* dbt */
1593    0x00,			/* dpp */
1594    0x80,			/* dfp */
1595    0x80,			/* den */
1596    0x80,			/* dds */
1597    0x80,			/* dar */
1598    0x80,			/* dpt */
1599    0x00,			/* dul */
1600    0x00,			/* dse */
1601    0x00,			/* dot */
1602    0xDE			/* CS */
1603  };
1604  fwrite (b, 1, sizeof (b), file);
1605}
1606
1607/* Write out the SC records for a unit.  Create an SC
1608   for all the sections which appear in the output file, even
1609   if there isn't an equivalent one on the input */
1610
1611static int
1612wr_sc (ptr, sfile)
1613     struct coff_ofile *ptr;
1614     struct coff_sfile *sfile;
1615{
1616  int i;
1617int scount = 0;
1618  /* First work out the total number of sections */
1619
1620  int total_sec = ptr->nsections;
1621
1622  struct myinfo
1623    {
1624      struct coff_section *sec;
1625      struct coff_symbol *symbol;
1626    };
1627  struct coff_symbol *symbol;
1628
1629  struct myinfo *info
1630    = (struct myinfo *) calloc (total_sec, sizeof (struct myinfo));
1631
1632
1633
1634  for (i = 0; i < total_sec; i++)
1635    {
1636      info[i].sec = ptr->sections + i;
1637      info[i].symbol = 0;
1638    }
1639
1640  for (symbol = sfile->scope->vars_head;
1641       symbol;
1642       symbol = symbol->next)
1643    {
1644
1645      if (symbol->type->type == coff_secdef_type)
1646	{
1647	  for (i = 0; i < total_sec; i++)
1648	    {
1649	      if (symbol->where->section == info[i].sec)
1650		{
1651		  info[i].symbol = symbol;
1652		  break;
1653		}
1654	    }
1655	}
1656    }
1657
1658  /* Now output all the section info, and fake up some stuff for sections
1659     we don't have */
1660
1661  for (i = 1; i < total_sec; i++)
1662    {
1663      struct IT_sc sc;
1664      char *name;
1665      symbol = info[i].symbol;
1666      sc.spare = 0;
1667      sc.spare1 = 0;
1668      if (!symbol)
1669	{
1670	  /* Don't have a symbol set aside for this section, which means that nothing
1671	     in this file does anything for the section. */
1672	  sc.format = !(bfd_get_file_flags (abfd) & EXEC_P);
1673	  sc.addr = 0;
1674	  sc.length = 0;
1675	  name = info[i].sec->name;
1676	}
1677      else
1678	{
1679	  if (bfd_get_file_flags (abfd) & EXEC_P)
1680	    {
1681	      sc.format = 0;
1682	      sc.addr = symbol->where->offset;
1683	    }
1684	  else
1685	    {
1686	      sc.format = 1;
1687	      sc.addr = 0;
1688	    }
1689	  sc.length = symbol->type->size;
1690	  name = symbol->name;
1691	}
1692
1693      sc.align = 4;
1694
1695      sc.concat = CONCAT_SIMPLE;
1696      sc.read = 3;
1697      sc.write = 3;
1698      sc.exec = 3;
1699      sc.init = 3;
1700      sc.mode = 3;
1701      sc.spare = 0;
1702      sc.segadd = 0;
1703      sc.spare1 = 0;		/* If not zero, then it doesn't work */
1704      sc.name = section_translate (name);
1705      if (strlen (sc.name) == 1)
1706	{
1707	  switch (sc.name[0])
1708	    {
1709	    case 'D':
1710	    case 'B':
1711	      sc.contents = CONTENTS_DATA;
1712	      break;
1713	    default:
1714	      sc.contents = CONTENTS_CODE;
1715	    }
1716	}
1717      else
1718	{
1719	  sc.contents = CONTENTS_CODE;
1720	}
1721#if 0
1722      /* NEW */
1723      if (sc.length) {
1724#endif
1725	sysroff_swap_sc_out (file, &sc);
1726	scount++;
1727#if 0
1728      }
1729#endif
1730    }
1731return scount;
1732}
1733
1734
1735/* Write out the ER records for a unit. */
1736static void
1737wr_er (ptr, sfile, first)
1738     struct coff_ofile *ptr;
1739     struct coff_sfile *sfile ATTRIBUTE_UNUSED;
1740     int first;
1741{
1742  int idx = 0;
1743  struct coff_symbol *sym;
1744  if (first)
1745    {
1746      for (sym = ptr->symbol_list_head; sym; sym = sym->next_in_ofile_list)
1747	{
1748	  if (sym->visible->type == coff_vis_ext_ref)
1749	    {
1750	      struct IT_er er;
1751	      er.spare = 0;
1752	      er.type = ER_NOTSPEC;
1753	      er.name = sym->name;
1754	      sysroff_swap_er_out (file, &er);
1755	      sym->er_number = idx++;
1756	    }
1757	}
1758    }
1759}
1760
1761/* Write out the ED records for a unit. */
1762static void
1763wr_ed (ptr, sfile, first)
1764     struct coff_ofile *ptr;
1765     struct coff_sfile *sfile ATTRIBUTE_UNUSED;
1766     int first;
1767{
1768  struct coff_symbol *s;
1769  if (first)
1770    {
1771      for (s = ptr->symbol_list_head; s; s = s->next_in_ofile_list)
1772	{
1773	  if (s->visible->type == coff_vis_ext_def
1774	      || s->visible->type == coff_vis_common)
1775	    {
1776	      struct IT_ed ed;
1777
1778	      ed.section = s->where->section->number;
1779	      ed.spare = 0;
1780	      if (s->where->section->data)
1781		{
1782		  ed.type = ED_TYPE_DATA;
1783		}
1784	      else if (s->where->section->code & SEC_CODE)
1785		{
1786		  ed.type = ED_TYPE_ENTRY;
1787		}
1788	      else
1789		{
1790		  ed.type = ED_TYPE_NOTSPEC;
1791		  ed.type = ED_TYPE_DATA;
1792		}
1793	      ed.address = s->where->offset - s->where->section->address;
1794	      ed.name = s->name;
1795	      sysroff_swap_ed_out (file, &ed);
1796	    }
1797	}
1798    }
1799}
1800
1801static void
1802wr_unit_info (ptr)
1803     struct coff_ofile *ptr;
1804{
1805  struct coff_sfile *sfile;
1806  int first = 1;
1807  for (sfile = ptr->source_head;
1808       sfile;
1809       sfile = sfile->next)
1810    {
1811      long p1;
1812      long p2;
1813      int nsecs;
1814      p1 = ftell (file);
1815      wr_un (ptr, sfile, first, 0);
1816      nsecs = wr_sc (ptr, sfile);
1817      p2 = ftell (file);
1818      fseek (file, p1, SEEK_SET);
1819      wr_un (ptr, sfile, first, nsecs);
1820      fseek (file, p2, SEEK_SET);
1821      wr_er (ptr, sfile, first);
1822      wr_ed (ptr, sfile, first);
1823      first = 0;
1824    }
1825}
1826
1827static void
1828wr_module (p)
1829     struct coff_ofile *p;
1830{
1831  wr_cs ();
1832  wr_hd (p);
1833  wr_unit_info (p);
1834  wr_object_body (p);
1835  wr_debug (p);
1836  wr_tr ();
1837}
1838
1839static int
1840align (x)
1841     int x;
1842{
1843  return (x + 3) & ~3;
1844}
1845
1846/* Find all the common variables and turn them into
1847   ordinary defs - dunno why, but thats what hitachi does with 'em */
1848
1849static void
1850prescan (tree)
1851     struct coff_ofile *tree;
1852{
1853  struct coff_symbol *s;
1854  struct coff_section *common_section;
1855  /* Find the common section - always section 3 */
1856  common_section = tree->sections + 3;
1857  for (s = tree->symbol_list_head;
1858       s;
1859       s = s->next_in_ofile_list)
1860    {
1861      if (s->visible->type == coff_vis_common)
1862	{
1863	  struct coff_where *w = s->where;
1864	  /*      s->visible->type = coff_vis_ext_def; leave it as common */
1865	  common_section->size = align (common_section->size);
1866	  w->offset = common_section->size + common_section->address;
1867	  w->section = common_section;
1868	  common_section->size += s->type->size;
1869	  common_section->size = align (common_section->size);
1870	}
1871    }
1872}
1873
1874char *program_name;
1875
1876static void
1877show_usage (file, status)
1878     FILE *file;
1879     int status;
1880{
1881  fprintf (file, _("Usage: %s [-dhVq] in-file [out-file]\n"), program_name);
1882  exit (status);
1883}
1884
1885static void
1886show_help ()
1887{
1888  printf (_("%s: Convert a COFF object file into a SYSROFF object file\n"),
1889	  program_name);
1890  show_usage (stdout, 0);
1891}
1892
1893
1894
1895int
1896main (ac, av)
1897     int ac;
1898     char *av[];
1899{
1900  int opt;
1901  static struct option long_options[] =
1902  {
1903    {"debug", no_argument, 0, 'd'},
1904    {"quick", no_argument, 0, 'q'},
1905    {"noprescan", no_argument, 0, 'n'},
1906    {"help", no_argument, 0, 'h'},
1907    {"version", no_argument, 0, 'V'},
1908    {NULL, no_argument, 0, 0}
1909  };
1910  char **matching;
1911  char *input_file;
1912  char *output_file;
1913
1914#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
1915  setlocale (LC_MESSAGES, "");
1916#endif
1917  bindtextdomain (PACKAGE, LOCALEDIR);
1918  textdomain (PACKAGE);
1919
1920  program_name = av[0];
1921  xmalloc_set_program_name (program_name);
1922
1923  while ((opt = getopt_long (ac, av, "dhVqn", long_options,
1924			     (int *) NULL))
1925	 != EOF)
1926    {
1927      switch (opt)
1928	{
1929	case 'q':
1930	  quick = 1;
1931	  break;
1932	case 'n':
1933	  noprescan = 1;
1934	  break;
1935	case 'd':
1936	  debug = 1;
1937	  break;
1938	case 'h':
1939	  show_help ();
1940	  /*NOTREACHED */
1941	case 'V':
1942	  printf (_("GNU %s version %s\n"), program_name, PROGRAM_VERSION);
1943	  exit (0);
1944	  /*NOTREACHED */
1945	case 0:
1946	  break;
1947	default:
1948	  show_usage (stderr, 1);
1949	  /*NOTREACHED */
1950	}
1951    }
1952
1953  /* The input and output files may be named on the command line.  */
1954  output_file = NULL;
1955  if (optind < ac)
1956    {
1957      input_file = av[optind];
1958      ++optind;
1959      if (optind < ac)
1960	{
1961	  output_file = av[optind];
1962	  ++optind;
1963	  if (optind < ac)
1964	    show_usage (stderr, 1);
1965	  if (strcmp (input_file, output_file) == 0)
1966	    {
1967	      fatal (_("input and output files must be different"));
1968	    }
1969	}
1970    }
1971  else
1972    input_file = 0;
1973
1974  if (!input_file)
1975    {
1976      fatal (_("no input file specified"));
1977    }
1978
1979  if (!output_file)
1980    {
1981      /* Take a .o off the input file and stick on a .obj.  If
1982         it doesn't end in .o, then stick a .obj on anyway */
1983
1984      int len = strlen (input_file);
1985      output_file = xmalloc (len + 5);
1986      strcpy (output_file, input_file);
1987      if (len > 3
1988	  && output_file[len - 2] == '.'
1989	  && output_file[len - 1] == 'o')
1990	{
1991	  output_file[len] = 'b';
1992	  output_file[len + 1] = 'j';
1993	  output_file[len + 2] = 0;
1994	}
1995      else
1996	{
1997	  strcat (output_file, ".obj");
1998	}
1999    }
2000
2001  abfd = bfd_openr (input_file, 0);
2002
2003  if (!abfd)
2004    bfd_fatal (input_file);
2005
2006  if (!bfd_check_format_matches (abfd, bfd_object, &matching))
2007    {
2008      bfd_nonfatal (input_file);
2009      if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
2010	{
2011	  list_matching_formats (matching);
2012	  free (matching);
2013	}
2014      exit (1);
2015    }
2016
2017  file = fopen (output_file, FOPEN_WB);
2018
2019  if (!file)
2020    {
2021      fatal (_("unable to open output file %s"), output_file);
2022    }
2023
2024  if (debug)
2025    printf ("ids %d %d\n", base1, base2);
2026  tree = coff_grok (abfd);
2027  if (!noprescan)
2028    prescan (tree);
2029  wr_module (tree);
2030  return 0;
2031}
2032