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