* bucomm.c (bfd_nonfatal_message): New.
[deliverable/binutils-gdb.git] / binutils / bucomm.c
CommitLineData
252b5132 1/* bucomm.c -- Bin Utils COMmon code.
485be063 2 Copyright 1991, 1992, 1993, 1994, 1995, 1997, 1998, 2000, 2001, 2002,
3db64b00 3 2003, 2006, 2007
37cc8ec1 4 Free Software Foundation, Inc.
252b5132
RH
5
6 This file is part of GNU Binutils.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
32866df7 10 the Free Software Foundation; either version 3 of the License, or
252b5132
RH
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
b43b5d5f
NC
20 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
21 02110-1301, USA. */
252b5132
RH
22\f
23/* We might put this in a library someday so it could be dynamically
24 loaded, but for now it's not necessary. */
25
3db64b00 26#include "sysdep.h"
252b5132
RH
27#include "bfd.h"
28#include "libiberty.h"
5af11cab 29#include "filenames.h"
06d86cf7 30#include "libbfd.h"
252b5132
RH
31
32#include <sys/stat.h>
33#include <time.h> /* ctime, maybe time_t */
77f762d6 34#include <assert.h>
3db64b00 35#include "bucomm.h"
252b5132
RH
36
37#ifndef HAVE_TIME_T_IN_TIME_H
38#ifndef HAVE_TIME_T_IN_TYPES_H
39typedef long time_t;
40#endif
41#endif
06d86cf7 42
2da42df6
AJ
43static const char * endian_string (enum bfd_endian);
44static int display_target_list (void);
45static int display_info_table (int, int);
46static int display_target_tables (void);
252b5132 47\f
06d86cf7 48/* Error reporting. */
252b5132
RH
49
50char *program_name;
51
52void
2da42df6 53bfd_nonfatal (const char *string)
252b5132 54{
b1f88ebe 55 const char *errmsg = bfd_errmsg (bfd_get_error ());
252b5132
RH
56
57 if (string)
58 fprintf (stderr, "%s: %s: %s\n", program_name, string, errmsg);
59 else
60 fprintf (stderr, "%s: %s\n", program_name, errmsg);
61}
62
2db6cde7
NS
63/* Issue a non fatal error message. FILENAME, or if NULL then BFD,
64 are used to indicate the problematic file. SECTION, if non NULL,
65 is used to provide a section name. If FORMAT is non-null, then it
66 is used to print additional information via vfprintf. Finally the
67 bfd error message is printed. In summary, error messages are of
68 one of the following forms:
69
70 PROGRAM:file: bfd-error-message
71 PROGRAM:file[section]: bfd-error-message
72 PROGRAM:file: printf-message: bfd-error-message
73 PROGRAM:file[section]: printf-message: bfd-error-message
74*/
75
76void
77bfd_nonfatal_message (const char *filename,
78 const bfd *bfd, const asection *section,
79 const char *format, ...)
80{
81 const char *errmsg = bfd_errmsg (bfd_get_error ());
82 const char *section_name = NULL;
83 va_list args;
84
85 va_start (args, format);
86 fprintf (stderr, "%s", program_name);
87
88 if (bfd)
89 {
90 if (!filename)
91 filename = bfd_get_filename (bfd);
92 if (section)
93 section_name = bfd_get_section_name (bfd, section);
94 }
95 if (section_name)
96 fprintf (stderr, ":%s[%s]", filename, section_name);
97 else
98 fprintf (stderr, ":%s", filename);
99
100 if (format)
101 {
102 fprintf (stderr, ": ");
103 vfprintf (stderr, format, args);
104 }
105 fprintf (stderr, ": %s\n", errmsg);
106 va_end (args);
107}
108
252b5132 109void
2da42df6 110bfd_fatal (const char *string)
252b5132
RH
111{
112 bfd_nonfatal (string);
113 xexit (1);
114}
115
cba12006 116void
2da42df6 117report (const char * format, va_list args)
252b5132
RH
118{
119 fprintf (stderr, "%s: ", program_name);
120 vfprintf (stderr, format, args);
121 putc ('\n', stderr);
122}
123
252b5132 124void
451dad9c 125fatal VPARAMS ((const char *format, ...))
252b5132 126{
451dad9c
AM
127 VA_OPEN (args, format);
128 VA_FIXEDARG (args, const char *, format);
252b5132 129
252b5132 130 report (format, args);
451dad9c 131 VA_CLOSE (args);
252b5132
RH
132 xexit (1);
133}
134
135void
451dad9c 136non_fatal VPARAMS ((const char *format, ...))
252b5132 137{
451dad9c
AM
138 VA_OPEN (args, format);
139 VA_FIXEDARG (args, const char *, format);
252b5132 140
252b5132 141 report (format, args);
451dad9c 142 VA_CLOSE (args);
252b5132 143}
252b5132
RH
144
145/* Set the default BFD target based on the configured target. Doing
146 this permits the binutils to be configured for a particular target,
147 and linked against a shared BFD library which was configured for a
148 different target. */
149
150void
2da42df6 151set_default_bfd_target (void)
252b5132
RH
152{
153 /* The macro TARGET is defined by Makefile. */
154 const char *target = TARGET;
155
156 if (! bfd_set_default_target (target))
157 fatal (_("can't set BFD default target to `%s': %s"),
158 target, bfd_errmsg (bfd_get_error ()));
159}
160
b34976b6 161/* After a FALSE return from bfd_check_format_matches with
252b5132
RH
162 bfd_get_error () == bfd_error_file_ambiguously_recognized, print
163 the possible matching targets. */
164
165void
2da42df6 166list_matching_formats (char **p)
252b5132
RH
167{
168 fprintf (stderr, _("%s: Matching formats:"), program_name);
169 while (*p)
170 fprintf (stderr, " %s", *p++);
171 fputc ('\n', stderr);
172}
173
174/* List the supported targets. */
175
176void
2da42df6 177list_supported_targets (const char *name, FILE *f)
252b5132 178{
252b5132 179 int t;
48417c1a 180 const char **targ_names = bfd_target_list ();
252b5132
RH
181
182 if (name == NULL)
183 fprintf (f, _("Supported targets:"));
184 else
185 fprintf (f, _("%s: supported targets:"), name);
48417c1a
AM
186
187 for (t = 0; targ_names[t] != NULL; t++)
188 fprintf (f, " %s", targ_names[t]);
252b5132 189 fprintf (f, "\n");
48417c1a 190 free (targ_names);
252b5132 191}
2f83960e
AM
192
193/* List the supported architectures. */
194
195void
2da42df6 196list_supported_architectures (const char *name, FILE *f)
2f83960e 197{
48417c1a 198 const char **arch;
2f83960e
AM
199
200 if (name == NULL)
201 fprintf (f, _("Supported architectures:"));
202 else
203 fprintf (f, _("%s: supported architectures:"), name);
204
205 for (arch = bfd_arch_list (); *arch; arch++)
206 fprintf (f, " %s", *arch);
207 fprintf (f, "\n");
208}
252b5132 209\f
06d86cf7
NC
210/* The length of the longest architecture name + 1. */
211#define LONGEST_ARCH sizeof ("powerpc:common")
212
213static const char *
2da42df6 214endian_string (enum bfd_endian endian)
06d86cf7
NC
215{
216 switch (endian)
217 {
218 case BFD_ENDIAN_BIG: return "big endian";
219 case BFD_ENDIAN_LITTLE: return "little endian";
220 default: return "endianness unknown";
221 }
222}
223
224/* List the targets that BFD is configured to support, each followed
225 by its endianness and the architectures it supports. */
226
227static int
2da42df6 228display_target_list (void)
06d86cf7
NC
229{
230 char *dummy_name;
231 int t;
232 int ret = 1;
233
234 dummy_name = make_temp_file (NULL);
235 for (t = 0; bfd_target_vector[t]; t++)
236 {
237 const bfd_target *p = bfd_target_vector[t];
238 bfd *abfd = bfd_openw (dummy_name, p->name);
91610c0c 239 enum bfd_architecture a;
06d86cf7
NC
240
241 printf ("%s\n (header %s, data %s)\n", p->name,
242 endian_string (p->header_byteorder),
243 endian_string (p->byteorder));
244
245 if (abfd == NULL)
246 {
247 bfd_nonfatal (dummy_name);
248 ret = 0;
249 continue;
250 }
251
252 if (! bfd_set_format (abfd, bfd_object))
253 {
254 if (bfd_get_error () != bfd_error_invalid_operation)
255 {
256 bfd_nonfatal (p->name);
257 ret = 0;
258 }
259 bfd_close_all_done (abfd);
260 continue;
261 }
262
91610c0c 263 for (a = bfd_arch_obscure + 1; a < bfd_arch_last; a++)
06d86cf7
NC
264 if (bfd_set_arch_mach (abfd, (enum bfd_architecture) a, 0))
265 printf (" %s\n",
266 bfd_printable_arch_mach ((enum bfd_architecture) a, 0));
267 bfd_close_all_done (abfd);
268 }
269 unlink (dummy_name);
270 free (dummy_name);
271
272 return ret;
273}
274
275/* Print a table showing which architectures are supported for entries
276 FIRST through LAST-1 of bfd_target_vector (targets across,
277 architectures down). */
278
279static int
2da42df6 280display_info_table (int first, int last)
06d86cf7
NC
281{
282 int t;
06d86cf7
NC
283 int ret = 1;
284 char *dummy_name;
91610c0c 285 enum bfd_architecture a;
06d86cf7
NC
286
287 /* Print heading of target names. */
288 printf ("\n%*s", (int) LONGEST_ARCH, " ");
289 for (t = first; t < last && bfd_target_vector[t]; t++)
290 printf ("%s ", bfd_target_vector[t]->name);
291 putchar ('\n');
292
293 dummy_name = make_temp_file (NULL);
91610c0c 294 for (a = bfd_arch_obscure + 1; a < bfd_arch_last; a++)
06d86cf7
NC
295 if (strcmp (bfd_printable_arch_mach (a, 0), "UNKNOWN!") != 0)
296 {
297 printf ("%*s ", (int) LONGEST_ARCH - 1,
298 bfd_printable_arch_mach (a, 0));
299 for (t = first; t < last && bfd_target_vector[t]; t++)
300 {
301 const bfd_target *p = bfd_target_vector[t];
302 bfd_boolean ok = TRUE;
303 bfd *abfd = bfd_openw (dummy_name, p->name);
304
305 if (abfd == NULL)
306 {
307 bfd_nonfatal (p->name);
308 ret = 0;
309 ok = FALSE;
310 }
311
312 if (ok)
313 {
314 if (! bfd_set_format (abfd, bfd_object))
315 {
316 if (bfd_get_error () != bfd_error_invalid_operation)
317 {
318 bfd_nonfatal (p->name);
319 ret = 0;
320 }
321 ok = FALSE;
322 }
323 }
324
325 if (ok)
326 {
327 if (! bfd_set_arch_mach (abfd, a, 0))
328 ok = FALSE;
329 }
330
331 if (ok)
332 printf ("%s ", p->name);
333 else
334 {
335 int l = strlen (p->name);
336 while (l--)
337 putchar ('-');
338 putchar (' ');
339 }
340 if (abfd != NULL)
341 bfd_close_all_done (abfd);
342 }
343 putchar ('\n');
344 }
345 unlink (dummy_name);
346 free (dummy_name);
347
348 return ret;
349}
350
351/* Print tables of all the target-architecture combinations that
352 BFD has been configured to support. */
353
354static int
2da42df6 355display_target_tables (void)
06d86cf7
NC
356{
357 int t;
358 int columns;
359 int ret = 1;
360 char *colum;
361
362 columns = 0;
363 colum = getenv ("COLUMNS");
364 if (colum != NULL)
365 columns = atoi (colum);
366 if (columns == 0)
367 columns = 80;
368
369 t = 0;
370 while (bfd_target_vector[t] != NULL)
371 {
372 int oldt = t, wid;
373
374 wid = LONGEST_ARCH + strlen (bfd_target_vector[t]->name) + 1;
375 ++t;
376 while (wid < columns && bfd_target_vector[t] != NULL)
377 {
378 int newwid;
379
380 newwid = wid + strlen (bfd_target_vector[t]->name) + 1;
381 if (newwid >= columns)
382 break;
383 wid = newwid;
384 ++t;
385 }
386 if (! display_info_table (oldt, t))
387 ret = 0;
388 }
389
390 return ret;
391}
392
393int
2da42df6 394display_info (void)
06d86cf7
NC
395{
396 printf (_("BFD header file version %s\n"), BFD_VERSION_STRING);
397 if (! display_target_list () || ! display_target_tables ())
398 return 1;
399 else
400 return 0;
401}
402\f
252b5132
RH
403/* Display the archive header for an element as if it were an ls -l listing:
404
405 Mode User\tGroup\tSize\tDate Name */
406
407void
2da42df6 408print_arelt_descr (FILE *file, bfd *abfd, bfd_boolean verbose)
252b5132
RH
409{
410 struct stat buf;
411
412 if (verbose)
413 {
414 if (bfd_stat_arch_elt (abfd, &buf) == 0)
415 {
416 char modebuf[11];
417 char timebuf[40];
418 time_t when = buf.st_mtime;
b1f88ebe 419 const char *ctime_result = (const char *) ctime (&when);
252b5132
RH
420
421 /* POSIX format: skip weekday and seconds from ctime output. */
422 sprintf (timebuf, "%.12s %.4s", ctime_result + 4, ctime_result + 20);
423
424 mode_string (buf.st_mode, modebuf);
425 modebuf[10] = '\0';
426 /* POSIX 1003.2/D11 says to skip first character (entry type). */
427 fprintf (file, "%s %ld/%ld %6ld %s ", modebuf + 1,
428 (long) buf.st_uid, (long) buf.st_gid,
429 (long) buf.st_size, timebuf);
430 }
431 }
432
433 fprintf (file, "%s\n", bfd_get_filename (abfd));
434}
435
485be063
AM
436/* Return a path for a new temporary file in the same directory
437 as file PATH. */
252b5132 438
485be063
AM
439static char *
440template_in_dir (const char *path)
252b5132 441{
485be063 442#define template "stXXXXXX"
2946671e 443 const char *slash = strrchr (path, '/');
252b5132 444 char *tmpname;
485be063 445 size_t len;
252b5132 446
5af11cab
AM
447#ifdef HAVE_DOS_BASED_FILE_SYSTEM
448 {
449 /* We could have foo/bar\\baz, or foo\\bar, or d:bar. */
485be063 450 char *bslash = strrchr (path, '\\');
f9c026a8 451
2ab47eed 452 if (slash == NULL || (bslash != NULL && bslash > slash))
5af11cab 453 slash = bslash;
485be063 454 if (slash == NULL && path[0] != '\0' && path[1] == ':')
2946671e 455 slash = path + 1;
5af11cab 456 }
252b5132
RH
457#endif
458
459 if (slash != (char *) NULL)
460 {
485be063
AM
461 len = slash - path;
462 tmpname = xmalloc (len + sizeof (template) + 2);
463 memcpy (tmpname, path, len);
252b5132 464
5af11cab
AM
465#ifdef HAVE_DOS_BASED_FILE_SYSTEM
466 /* If tmpname is "X:", appending a slash will make it a root
467 directory on drive X, which is NOT the same as the current
468 directory on drive X. */
485be063
AM
469 if (len == 2 && tmpname[1] == ':')
470 tmpname[len++] = '.';
5af11cab 471#endif
485be063 472 tmpname[len++] = '/';
252b5132
RH
473 }
474 else
475 {
476 tmpname = xmalloc (sizeof (template));
485be063 477 len = 0;
f9c026a8 478 }
485be063
AM
479
480 memcpy (tmpname + len, template, sizeof (template));
481 return tmpname;
482#undef template
483}
484
485/* Return the name of a created temporary file in the same directory
486 as FILENAME. */
487
488char *
489make_tempname (char *filename)
490{
491 char *tmpname = template_in_dir (filename);
492 int fd;
493
494#ifdef HAVE_MKSTEMP
495 fd = mkstemp (tmpname);
496#else
497 tmpname = mktemp (tmpname);
498 if (tmpname == NULL)
f9c026a8 499 return NULL;
485be063 500 fd = open (tmpname, O_RDWR | O_CREAT | O_EXCL, 0600);
f9c026a8 501#endif
485be063
AM
502 if (fd == -1)
503 return NULL;
504 close (fd);
f9c026a8
NC
505 return tmpname;
506}
507
485be063
AM
508/* Return the name of a created temporary directory inside the
509 directory containing FILENAME. */
f9c026a8
NC
510
511char *
512make_tempdir (char *filename)
513{
485be063 514 char *tmpname = template_in_dir (filename);
f9c026a8 515
485be063
AM
516#ifdef HAVE_MKDTEMP
517 return mkdtemp (tmpname);
518#else
519 tmpname = mktemp (tmpname);
520 if (tmpname == NULL)
521 return NULL;
522#if defined (_WIN32) && !defined (__CYGWIN32__)
523 if (mkdir (tmpname) != 0)
524 return NULL;
525#else
526 if (mkdir (tmpname, 0700) != 0)
527 return NULL;
f9c026a8 528#endif
252b5132 529 return tmpname;
485be063 530#endif
252b5132
RH
531}
532
533/* Parse a string into a VMA, with a fatal error if it can't be
534 parsed. */
535
536bfd_vma
2da42df6 537parse_vma (const char *s, const char *arg)
252b5132
RH
538{
539 bfd_vma ret;
540 const char *end;
541
542 ret = bfd_scan_vma (s, &end, 0);
f462a9ea 543
252b5132
RH
544 if (*end != '\0')
545 fatal (_("%s: bad number: %s"), arg, s);
546
547 return ret;
548}
f24ddbdd
NC
549
550/* Returns the size of the named file. If the file does not
551 exist, or if it is not a real file, then a suitable non-fatal
552 error message is printed and zero is returned. */
553
554off_t
555get_file_size (const char * file_name)
556{
557 struct stat statbuf;
558
559 if (stat (file_name, &statbuf) < 0)
560 {
561 if (errno == ENOENT)
562 non_fatal (_("'%s': No such file"), file_name);
563 else
564 non_fatal (_("Warning: could not locate '%s'. reason: %s"),
565 file_name, strerror (errno));
566 }
567 else if (! S_ISREG (statbuf.st_mode))
568 non_fatal (_("Warning: '%s' is not an ordinary file"), file_name);
569 else
570 return statbuf.st_size;
571
572 return 0;
573}
77f762d6
L
574
575/* Return the filename in a static buffer. */
576
577const char *
578bfd_get_archive_filename (bfd *abfd)
579{
580 static size_t curr = 0;
581 static char *buf;
582 size_t needed;
583
584 assert (abfd != NULL);
585
586 if (!abfd->my_archive)
587 return bfd_get_filename (abfd);
588
589 needed = (strlen (bfd_get_filename (abfd->my_archive))
590 + strlen (bfd_get_filename (abfd)) + 3);
591 if (needed > curr)
592 {
593 if (curr)
594 free (buf);
595 curr = needed + (needed >> 1);
596 buf = bfd_malloc (curr);
597 /* If we can't malloc, fail safe by returning just the file name.
598 This function is only used when building error messages. */
599 if (!buf)
600 {
601 curr = 0;
602 return bfd_get_filename (abfd);
603 }
604 }
605 sprintf (buf, "%s(%s)", bfd_get_filename (abfd->my_archive),
606 bfd_get_filename (abfd));
607 return buf;
608}
This page took 0.332437 seconds and 4 git commands to generate.