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