* config/m68k/monitor.mt (TDEPFILE): Add remote-es.o.
[deliverable/binutils-gdb.git] / gdb / printcmd.c
index 54b5d942bcb85eb317d11ac109892c534dd72102..f6be18420a28b71edb02d173c28a86a0661229a0 100644 (file)
@@ -1,5 +1,6 @@
 /* Print values for GNU debugger GDB.
-   Copyright 1986, 1987, 1988, 1989, 1990, 1991 Free Software Foundation, Inc.
+   Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1993, 1994
+             Free Software Foundation, Inc.
 
 This file is part of GDB.
 
@@ -19,6 +20,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 #include "defs.h"
 #include <string.h>
+#include <varargs.h>
 #include "frame.h"
 #include "symtab.h"
 #include "gdbtypes.h"
@@ -30,12 +32,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "target.h"
 #include "breakpoint.h"
 #include "demangle.h"
-
-/* These are just for containing_function_bounds.  It might be better
-   to move containing_function_bounds to blockframe.c or thereabouts.  */
-#include "bfd.h"
-#include "symfile.h"
-#include "objfiles.h"
+#include "valprint.h"
 
 extern int asm_demangle;       /* Whether to demangle syms in asm printouts */
 extern int addressprint;       /* Whether to print hex addresses in HLL " */
@@ -77,6 +74,11 @@ static unsigned int max_symbolic_offset = UINT_MAX;
    printing a symbolic value as `<symbol at filename:linenum>' if set.  */
 static int print_symbol_filename = 0;
 
+/* Switch for quick display of symbolic addresses -- only uses minsyms,
+   not full search of symtabs.  */
+
+int fast_symbolic_addr = 1;
+
 /* Number of auto-display expression currently being displayed.
    So that we can disable it if we get an error or a signal within it.
    -1 when not doing one.  */
@@ -127,15 +129,12 @@ disable_display_command PARAMS ((char *, int));
 static void
 disassemble_command PARAMS ((char *, int));
 
-static int
-containing_function_bounds PARAMS ((CORE_ADDR, CORE_ADDR *, CORE_ADDR *));
-
 static void
 printf_command PARAMS ((char *, int));
 
 static void
 print_frame_nameless_args PARAMS ((struct frame_info *, long, int, int,
-                                  FILE *));
+                                  GDB_FILE *));
 
 static void
 display_info PARAMS ((char *, int));
@@ -222,13 +221,6 @@ decode_format (string_ptr, oformat, osize)
     {
       if (*p == 'b' || *p == 'h' || *p == 'w' || *p == 'g')
        val.size = *p++;
-#ifdef CC_HAS_LONG_LONG
-      else if (*p == 'l')
-       {
-         val.size = 'g';
-         p++;
-       }
-#endif
       else if (*p >= 'a' && *p <= 'z')
        val.format = *p++;
       else
@@ -288,7 +280,7 @@ decode_format (string_ptr, oformat, osize)
   return val;
 }
 \f
-/* Print value VAL on stdout according to FORMAT, a letter or 0.
+/* Print value VAL on gdb_stdout according to FORMAT, a letter or 0.
    Do not end with a newline.
    0 means print VAL according to its own type.
    SIZE is the letter for the size of datum being printed.
@@ -309,7 +301,7 @@ print_formatted (val, format, size)
     {
     case 's':
       next_address = VALUE_ADDRESS (val)
-       + value_print (value_addr (val), stdout, format, Val_pretty_default);
+       + value_print (value_addr (val), gdb_stdout, format, Val_pretty_default);
       break;
 
     case 'i':
@@ -318,9 +310,9 @@ print_formatted (val, format, size)
         I'm not completely sure what that means, I suspect most print_insn
         now do use _filtered, so I guess it's obsolete.  */
       /* We often wrap here if there are long symbolic names.  */
-      wrap_here ("\t");
+      wrap_here ("    ");
       next_address = VALUE_ADDRESS (val)
-       + print_insn (VALUE_ADDRESS (val), stdout);
+       + print_insn (VALUE_ADDRESS (val), gdb_stdout);
       break;
 
     default:
@@ -330,10 +322,10 @@ print_formatted (val, format, size)
          || TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_STRUCT
          || TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_UNION
          || VALUE_REPEATED (val))
-       value_print (val, stdout, format, Val_pretty_default);
+       value_print (val, gdb_stdout, format, Val_pretty_default);
       else
        print_scalar_formatted (VALUE_CONTENTS (val), VALUE_TYPE (val),
-                               format, size, stdout);
+                               format, size, gdb_stdout);
     }
 }
 
@@ -350,7 +342,7 @@ print_scalar_formatted (valaddr, type, format, size, stream)
      struct type *type;
      int format;
      int size;
-     FILE *stream;
+     GDB_FILE *stream;
 {
   LONGEST val_long;
   int len = TYPE_LENGTH (type);
@@ -376,15 +368,13 @@ print_scalar_formatted (valaddr, type, format, size, stream)
 
   val_long = unpack_long (type, valaddr);
 
-  /* If value is unsigned, truncate it in case negative.  */
+  /* If we are printing it as unsigned, truncate it in case it is actually
+     a negative signed value (e.g. "print/u (short)-1" should print 65535
+     (if shorts are 16 bits) instead of 4294967295).  */
   if (format != 'd')
     {
-      if (len == sizeof (char))
-       val_long &= (1 << 8 * sizeof(char)) - 1;
-      else if (len == sizeof (short))
-       val_long &= (1 << 8 * sizeof(short)) - 1;
-      else if (len == sizeof (long))
-       val_long &= (unsigned long) - 1;
+      if (len < sizeof (LONGEST))
+       val_long &= ((LONGEST) 1 << HOST_CHAR_BIT * len) - 1;
     }
 
   switch (format)
@@ -513,49 +503,64 @@ set_next_address (addr)
 
 /* Optionally print address ADDR symbolically as <SYMBOL+OFFSET> on STREAM,
    after LEADIN.  Print nothing if no symbolic name is found nearby.
+   Optionally also print source file and line number, if available.
    DO_DEMANGLE controls whether to print a symbol in its native "raw" form,
    or to interpret it as a possible C++ name and convert it back to source
    form.  However note that DO_DEMANGLE can be overridden by the specific
-   settings of the demangle and asm_demangle variables. */
+   settings of the demangle and asm_demangle variables.  */
 
 void
 print_address_symbolic (addr, stream, do_demangle, leadin)
      CORE_ADDR addr;
-     FILE *stream;
+     GDB_FILE *stream;
      int do_demangle;
      char *leadin;
 {
-  CORE_ADDR name_location;
-  register struct symbol *symbol;
+  struct minimal_symbol *msymbol;
+  struct symbol *symbol;
+  struct symtab *symtab = 0;
+  CORE_ADDR name_location = 0;
   char *name;
 
-  /* First try to find the address in the symbol tables to find
-     static functions. If that doesn't succeed we try the minimal symbol
-     vector for symbols in non-text space.
-     FIXME: Should find a way to get at the static non-text symbols too.  */
-  
-  symbol = find_pc_function (addr);
-  if (symbol)
+  /* First try to find the address in the symbol table, then
+     in the minsyms.  Take the closest one.  */
+
+  if (fast_symbolic_addr)
     {
-    name_location = BLOCK_START (SYMBOL_BLOCK_VALUE (symbol));
-    if (do_demangle)
-      name = SYMBOL_SOURCE_NAME (symbol);
-    else
-      name = SYMBOL_LINKAGE_NAME (symbol);
+      /* This is defective in the sense that it only finds text symbols.  */
+      symbol = find_pc_function (addr);
+      if (symbol)
+       name_location = BLOCK_START (SYMBOL_BLOCK_VALUE (symbol));
     }
   else
+    find_addr_symbol (addr, &symtab, &name_location);
+
+  if (symbol)
     {
-    register struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (addr);
+      if (do_demangle)
+       name = SYMBOL_SOURCE_NAME (symbol);
+      else
+       name = SYMBOL_LINKAGE_NAME (symbol);
+    }
 
-    /* If nothing comes out, don't print anything symbolic.  */
-    if (msymbol == NULL)
-      return;
-    name_location = SYMBOL_VALUE_ADDRESS (msymbol);
-    if (do_demangle)
-      name = SYMBOL_SOURCE_NAME (msymbol);
-    else
-      name = SYMBOL_LINKAGE_NAME (msymbol);
+  msymbol = lookup_minimal_symbol_by_pc (addr);
+  if (msymbol != NULL)
+    {
+      if (SYMBOL_VALUE_ADDRESS (msymbol) > name_location || symbol == NULL)
+       {
+         /* The msymbol is closer to the address than the symbol;
+            use the msymbol instead.  */
+         symbol = 0;
+         symtab = 0;
+         name_location = SYMBOL_VALUE_ADDRESS (msymbol);
+         if (do_demangle)
+           name = SYMBOL_SOURCE_NAME (msymbol);
+         else
+           name = SYMBOL_LINKAGE_NAME (msymbol);
+       }
     }
+  if (symbol == NULL && msymbol == NULL)
+    return;
 
   /* If the nearest symbol is too far away, don't print anything symbolic.  */
 
@@ -574,18 +579,35 @@ print_address_symbolic (addr, stream, do_demangle, leadin)
   if (addr != name_location)
     fprintf_filtered (stream, "+%u", (unsigned int)(addr - name_location));
 
-  /* Append source filename and line number if desired.  */
-  if (symbol && print_symbol_filename)
+  /* Append source filename and line number if desired.  Give specific
+     line # of this addr, if we have it; else line # of the nearest symbol.  */
+  if (print_symbol_filename)
     {
       struct symtab_and_line sal;
 
       sal = find_pc_line (addr, 0);
       if (sal.symtab)
        fprintf_filtered (stream, " at %s:%d", sal.symtab->filename, sal.line);
+      else if (symtab && symbol && symbol->line)
+       fprintf_filtered (stream, " at %s:%d", symtab->filename, symbol->line);
+      else if (symtab)
+       fprintf_filtered (stream, " in %s", symtab->filename);
     }
   fputs_filtered (">", stream);
 }
 
+/* Print address ADDR on STREAM.  */
+void
+print_address_numeric (addr, stream)
+     CORE_ADDR addr;
+     GDB_FILE *stream;
+{
+  /* This assumes a CORE_ADDR can fit in a LONGEST.  Probably a safe
+     assumption.  We pass use_local but I'm not completely sure whether
+     that is correct.  When (if ever) should we *not* use_local?  */
+  print_longest (stream, 'x', 1, (unsigned LONGEST) addr);
+}
+
 /* Print address ADDR symbolically on STREAM.
    First print it as a number.  Then perhaps print
    <SYMBOL + OFFSET> after the number.  */
@@ -593,13 +615,9 @@ print_address_symbolic (addr, stream, do_demangle, leadin)
 void
 print_address (addr, stream)
      CORE_ADDR addr;
-     FILE *stream;
+     GDB_FILE *stream;
 {
-#ifdef ADDR_BITS_REMOVE
-  fprintf_filtered (stream, local_hex_format(), ADDR_BITS_REMOVE(addr));
-#else
-  fprintf_filtered (stream, local_hex_format(), addr);
-#endif
+  print_address_numeric (addr, stream);
   print_address_symbolic (addr, stream, asm_demangle, " ");
 }
 
@@ -611,22 +629,35 @@ print_address (addr, stream)
 void
 print_address_demangle (addr, stream, do_demangle)
      CORE_ADDR addr;
-     FILE *stream;
+     GDB_FILE *stream;
      int do_demangle;
 {
-  if (addr == 0) {
-    fprintf_filtered (stream, "0");
-  } else if (addressprint) {
-    fprintf_filtered (stream, local_hex_format(), addr);
-    print_address_symbolic (addr, stream, do_demangle, " ");
-  } else {
-    print_address_symbolic (addr, stream, do_demangle, "");
-  }
+  if (addr == 0)
+    {
+      fprintf_filtered (stream, "0");
+    }
+  else if (addressprint)
+    {
+      print_address_numeric (addr, stream);
+      print_address_symbolic (addr, stream, do_demangle, " ");
+    }
+  else
+    {
+      print_address_symbolic (addr, stream, do_demangle, "");
+    }
 }
 \f
 
+/* These are the types that $__ will get after an examine command of one
+   of these sizes.  */
+
+static struct type *examine_b_type;
+static struct type *examine_h_type;
+static struct type *examine_w_type;
+static struct type *examine_g_type;
+
 /* Examine data at address ADDR in format FMT.
-   Fetch it from memory and print on stdout.  */
+   Fetch it from memory and print on gdb_stdout.  */
 
 static void
 do_examine (fmt, addr)
@@ -636,7 +667,7 @@ do_examine (fmt, addr)
   register char format = 0;
   register char size;
   register int count = 1;
-  struct type *val_type;
+  struct type *val_type = NULL;
   register int i;
   register int maxelts;
 
@@ -651,17 +682,13 @@ do_examine (fmt, addr)
     size = 'b';
 
   if (size == 'b')
-    val_type = builtin_type_char;
+    val_type = examine_b_type;
   else if (size == 'h')
-    val_type = builtin_type_short;
+    val_type = examine_h_type;
   else if (size == 'w')
-    val_type = builtin_type_long;
+    val_type = examine_w_type;
   else if (size == 'g')
-#ifndef CC_HAS_LONG_LONG
-    val_type = builtin_type_double;
-#else
-    val_type = builtin_type_long_long;
-#endif
+    val_type = examine_g_type;
 
   maxelts = 8;
   if (size == 'w')
@@ -676,7 +703,7 @@ do_examine (fmt, addr)
 
   while (count > 0)
     {
-      print_address (next_address, stdout);
+      print_address (next_address, gdb_stdout);
       printf_filtered (":");
       for (i = maxelts;
           i > 0 && count > 0;
@@ -690,7 +717,7 @@ do_examine (fmt, addr)
          print_formatted (last_examine_value, format, size);
        }
       printf_filtered ("\n");
-      fflush (stdout);
+      gdb_flush (gdb_stdout);
     }
 }
 \f
@@ -781,14 +808,14 @@ print_command_1 (exp, inspect, voidprint)
       int histindex = record_latest_value (val);
 
       if (inspect)
-       printf ("\031(gdb-makebuffer \"%s\"  %d '(\"", exp, histindex);
+       printf_unfiltered ("\031(gdb-makebuffer \"%s\"  %d '(\"", exp, histindex);
       else
        if (histindex >= 0) printf_filtered ("$%d = ", histindex);
 
       print_formatted (val, format, fmt.size);
       printf_filtered ("\n");
       if (inspect)
-       printf("\") )\030");
+       printf_unfiltered("\") )\030");
     }
 
   if (cleanup)
@@ -892,21 +919,33 @@ address_info (exp, from_tty)
     {
       if (is_a_field_of_this)
        {
-         printf ("Symbol \"%s\" is a field of the local class variable `this'\n", exp);
+         printf_filtered ("Symbol \"");
+         fprintf_symbol_filtered (gdb_stdout, exp,
+                                  current_language->la_language, DMGL_ANSI);
+         printf_filtered ("\" is a field of the local class variable `this'\n");
          return;
        }
 
       msymbol = lookup_minimal_symbol (exp, (struct objfile *) NULL);
 
       if (msymbol != NULL)
-       printf ("Symbol \"%s\" is at %s in a file compiled without debugging.\n",
-               exp, local_hex_string(SYMBOL_VALUE_ADDRESS (msymbol)));
+       {
+         printf_filtered ("Symbol \"");
+         fprintf_symbol_filtered (gdb_stdout, exp,
+                                  current_language->la_language, DMGL_ANSI);
+         printf_filtered ("\" is at ");
+         print_address_numeric (SYMBOL_VALUE_ADDRESS (msymbol), gdb_stdout);
+         printf_filtered (" in a file compiled without debugging.\n");
+       }
       else
        error ("No symbol \"%s\" in current context.", exp);
       return;
     }
 
-  printf ("Symbol \"%s\" is ", SYMBOL_NAME (sym));
+  printf_filtered ("Symbol \"");
+  fprintf_symbol_filtered (gdb_stdout, SYMBOL_NAME (sym),
+                          current_language->la_language, DMGL_ANSI);
+  printf_filtered ("\" is ", SYMBOL_NAME (sym));
   val = SYMBOL_VALUE (sym);
   basereg = SYMBOL_BASEREG (sym);
 
@@ -914,76 +953,65 @@ address_info (exp, from_tty)
     {
     case LOC_CONST:
     case LOC_CONST_BYTES:
-      printf ("constant");
+      printf_filtered ("constant");
       break;
 
     case LOC_LABEL:
-      printf ("a label at address %s", local_hex_string(SYMBOL_VALUE_ADDRESS (sym)));
+      printf_filtered ("a label at address ");
+      print_address_numeric (SYMBOL_VALUE_ADDRESS (sym), gdb_stdout);
       break;
 
     case LOC_REGISTER:
-      printf ("a variable in register %s", reg_names[val]);
+      printf_filtered ("a variable in register %s", reg_names[val]);
       break;
 
     case LOC_STATIC:
-      printf ("static storage at address %s", local_hex_string(SYMBOL_VALUE_ADDRESS (sym)));
+      printf_filtered ("static storage at address ");
+      print_address_numeric (SYMBOL_VALUE_ADDRESS (sym), gdb_stdout);
       break;
 
     case LOC_REGPARM:
-      printf ("an argument in register %s", reg_names[val]);
+      printf_filtered ("an argument in register %s", reg_names[val]);
+      break;
+
+    case LOC_REGPARM_ADDR:
+      printf_filtered ("address of an argument in register %s", reg_names[val]);
       break;
 
-   case LOC_REGPARM_ADDR:
-     printf ("address of an argument in register %s", reg_names[val]);
-     break;
-      
     case LOC_ARG:
-      if (SYMBOL_BASEREG_VALID (sym))
-       {
-         printf ("an argument at offset %ld from register %s",
-                 val, reg_names[basereg]);
-       }
-      else
-       {
-         printf ("an argument at offset %ld", val);
-       }
+      printf_filtered ("an argument at offset %ld", val);
       break;
 
     case LOC_LOCAL_ARG:
-      if (SYMBOL_BASEREG_VALID (sym))
-       {
-         printf ("an argument at offset %ld from register %s",
-                 val, reg_names[basereg]);
-       }
-      else
-       {
-         printf ("an argument at frame offset %ld", val);
-       }
+      printf_filtered ("an argument at frame offset %ld", val);
       break;
 
     case LOC_LOCAL:
-      if (SYMBOL_BASEREG_VALID (sym))
-       {
-         printf ("a local variable at offset %ld from register %s",
-                 val, reg_names[basereg]);
-       }
-      else
-       {
-         printf ("a local variable at frame offset %ld", val);
-       }
+      printf_filtered ("a local variable at frame offset %ld", val);
       break;
 
     case LOC_REF_ARG:
-      printf ("a reference argument at offset %ld", val);
+      printf_filtered ("a reference argument at offset %ld", val);
+      break;
+
+    case LOC_BASEREG:
+      printf_filtered ("a variable at offset %ld from register %s",
+             val, reg_names[basereg]);
+      break;
+
+    case LOC_BASEREG_ARG:
+      printf_filtered ("an argument at offset %ld from register %s",
+             val, reg_names[basereg]);
       break;
 
     case LOC_TYPEDEF:
-      printf ("a typedef");
+      printf_filtered ("a typedef");
       break;
 
     case LOC_BLOCK:
-      printf ("a function at address %s",
-             local_hex_string(BLOCK_START (SYMBOL_BLOCK_VALUE (sym))));
+      printf_filtered ("a function at address ");
+      print_address_numeric (BLOCK_START (SYMBOL_BLOCK_VALUE (sym)),
+                            gdb_stdout);
       break;
 
     case LOC_OPTIMIZED_OUT:
@@ -991,10 +1019,10 @@ address_info (exp, from_tty)
       break;
       
     default:
-      printf ("of unknown (botched) type");
+      printf_filtered ("of unknown (botched) type");
       break;
     }
-  printf (".\n");
+  printf_filtered (".\n");
 }
 \f
 static void
@@ -1245,7 +1273,7 @@ do_one_display (d)
       if (d->format.format != 'i' && d->format.format != 's')
        printf_filtered ("%c", d->format.size);
       printf_filtered (" ");
-      print_expression (d->exp, stdout);
+      print_expression (d->exp, gdb_stdout);
       if (d->format.count != 1)
        printf_filtered ("\n");
       else
@@ -1261,14 +1289,14 @@ do_one_display (d)
     {
       if (d->format.format)
        printf_filtered ("/%c ", d->format.format);
-      print_expression (d->exp, stdout);
+      print_expression (d->exp, gdb_stdout);
       printf_filtered (" = ");
       print_formatted (evaluate_expression (d->exp),
                       d->format.format, d->format.size);
       printf_filtered ("\n");
     }
 
-  fflush (stdout);
+  gdb_flush (gdb_stdout);
   current_display_number = -1;
 }
 
@@ -1299,7 +1327,7 @@ disable_display (num)
        d->status = disabled;
        return;
       }
-  printf ("No display number %d.\n", num);
+  printf_unfiltered ("No display number %d.\n", num);
 }
   
 void
@@ -1308,7 +1336,7 @@ disable_current_display ()
   if (current_display_number >= 0)
     {
       disable_display (current_display_number);
-      fprintf (stderr, "Disabling display %d to avoid infinite recursion.\n",
+      fprintf_unfiltered (gdb_stderr, "Disabling display %d to avoid infinite recursion.\n",
               current_display_number);
     }
   current_display_number = -1;
@@ -1322,7 +1350,7 @@ display_info (ignore, from_tty)
   register struct display *d;
 
   if (!display_chain)
-    printf ("There are no auto-display expressions now.\n");
+    printf_unfiltered ("There are no auto-display expressions now.\n");
   else
       printf_filtered ("Auto-display expressions now in effect:\n\
 Num Enb Expression\n");
@@ -1335,11 +1363,11 @@ Num Enb Expression\n");
                d->format.format);
       else if (d->format.format)
        printf_filtered ("/%c ", d->format.format);
-      print_expression (d->exp, stdout);
+      print_expression (d->exp, gdb_stdout);
       if (d->block && !contained_in (get_selected_block (), d->block))
        printf_filtered (" (cannot be evaluated in the current context)");
       printf_filtered ("\n");
-      fflush (stdout);
+      gdb_flush (gdb_stdout);
     }
 }
 
@@ -1375,7 +1403,7 @@ enable_display (args, from_tty)
              d->status = enabled;
              goto win;
            }
-       printf ("No display number %d.\n", num);
+       printf_unfiltered ("No display number %d.\n", num);
       win:
        p = p1;
        while (*p == ' ' || *p == '\t')
@@ -1423,7 +1451,7 @@ void
 print_variable_value (var, frame, stream)
      struct symbol *var;
      FRAME frame;
-     FILE *stream;
+     GDB_FILE *stream;
 {
   value val = read_var_value (var, frame);
   value_print (val, stream, 0, Val_pretty_default);
@@ -1442,9 +1470,9 @@ print_frame_args (func, fi, num, stream)
      struct symbol *func;
      struct frame_info *fi;
      int num;
-     FILE *stream;
+     GDB_FILE *stream;
 {
-  struct block *b;
+  struct block *b = NULL;
   int nsyms = 0;
   int first = 1;
   register int i;
@@ -1500,6 +1528,7 @@ print_frame_args (func, fi, num, stream)
       case LOC_REGPARM:
       case LOC_REGPARM_ADDR:
       case LOC_LOCAL_ARG:
+      case LOC_BASEREG_ARG:
        break;
 
       /* Other types of symbols we just skip over.  */
@@ -1515,16 +1544,50 @@ print_frame_args (func, fi, num, stream)
         and it is passed as a double and converted to float by
         the prologue (in the latter case the type of the LOC_ARG
         symbol is double and the type of the LOC_LOCAL symbol is
-        float).  There are also LOC_ARG/LOC_REGISTER pairs which
-        are not combined in symbol-reading.  */
+        float).  */
       /* But if the parameter name is null, don't try it.
         Null parameter names occur on the RS/6000, for traceback tables.
         FIXME, should we even print them?  */
 
       if (*SYMBOL_NAME (sym))
-        sym = lookup_symbol
-         (SYMBOL_NAME (sym),
-          b, VAR_NAMESPACE, (int *)NULL, (struct symtab **)NULL);
+       {
+         struct symbol *nsym;
+         nsym = lookup_symbol
+           (SYMBOL_NAME (sym),
+            b, VAR_NAMESPACE, (int *)NULL, (struct symtab **)NULL);
+         if (SYMBOL_CLASS (nsym) == LOC_REGISTER)
+           {
+             /* There is a LOC_ARG/LOC_REGISTER pair.  This means that
+                it was passed on the stack and loaded into a register,
+                or passed in a register and stored in a stack slot.
+                GDB 3.x used the LOC_ARG; GDB 4.0-4.11 used the LOC_REGISTER.
+
+                Reasons for using the LOC_ARG:
+                (1) because find_saved_registers may be slow for remote
+                debugging,
+                (2) because registers are often re-used and stack slots
+                rarely (never?) are.  Therefore using the stack slot is
+                much less likely to print garbage.
+
+                Reasons why we might want to use the LOC_REGISTER:
+                (1) So that the backtrace prints the same value as
+                "print foo".  I see no compelling reason why this needs
+                to be the case; having the backtrace print the value which
+                was passed in, and "print foo" print the value as modified
+                within the called function, makes perfect sense to me.
+
+                Additional note:  It might be nice if "info args" displayed
+                both values.
+                One more note:  There is a case with sparc sturcture passing
+                where we need to use the LOC_REGISTER, but this is dealt with
+                by creating a single LOC_REGPARM in symbol reading.  */
+
+             /* Leave sym (the LOC_ARG) alone.  */
+             ;
+           }
+         else
+           sym = nsym;
+       }
 
       /* Print the current arg.  */
       if (! first)
@@ -1575,7 +1638,7 @@ print_frame_nameless_args (fi, start, num, first, stream)
      long start;
      int num;
      int first;
-     FILE *stream;
+     GDB_FILE *stream;
 {
   int i;
   CORE_ADDR argsaddr;
@@ -1621,11 +1684,14 @@ printf_command (arg, from_tty)
   register char *s = arg;
   char *string;
   value *val_args;
+  char *substrings;
+  char *current_substring;
   int nargs = 0;
   int allocated_args = 20;
-  char *arg_bytes;
+  struct cleanup *old_cleanups;
 
   val_args = (value *) xmalloc (allocated_args * sizeof (value));
+  old_cleanups = make_cleanup (free_current_contents, &val_args);
 
   if (s == 0)
     error_no_arg ("format-control string and values to print");
@@ -1641,6 +1707,7 @@ printf_command (arg, from_tty)
      processing some kinds of escape sequence.  */
 
   f = string = (char *) alloca (strlen (s) + 1);
+
   while (*s != '"')
     {
       int c = *s++;
@@ -1648,7 +1715,6 @@ printf_command (arg, from_tty)
        {
        case '\0':
          error ("Bad format string, non-terminated '\"'.");
-         /* doesn't return */
 
        case '\\':
          switch (c = *s++)
@@ -1690,21 +1756,27 @@ printf_command (arg, from_tty)
   if (*s == ',') s++;
   while (*s == ' ' || *s == '\t') s++;
 
+  /* Need extra space for the '\0's.  Doubling the size is sufficient.  */
+  substrings = alloca (strlen (string) * 2);
+  current_substring = substrings;
+
   {
     /* Now scan the string for %-specs and see what kinds of args they want.
-       argclass[I] classifies the %-specs so we can give vprintf something
+       argclass[I] classifies the %-specs so we can give vprintf_unfiltered something
        of the right size.  */
-    enum argclass {int_arg, string_arg, double_arg, long_long_arg};
+
+    enum argclass {no_arg, int_arg, string_arg, double_arg, long_long_arg};
     enum argclass *argclass;
+    enum argclass this_argclass;
+    char *last_arg;
     int nargs_wanted;
-    int argindex;
     int lcount;
     int i;
+
     argclass = (enum argclass *) alloca (strlen (s) * sizeof *argclass);
     nargs_wanted = 0;
     f = string;
+    last_arg = string;
     while (*f)
       if (*f++ == '%')
        {
@@ -1715,20 +1787,49 @@ printf_command (arg, from_tty)
                lcount++;
              f++;
            }
-         if (*f == 's')
-           argclass[nargs_wanted++] = string_arg;
-         else if (*f == 'e' || *f == 'f' || *f == 'g')
-           argclass[nargs_wanted++] = double_arg;
-         else if (lcount > 1)
-           argclass[nargs_wanted++] = long_long_arg;
-         else if (*f != '%')
-           argclass[nargs_wanted++] = int_arg;
+         switch (*f)
+           {
+           case 's':
+             this_argclass = string_arg;
+             break;
+
+           case 'e':
+           case 'f':
+           case 'g':
+             this_argclass = double_arg;
+             break;
+
+           case '*':
+             error ("`*' not supported for precision or width in printf");
+
+           case 'n':
+             error ("Format specifier `n' not supported in printf");
+
+           case '%':
+             this_argclass = no_arg;
+             break;
+
+           default:
+             if (lcount > 1)
+               this_argclass = long_long_arg;
+             else
+               this_argclass = int_arg;
+             break;
+           }
          f++;
+         if (this_argclass != no_arg)
+           {
+             strncpy (current_substring, last_arg, f - last_arg);
+             current_substring += f - last_arg;
+             *current_substring++ = '\0';
+             last_arg = f;
+             argclass[nargs_wanted++] = this_argclass;
+           }
        }
+
     /* Now, parse all arguments and evaluate them.
        Store the VALUEs in VAL_ARGS.  */
+
     while (*s != '\0')
       {
        char *s1;
@@ -1757,117 +1858,88 @@ printf_command (arg, from_tty)
  
     if (nargs != nargs_wanted)
       error ("Wrong number of arguments for specified format-string");
-    /* Now lay out an argument-list containing the arguments
-       as doubles, integers and C pointers.  */
-    arg_bytes = (char *) alloca (sizeof (double) * nargs);
-    argindex = 0;
+
+    /* FIXME: We should be using vprintf_filtered, but as long as it
+       has an arbitrary limit that is unacceptable.  Correct fix is
+       for vprintf_filtered to scan down the format string so it knows
+       how big a buffer it needs (perhaps by putting a vasprintf (see
+       GNU C library) in libiberty).
+
+       But for now, just force out any pending output, so at least the output
+       appears in the correct order.  */
+    wrap_here ((char *)NULL);
+
+    /* Now actually print them.  */
+    current_substring = substrings;
     for (i = 0; i < nargs; i++)
       {
-       if (argclass[i] == string_arg)
-         {
-           char *str;
-           CORE_ADDR tem;
-           int j;
-           tem = value_as_pointer (val_args[i]);
-           /* This is a %s argument.  Find the length of the string.  */
-           for (j = 0; ; j++)
-             {
-               char c;
-               QUIT;
-               read_memory (tem + j, &c, 1);
-               if (c == 0)
-                 break;
-             }
-           /* Copy the string contents into a string inside GDB.  */
-           str = (char *) alloca (j + 1);
-           read_memory (tem, str, j);
-           str[j] = 0;
-           /* Pass address of internal copy as the arg to vprintf.  */
-           *((int *) &arg_bytes[argindex]) = (int) str;
-           argindex += sizeof (int);
-         }
-       else if (VALUE_TYPE (val_args[i])->code == TYPE_CODE_FLT)
+       switch (argclass[i])
          {
-           *((double *) &arg_bytes[argindex]) = value_as_double (val_args[i]);
-           argindex += sizeof (double);
-         }
-       else
-#ifdef CC_HAS_LONG_LONG
-         if (argclass[i] == long_long_arg)
+         case string_arg:
            {
-             *(LONGEST *) &arg_bytes[argindex] = value_as_long (val_args[i]);
-             argindex += sizeof (LONGEST);
+             char *str;
+             CORE_ADDR tem;
+             int j;
+             tem = value_as_pointer (val_args[i]);
+
+             /* This is a %s argument.  Find the length of the string.  */
+             for (j = 0; ; j++)
+               {
+                 char c;
+                 QUIT;
+                 read_memory (tem + j, &c, 1);
+                 if (c == 0)
+                   break;
+               }
+
+             /* Copy the string contents into a string inside GDB.  */
+             str = (char *) alloca (j + 1);
+             read_memory (tem, str, j);
+             str[j] = 0;
+
+             /* Don't use printf_filtered because of arbitrary limit.  */
+             printf_unfiltered (current_substring, str);
            }
-         else
+           break;
+         case double_arg:
+           {
+             double val = value_as_double (val_args[i]);
+             /* Don't use printf_filtered because of arbitrary limit.  */
+             printf_unfiltered (current_substring, val);
+             break;
+           }
+         case long_long_arg:
+#if defined (CC_HAS_LONG_LONG) && defined (PRINTF_HAS_LONG_LONG)
+           {
+             long long val = value_as_long (val_args[i]);
+             /* Don't use printf_filtered because of arbitrary limit.  */
+             printf_unfiltered (current_substring, val);
+             break;
+           }
+#else
+           error ("long long not supported in printf");
 #endif
+         case int_arg:
            {
-             *((long *) &arg_bytes[argindex]) = value_as_long (val_args[i]);
-             argindex += sizeof (long);
+             /* FIXME: there should be separate int_arg and long_arg.  */
+             long val = value_as_long (val_args[i]);
+             /* Don't use printf_filtered because of arbitrary limit.  */
+             printf_unfiltered (current_substring, val);
+             break;
            }
+         default:
+           error ("internal error in printf_command");
+         }
+       /* Skip to the next substring.  */
+       current_substring += strlen (current_substring) + 1;
       }
+    /* Print the portion of the format string after the last argument.  */
+    /* It would be OK to use printf_filtered here.  */
+    printf (last_arg);
   }
-
-  /* There is not a standard way to make a va_list, so we need
-     to do various things for different systems.  */
-#if defined (__INT_VARARGS_H)
-  /* This is defined by an 88k using gcc1.  Do other machines use it?  */
-  {
-    va_list list;
-
-    list.__va_arg = 0;
-    list.__va_stk = (int *) arg_bytes;
-    list.__va_reg = (int *) arg_bytes;
-    vprintf (string, list);
-  }
-#else /* No __INT_VARARGS_H.  */
-#ifdef VPRINTF
-  VPRINTF (string, arg_bytes);
-#else /* No VPRINTF.  */
-  vprintf (string, (PTR) arg_bytes);
-#endif /* No VPRINTF.  */
-#endif /* No __INT_VARARGS_H.  */
+  do_cleanups (old_cleanups);
 }
 \f
-/* Helper function for asdump_command.  Finds the bounds of a function
-   for a specified section of text.  PC is an address within the
-   function which you want bounds for; *LOW and *HIGH are set to the
-   beginning (inclusive) and end (exclusive) of the function.  This
-   function returns 1 on success and 0 on failure.  */
-
-static int
-containing_function_bounds (pc, low, high)
-     CORE_ADDR pc, *low, *high;
-{
-  CORE_ADDR scan;
-  CORE_ADDR limit;
-  struct obj_section *sec;
-
-  if (!find_pc_partial_function (pc, 0, low))
-    return 0;
-
-  sec = find_pc_section (pc);
-  if (sec == NULL)
-    return 0;
-  limit = sec->endaddr;
-  
-  scan = *low;
-  while (scan < limit)
-    {
-      ++scan;
-      if (!find_pc_partial_function (scan, 0, high))
-       return 0;
-      if (*low != *high)
-       return 1;
-    }
-  *high = limit;
-  return 1;
-}
-
 /* Dump a specified section of assembly code.  With no command line
    arguments, this command will dump the assembly code for the
    function surrounding the pc value in the selected frame.  With one
@@ -1882,24 +1954,26 @@ disassemble_command (arg, from_tty)
      int from_tty;
 {
   CORE_ADDR low, high;
+  char *name;
   CORE_ADDR pc;
   char *space_index;
 
+  name = NULL;
   if (!arg)
     {
       if (!selected_frame)
        error ("No frame selected.\n");
 
       pc = get_frame_pc (selected_frame);
-      if (!containing_function_bounds (pc, &low, &high))
-       error ("No function contains pc specified by selected frame.\n");
+      if (find_pc_partial_function (pc, &name, &low, &high) == 0)
+       error ("No function contains program counter for selected frame.\n");
     }
   else if (!(space_index = (char *) strchr (arg, ' ')))
     {
       /* One argument.  */
       pc = parse_and_eval_address (arg);
-      if (!containing_function_bounds (pc, &low, &high))
-       error ("No function contains specified pc.\n");
+      if (find_pc_partial_function (pc, &name, &low, &high) == 0)
+       error ("No function contains specified address.\n");
     }
   else
     {
@@ -1910,29 +1984,32 @@ disassemble_command (arg, from_tty)
     }
 
   printf_filtered ("Dump of assembler code ");
-  if (!space_index)
+  if (name != NULL)
     {
-      char *name;
-      find_pc_partial_function (pc, &name, 0);
       printf_filtered ("for function %s:\n", name);
     }
   else
     {
-      printf_filtered ("from %s ", local_hex_string(low));
-      printf_filtered ("to %s:\n", local_hex_string(high));
+      printf_filtered ("from ");
+      print_address_numeric (low, gdb_stdout);
+      printf_filtered (" to ");
+      print_address_numeric (high, gdb_stdout);
+      printf_filtered (":\n");
     }
 
   /* Dump the specified range.  */
   for (pc = low; pc < high; )
     {
       QUIT;
-      print_address (pc, stdout);
+      print_address (pc, gdb_stdout);
       printf_filtered (":\t");
-      pc += print_insn (pc, stdout);
+      /* We often wrap here if there are long symbolic names.  */
+      wrap_here ("    ");
+      pc += print_insn (pc, gdb_stdout);
       printf_filtered ("\n");
     }
   printf_filtered ("End of assembler dump.\n");
-  fflush (stdout);
+  gdb_flush (gdb_stdout);
 }
 
 \f
@@ -2080,4 +2157,16 @@ environment, the value is printed in its own window.");
        "Set printing of source filename and line number with <symbol>.",
                   &setprintlist),
       &showprintlist);
+
+  add_show_from_set (
+      add_set_cmd ("fast-symbolic-addr", no_class, var_boolean,
+                  (char *)&fast_symbolic_addr,
+       "Set fast printing of symbolic addresses (using minimal symbols).",
+                  &setprintlist),
+      &showprintlist);
+
+  examine_b_type = init_type (TYPE_CODE_INT, 1, 0, NULL, NULL);
+  examine_h_type = init_type (TYPE_CODE_INT, 2, 0, NULL, NULL);
+  examine_w_type = init_type (TYPE_CODE_INT, 4, 0, NULL, NULL);
+  examine_g_type = init_type (TYPE_CODE_INT, 8, 0, NULL, NULL);
 }
This page took 0.036631 seconds and 4 git commands to generate.