keep riscix, pc532mach files
[deliverable/binutils-gdb.git] / ld / ldmisc.c
index 8af24d99ef25ad126b55494409438856bc96e99c..9c5b3e5c1febad4c7d1bbd734e57c964a8c05f5a 100644 (file)
@@ -1,5 +1,5 @@
 /* ldmisc.c
-   Copyright (C) 1991 Free Software Foundation, Inc.
+   Copyright (C) 1991, 92, 93, 94 Free Software Foundation, Inc.
 
    Written by Steve Chamberlain of Cygnus Support.
 
@@ -26,57 +26,53 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 #include "ld.h"
 #include "ldmisc.h"
+#include "ldexp.h"
 #include "ldlang.h"
+#include "ldgram.h"
 #include "ldlex.h"
-/* IMPORTS */
-
-extern char *program_name;
-
-extern FILE *ldlex_input_stack;
-extern char *ldfile_input_filename;
-extern ld_config_type config;
-
-
-extern int errno;
-extern   int  sys_nerr;
-extern char *sys_errlist[];
+#include "ldmain.h"
+#include "ldfile.h"
 
 /* VARARGS*/
 static void finfo ();
+static const char *demangle PARAMS ((const char *string,
+                                    int remove_underscore));
 
 /*
+ %% literal %
  %F error is fatal
- %P print progam name
+ %P print program name
  %S print script file and linenumber
  %E current bfd error or errno
  %I filename from a lang_input_statement_type
  %B filename from a bfd
- %T symbol table entry
+ %T symbol name
  %X no object output, fail return
  %V hex bfd_vma
  %v hex bfd_vma, no leading zeros
- %C Clever filename:linenumber 
+ %C clever filename:linenumber with function
+ %D like %C, but no function name
  %R info about a relent
- %
+ %s arbitrary string, like printf
+ %d integer, like printf
 */
-extern bfd *output_bfd;
 
-static char *
-demangle(string, remove_underscore)
-char *string;
-int remove_underscore;
+static const char *
+demangle (string, remove_underscore)
+     const char *string;
+     int remove_underscore;
 {
-  char *res;
+  const char *res;
   if (remove_underscore && output_bfd) 
   {
-    if (bfd_get_symbol_leading_char(output_bfd) == string[0])
+    if (bfd_get_symbol_leading_char (output_bfd) == string[0])
      string++;
   }
   /* Note that there's a memory leak here, we keep buying memory
      for demangled names, and never free.  But if you have so many
      errors that you run out of VM with the error messages, then
      there's something up */
-  res = cplus_demangle(string, DMGL_ANSI|DMGL_PARAMS);
+  res = cplus_demangle (string, DMGL_ANSI|DMGL_PARAMS);
   return res ? res : string;
 }
 
@@ -87,6 +83,7 @@ vfinfo(fp, fmt, arg)
      va_list arg;
 {
   boolean fatal = false;
+
   while (*fmt) 
   {
     while (*fmt != '%' && *fmt != '\0') 
@@ -94,21 +91,36 @@ vfinfo(fp, fmt, arg)
       putc(*fmt, fp);
       fmt++;
     }
+
     if (*fmt == '%') 
     {
       fmt ++;
       switch (*fmt++) 
       {
+      default:
+       fprintf(fp,"%%%c", fmt[-1]);
+       break;
+
+      case '%':
+       /* literal % */
+       putc('%', fp);
+       break;
+
        case 'X':
+       /* no object output, fail return */
        config.make_executable = false;
        break;
+
        case 'V':
-       {
-        bfd_vma value = va_arg(arg, bfd_vma);
-        fprintf_vma(fp, value);
-       }
+       /* hex bfd_vma */
+       {
+         bfd_vma value = va_arg(arg, bfd_vma);
+         fprintf_vma(fp, value);
+       }
        break;
+
       case 'v':
+       /* hex bfd_vma, no leading zeros */
        {
          char buf[100];
          char *p = buf;
@@ -121,32 +133,21 @@ vfinfo(fp, fmt, arg)
          fputs (p, fp);
        }
        break;
+
        case 'T':
-       {
-        asymbol *symbol = va_arg(arg, asymbol *);
-        if (symbol) 
-        {
-
-           
-          asection *section = symbol->section;
-          char *cplusname =   demangle(symbol->name, 1);
-          CONST char *section_name =  section->name;
-          if (section != &bfd_und_section) 
-          {
-            fprintf(fp,"%s (%s)", cplusname, section_name);
-          }
-          else 
-          {
-            fprintf(fp,"%s", cplusname);
-          }
-        }
-        else 
-        {
-          fprintf(fp,"no symbol");
-        }
-       }
+       /* Symbol name.  */
+       {
+         const char *name = va_arg (arg, const char *);
+
+         if (name != (const char *) NULL)
+           fprintf (fp, "%s", demangle (name, 1));
+         else
+           fprintf (fp, "no symbol");
+       }
        break;
+
        case 'B':
+       /* filename from a bfd */
        { 
         bfd *abfd = va_arg(arg, bfd *);
         if (abfd->my_archive) {
@@ -155,47 +156,44 @@ vfinfo(fp, fmt, arg)
         }
         else {
           fprintf(fp,"%s", abfd->filename);
-
         }
        }
        break;
+
        case 'F':
+       /* error is fatal */
        fatal = true;
        break;
+
        case 'P':
+       /* print program name */
        fprintf(fp,"%s", program_name);
        break;
-       case 'E':
-       /* Replace with the most recent errno explanation */
-
-
-       fprintf(fp, bfd_errmsg(bfd_error));
-
 
+       case 'E':
+       /* current bfd error or errno */
+       fprintf(fp, bfd_errmsg(bfd_get_error ()));
        break;
+
        case 'I':
+       /* filename from a lang_input_statement_type */
        {
         lang_input_statement_type *i =
          va_arg(arg,lang_input_statement_type *);
-       
+
+        if (i->the_bfd->my_archive)
+          fprintf(fp, "(%s)", i->the_bfd->my_archive->filename);
         fprintf(fp,"%s", i->local_sym_name);
        }
        break;
-       case 'S':
-       /* Print source script file and line number */
 
+       case 'S':
+       /* print script file and linenumber */
        {
-       
-        
-        extern unsigned int lineno;
-        if (ldfile_input_filename == (char *)NULL) {
-          fprintf(fp,"command line");
-        }
-        else {
+        if (ldfile_input_filename) {
           fprintf(fp,"%s:%u", ldfile_input_filename, lineno );
         }
        }
-       
        break;
 
        case 'R':
@@ -210,82 +208,125 @@ vfinfo(fp, fmt, arg)
        }
        break;
        
-
-
-       
        case 'C':
-       {
-        CONST char *filename;
-        CONST char *functionname;
-        char *cplus_name;
-        
-        unsigned int linenumber;
-        bfd *abfd = va_arg(arg, bfd *);
-        asection *section = va_arg(arg, asection *);
-        asymbol **symbols = va_arg(arg, asymbol **);
-        bfd_vma offset = va_arg(arg, bfd_vma);
-        
-        if (bfd_find_nearest_line(abfd,
-                                  section,
-                                  symbols,
-                                  offset,
-                                  &filename,
-                                  &functionname,
-                                  &linenumber))
-        {
-          if (filename == (char *)NULL)        
-           filename = abfd->filename;
-          if (functionname != (char *)NULL) 
-          {
-            /* There is no initial '_' to remove here. */
-            cplus_name = demangle(functionname, 0);
-            fprintf(fp,"%s:%u: (%s)", filename, linenumber, cplus_name);
-          }
-               
-          else if (linenumber != 0) 
-           fprintf(fp,"%s:%u", filename, linenumber);
-          else
-            finfo (fp, "%s(%s+0x%v)", filename, section->name, offset);
-
-        }
-        else
-          finfo (fp, "%s(%s+0x%v)", abfd->filename, section->name, offset);
-       }
+       case 'D':
+       /* Clever filename:linenumber with function name if possible,
+          or section name as a last resort.  The arguments are a BFD,
+          a section, and an offset.  */
+       {
+         static char *last_file = NULL;
+         static char *last_function = NULL;
+         bfd *abfd;
+         asection *section;
+         bfd_vma offset;
+         lang_input_statement_type *entry;
+         asymbol **asymbols;
+         const char *filename;
+         const char *functionname;
+         unsigned int linenumber;
+         boolean discard_last;
+
+         abfd = va_arg (arg, bfd *);
+         section = va_arg (arg, asection *);
+         offset = va_arg (arg, bfd_vma);
+
+         entry = (lang_input_statement_type *) abfd->usrdata;
+         if (entry != (lang_input_statement_type *) NULL
+             && entry->asymbols != (asymbol **) NULL)
+           asymbols = entry->asymbols;
+         else
+           {
+             long symsize;
+             long symbol_count;
+
+             symsize = bfd_get_symtab_upper_bound (abfd);
+             if (symsize < 0)
+               einfo ("%B%F: could not read symbols", abfd);
+             asymbols = (asymbol **) xmalloc (symsize);
+             symbol_count = bfd_canonicalize_symtab (abfd, asymbols);
+             if (symbol_count < 0)
+               einfo ("%B%F: could not read symbols", abfd);
+             if (entry != (lang_input_statement_type *) NULL)
+               {
+                 entry->asymbols = asymbols;
+                 entry->symbol_count = symbol_count;
+               }
+           }
+
+         discard_last = true;
+         if (bfd_find_nearest_line (abfd, section, asymbols, offset,
+                                    &filename, &functionname, &linenumber))
+           {
+             if (filename == (char *) NULL)
+               filename = abfd->filename;
+
+             if (functionname != NULL && fmt[-1] == 'C')
+               {
+                 if (last_file == NULL
+                     || last_function == NULL
+                     || strcmp (last_file, filename) != 0
+                     || strcmp (last_function, functionname) != 0)
+                   {
+                     fprintf (fp, "%s: In function `%s':\n", filename,
+                              demangle (functionname, 1));
+                     if (last_file != NULL)
+                       free (last_file);
+                     last_file = buystring (filename);
+                     if (last_function != NULL)
+                       free (last_function);
+                     last_function = buystring (functionname);
+                   }
+                 discard_last = false;
+                 fprintf (fp, "%s:%u", filename, linenumber);
+               }
+             else if (linenumber != 0) 
+               fprintf (fp, "%s:%u", filename, linenumber);
+             else
+               finfo (fp, "%s(%s+0x%v)", filename, section->name, offset);
+           }
+         else
+           finfo (fp, "%s(%s+0x%v)", abfd->filename, section->name, offset);
+
+         if (discard_last)
+           {
+             if (last_file != NULL)
+               {
+                 free (last_file);
+                 last_file = NULL;
+               }
+             if (last_function != NULL)
+               {
+                 free (last_function);
+                 last_function = NULL;
+               }
+           }
+       }
        break;
                
        case 's':
+       /* arbitrary string, like printf */
        fprintf(fp,"%s", va_arg(arg, char *));
        break;
+
        case 'd':
+       /* integer, like printf */
        fprintf(fp,"%d", va_arg(arg, int));
        break;
-       default:
-       fprintf(fp,"%s", va_arg(arg, char *));
-       break;
       }
     }
   }
+
   if (fatal == true) 
-  {
-    extern char *output_filename;
-    if (output_filename) 
-    {
-      char *new = malloc(strlen(output_filename)+2);
-      extern bfd *output_bfd;
-      
-      strcpy(new, output_filename);
-      if (output_bfd && output_bfd->iostream)
-       fclose((FILE *)(output_bfd->iostream));
-      unlink(new);
-    }
-    exit(1);
-  }
+    xexit(1);
 }
 
 /* Format info message and print on stdout. */
 
-void info(va_alist)
-va_dcl
+/* (You would think this should be called just "info", but then you would
+   hosed by LynxOS, which defines that name in its libc.) */
+
+void info_msg(va_alist)
+     va_dcl
 {
   char *fmt;
   va_list arg;
@@ -298,7 +339,7 @@ va_dcl
 /* ('e' for error.) Format info message and print on stderr. */
 
 void einfo(va_alist)
-va_dcl
+     va_dcl
 {
   char *fmt;
   va_list arg;
@@ -310,86 +351,18 @@ va_dcl
 
 void 
 info_assert(file, line)
-char *file;
-unsigned int line;
+     char *file;
+     unsigned int line;
 {
-  einfo("%F%P internal error %s %d\n", file,line);
+  einfo("%F%P: internal error %s %d\n", file,line);
 }
 
-/* Return a newly-allocated string
-   whose contents concatenate those of S1, S2, S3.  */
-
-char *
-concat (s1, s2, s3)
-     CONST char *s1;
-     CONST char *s2;
-     CONST char *s3;
-{
-  size_t len1 = strlen (s1);
-  size_t len2 = strlen (s2);
-  size_t len3 = strlen (s3);
-  char *result = ldmalloc (len1 + len2 + len3 + 1);
-
-  if (len1 != 0)
-    memcpy(result, s1, len1);
-  if (len2 != 0)
-    memcpy(result+len1, s2, len2);
-  if (len3 != 0)
-    memcpy(result+len1+len2, s2, len3);
-  *(result + len1 + len2 + len3) = 0;
-
-  return result;
-}
-
-
-PTR
-ldmalloc (size)
-     size_t size;
-{
-  PTR result =  malloc ((int)size);
-
-  if (result == (char *)NULL && size != 0)
-    einfo("%F%P virtual memory exhausted\n");
-
-  return result;
-} 
-
-PTR
-xmalloc (size)
-     int size;
-{
-return ldmalloc(size);
-}
-
-
-PTR
-ldrealloc (ptr, size)
-     PTR ptr;
-     size_t size;
-{
-  PTR result =  realloc (ptr, (int)size);
-
-  if (result == (char *)NULL && size != 0)
-    einfo("%F%P virtual memory exhausted\n");
-
-  return result;
-} 
-
-PTR
-xrealloc (ptr, size)
-     PTR ptr;
-     size_t size;
-{
-return ldrealloc(ptr, size);
-}
-
-
 char *
 buystring (x)
      CONST char *CONST x;
 {
   size_t l = strlen(x)+1;
-  char *r = ldmalloc(l);
+  char *r = xmalloc(l);
   memcpy(r, x,l);
   return r;
 }
@@ -398,7 +371,7 @@ buystring (x)
 /* ('m' for map) Format info message and print on map. */
 
 void minfo(va_alist)
-va_dcl
+     va_dcl
 {
   char *fmt;
   va_list arg;
This page took 0.030342 seconds and 4 git commands to generate.