WARNS=6 safeness:
[dragonfly.git] / contrib / binutils-2.14 / binutils / bucomm.c
1 /* bucomm.c -- Bin Utils COMmon code.
2    Copyright 1991, 1992, 1993, 1994, 1995, 1997, 1998, 2000, 2001, 2002, 2003
3    Free Software Foundation, Inc.
4
5    This file is part of GNU Binutils.
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20    02111-1307, USA.  */
21 \f
22 /* We might put this in a library someday so it could be dynamically
23    loaded, but for now it's not necessary.  */
24
25 #include "bfd.h"
26 #include "bfdver.h"
27 #include "libiberty.h"
28 #include "bucomm.h"
29 #include "filenames.h"
30 #include "libbfd.h"
31
32 #include <sys/stat.h>
33 #include <time.h>               /* ctime, maybe time_t */
34
35 #ifndef HAVE_TIME_T_IN_TIME_H
36 #ifndef HAVE_TIME_T_IN_TYPES_H
37 typedef long time_t;
38 #endif
39 #endif
40
41 static const char * endian_string PARAMS ((enum bfd_endian));
42 static int display_target_list PARAMS ((void));
43 static int display_info_table PARAMS ((int, int));
44 static int display_target_tables PARAMS ((void));
45 \f
46 /* Error reporting.  */
47
48 char *program_name;
49
50 void
51 bfd_nonfatal (string)
52      const char *string;
53 {
54   const char *errmsg = bfd_errmsg (bfd_get_error ());
55
56   if (string)
57     fprintf (stderr, "%s: %s: %s\n", program_name, string, errmsg);
58   else
59     fprintf (stderr, "%s: %s\n", program_name, errmsg);
60 }
61
62 void
63 bfd_fatal (string)
64      const char *string;
65 {
66   bfd_nonfatal (string);
67   xexit (1);
68 }
69
70 void
71 report (format, args)
72      const char * format;
73      va_list args;
74 {
75   fprintf (stderr, "%s: ", program_name);
76   vfprintf (stderr, format, args);
77   putc ('\n', stderr);
78 }
79
80 void
81 fatal VPARAMS ((const char *format, ...))
82 {
83   VA_OPEN (args, format);
84   VA_FIXEDARG (args, const char *, format);
85
86   report (format, args);
87   VA_CLOSE (args);
88   xexit (1);
89 }
90
91 void
92 non_fatal VPARAMS ((const char *format, ...))
93 {
94   VA_OPEN (args, format);
95   VA_FIXEDARG (args, const char *, format);
96
97   report (format, args);
98   VA_CLOSE (args);
99 }
100
101 /* Set the default BFD target based on the configured target.  Doing
102    this permits the binutils to be configured for a particular target,
103    and linked against a shared BFD library which was configured for a
104    different target.  */
105
106 void
107 set_default_bfd_target ()
108 {
109   /* The macro TARGET is defined by Makefile.  */
110   const char *target = TARGET;
111
112   if (! bfd_set_default_target (target))
113     fatal (_("can't set BFD default target to `%s': %s"),
114            target, bfd_errmsg (bfd_get_error ()));
115 }
116
117 /* After a FALSE return from bfd_check_format_matches with
118    bfd_get_error () == bfd_error_file_ambiguously_recognized, print
119    the possible matching targets.  */
120
121 void
122 list_matching_formats (p)
123      char **p;
124 {
125   fprintf (stderr, _("%s: Matching formats:"), program_name);
126   while (*p)
127     fprintf (stderr, " %s", *p++);
128   fputc ('\n', stderr);
129 }
130
131 /* List the supported targets.  */
132
133 void
134 list_supported_targets (name, f)
135      const char *name;
136      FILE *f;
137 {
138   int t;
139   const char **targ_names = bfd_target_list ();
140
141   if (name == NULL)
142     fprintf (f, _("Supported targets:"));
143   else
144     fprintf (f, _("%s: supported targets:"), name);
145
146   for (t = 0; targ_names[t] != NULL; t++)
147     fprintf (f, " %s", targ_names[t]);
148   fprintf (f, "\n");
149   free (targ_names);
150 }
151
152 /* List the supported architectures.  */
153
154 void
155 list_supported_architectures (name, f)
156      const char *name;
157      FILE *f;
158 {
159   const char **arch;
160
161   if (name == NULL)
162     fprintf (f, _("Supported architectures:"));
163   else
164     fprintf (f, _("%s: supported architectures:"), name);
165
166   for (arch = bfd_arch_list (); *arch; arch++)
167     fprintf (f, " %s", *arch);
168   fprintf (f, "\n");
169 }
170 \f
171 /* The length of the longest architecture name + 1.  */
172 #define LONGEST_ARCH sizeof ("powerpc:common")
173
174 static const char *
175 endian_string (endian)
176      enum bfd_endian endian;
177 {
178   switch (endian)
179     {
180     case BFD_ENDIAN_BIG: return "big endian";
181     case BFD_ENDIAN_LITTLE: return "little endian";
182     default: return "endianness unknown";
183     }
184 }
185
186 /* List the targets that BFD is configured to support, each followed
187    by its endianness and the architectures it supports.  */
188
189 static int
190 display_target_list ()
191 {
192   char *dummy_name;
193   int t;
194   int ret = 1;
195
196   dummy_name = make_temp_file (NULL);
197   for (t = 0; bfd_target_vector[t]; t++)
198     {
199       const bfd_target *p = bfd_target_vector[t];
200       bfd *abfd = bfd_openw (dummy_name, p->name);
201       int a;
202
203       printf ("%s\n (header %s, data %s)\n", p->name,
204               endian_string (p->header_byteorder),
205               endian_string (p->byteorder));
206
207       if (abfd == NULL)
208         {
209           bfd_nonfatal (dummy_name);
210           ret = 0;
211           continue;
212         }
213
214       if (! bfd_set_format (abfd, bfd_object))
215         {
216           if (bfd_get_error () != bfd_error_invalid_operation)
217             {
218               bfd_nonfatal (p->name);
219               ret = 0;
220             }
221           bfd_close_all_done (abfd);
222           continue;
223         }
224
225       for (a = (int) bfd_arch_obscure + 1; a < (int) bfd_arch_last; a++)
226         if (bfd_set_arch_mach (abfd, (enum bfd_architecture) a, 0))
227           printf ("  %s\n",
228                   bfd_printable_arch_mach ((enum bfd_architecture) a, 0));
229       bfd_close_all_done (abfd);
230     }
231   unlink (dummy_name);
232   free (dummy_name);
233
234   return ret;
235 }
236
237 /* Print a table showing which architectures are supported for entries
238    FIRST through LAST-1 of bfd_target_vector (targets across,
239    architectures down).  */
240
241 static int
242 display_info_table (first, last)
243      int first;
244      int last;
245 {
246   int t;
247   int a;
248   int ret = 1;
249   char *dummy_name;
250
251   /* Print heading of target names.  */
252   printf ("\n%*s", (int) LONGEST_ARCH, " ");
253   for (t = first; t < last && bfd_target_vector[t]; t++)
254     printf ("%s ", bfd_target_vector[t]->name);
255   putchar ('\n');
256
257   dummy_name = make_temp_file (NULL);
258   for (a = (int) bfd_arch_obscure + 1; a < (int) bfd_arch_last; a++)
259     if (strcmp (bfd_printable_arch_mach (a, 0), "UNKNOWN!") != 0)
260       {
261         printf ("%*s ", (int) LONGEST_ARCH - 1,
262                 bfd_printable_arch_mach (a, 0));
263         for (t = first; t < last && bfd_target_vector[t]; t++)
264           {
265             const bfd_target *p = bfd_target_vector[t];
266             bfd_boolean ok = TRUE;
267             bfd *abfd = bfd_openw (dummy_name, p->name);
268
269             if (abfd == NULL)
270               {
271                 bfd_nonfatal (p->name);
272                 ret = 0;
273                 ok = FALSE;
274               }
275
276             if (ok)
277               {
278                 if (! bfd_set_format (abfd, bfd_object))
279                   {
280                     if (bfd_get_error () != bfd_error_invalid_operation)
281                       {
282                         bfd_nonfatal (p->name);
283                         ret = 0;
284                       }
285                     ok = FALSE;
286                   }
287               }
288
289             if (ok)
290               {
291                 if (! bfd_set_arch_mach (abfd, a, 0))
292                   ok = FALSE;
293               }
294
295             if (ok)
296               printf ("%s ", p->name);
297             else
298               {
299                 int l = strlen (p->name);
300                 while (l--)
301                   putchar ('-');
302                 putchar (' ');
303               }
304             if (abfd != NULL)
305               bfd_close_all_done (abfd);
306           }
307         putchar ('\n');
308       }
309   unlink (dummy_name);
310   free (dummy_name);
311
312   return ret;
313 }
314
315 /* Print tables of all the target-architecture combinations that
316    BFD has been configured to support.  */
317
318 static int
319 display_target_tables ()
320 {
321   int t;
322   int columns;
323   int ret = 1;
324   char *colum;
325
326   columns = 0;
327   colum = getenv ("COLUMNS");
328   if (colum != NULL)
329     columns = atoi (colum);
330   if (columns == 0)
331     columns = 80;
332
333   t = 0;
334   while (bfd_target_vector[t] != NULL)
335     {
336       int oldt = t, wid;
337
338       wid = LONGEST_ARCH + strlen (bfd_target_vector[t]->name) + 1;
339       ++t;
340       while (wid < columns && bfd_target_vector[t] != NULL)
341         {
342           int newwid;
343
344           newwid = wid + strlen (bfd_target_vector[t]->name) + 1;
345           if (newwid >= columns)
346             break;
347           wid = newwid;
348           ++t;
349         }
350       if (! display_info_table (oldt, t))
351         ret = 0;
352     }
353
354   return ret;
355 }
356
357 int
358 display_info ()
359 {
360   printf (_("BFD header file version %s\n"), BFD_VERSION_STRING);
361   if (! display_target_list () || ! display_target_tables ())
362     return 1;
363   else
364     return 0;
365 }
366 \f
367 /* Display the archive header for an element as if it were an ls -l listing:
368
369    Mode       User\tGroup\tSize\tDate               Name */
370
371 void
372 print_arelt_descr (file, abfd, verbose)
373      FILE *file;
374      bfd *abfd;
375      bfd_boolean verbose;
376 {
377   struct stat buf;
378
379   if (verbose)
380     {
381       if (bfd_stat_arch_elt (abfd, &buf) == 0)
382         {
383           char modebuf[11];
384           char timebuf[40];
385           time_t when = buf.st_mtime;
386           const char *ctime_result = (const char *) ctime (&when);
387
388           /* POSIX format:  skip weekday and seconds from ctime output.  */
389           sprintf (timebuf, "%.12s %.4s", ctime_result + 4, ctime_result + 20);
390
391           mode_string (buf.st_mode, modebuf);
392           modebuf[10] = '\0';
393           /* POSIX 1003.2/D11 says to skip first character (entry type).  */
394           fprintf (file, "%s %ld/%ld %6ld %s ", modebuf + 1,
395                    (long) buf.st_uid, (long) buf.st_gid,
396                    (long) buf.st_size, timebuf);
397         }
398     }
399
400   fprintf (file, "%s\n", bfd_get_filename (abfd));
401 }
402
403 /* Return the name of a temporary file in the same directory as FILENAME.  */
404
405 char *
406 make_tempname (filename)
407      char *filename;
408 {
409   static char template[] = "stXXXXXX";
410   char *tmpname;
411   char *slash = strrchr (filename, '/');
412
413 #ifdef HAVE_DOS_BASED_FILE_SYSTEM
414   {
415     /* We could have foo/bar\\baz, or foo\\bar, or d:bar.  */
416     char *bslash = strrchr (filename, '\\');
417     if (slash == NULL || (bslash != NULL && bslash > slash))
418       slash = bslash;
419     if (slash == NULL && filename[0] != '\0' && filename[1] == ':')
420       slash = filename + 1;
421   }
422 #endif
423
424   if (slash != (char *) NULL)
425     {
426       char c;
427
428       c = *slash;
429       *slash = 0;
430       tmpname = xmalloc (strlen (filename) + sizeof (template) + 2);
431       strcpy (tmpname, filename);
432 #ifdef HAVE_DOS_BASED_FILE_SYSTEM
433       /* If tmpname is "X:", appending a slash will make it a root
434          directory on drive X, which is NOT the same as the current
435          directory on drive X.  */
436       if (tmpname[1] == ':' && tmpname[2] == '\0')
437         strcat (tmpname, ".");
438 #endif
439       strcat (tmpname, "/");
440       strcat (tmpname, template);
441       mktemp (tmpname);
442       *slash = c;
443     }
444   else
445     {
446       tmpname = xmalloc (sizeof (template));
447       strcpy (tmpname, template);
448       mktemp (tmpname);
449     }
450   return tmpname;
451 }
452
453 /* Parse a string into a VMA, with a fatal error if it can't be
454    parsed.  */
455
456 bfd_vma
457 parse_vma (s, arg)
458      const char *s;
459      const char *arg;
460 {
461   bfd_vma ret;
462   const char *end;
463
464   ret = bfd_scan_vma (s, &end, 0);
465
466   if (*end != '\0')
467     fatal (_("%s: bad number: %s"), arg, s);
468
469   return ret;
470 }