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