* Makefile.in (c_lang.o, jv_lang.o, language.o): Add $(demangle_h).
[deliverable/binutils-gdb.git] / gdb / c-lang.c
index 2211acb2e08ead7290affecfbc7c24ce4bc8bd9e..e492b9a205e3295139d4f6afda3f4a9b94f2e56c 100644 (file)
@@ -1,5 +1,6 @@
 /* C language support routines for GDB, the GNU debugger.
-   Copyright 1992, 1993, 1994, 2000 Free Software Foundation, Inc.
+   Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2002
+   Free Software Foundation, Inc.
 
    This file is part of GDB.
 
 #include "language.h"
 #include "c-lang.h"
 #include "valprint.h"
+#include "macroscope.h"
+#include "gdb_assert.h"
+#include "charset.h"
+#include "gdb_string.h"
+#include "demangle.h"
 
-extern void _initialize_c_language PARAMS ((void));
+extern void _initialize_c_language (void);
 static void c_emit_char (int c, struct ui_file * stream, int quoter);
 
 /* Print the character C on STREAM as part of the contents of a literal
@@ -35,57 +41,36 @@ static void c_emit_char (int c, struct ui_file * stream, int quoter);
    characters and strings is language specific. */
 
 static void
-c_emit_char (c, stream, quoter)
-     register int c;
-     struct ui_file *stream;
-     int quoter;
+c_emit_char (register int c, struct ui_file *stream, int quoter)
 {
+  const char *escape;
+  int host_char;
+
   c &= 0xFF;                   /* Avoid sign bit follies */
 
-  if (PRINT_LITERAL_FORM (c))
+  escape = c_target_char_has_backslash_escape (c);
+  if (escape)
     {
-      if (c == '\\' || c == quoter)
-       {
-         fputs_filtered ("\\", stream);
-       }
-      fprintf_filtered (stream, "%c", c);
+      if (quoter == '"' && strcmp (escape, "0") == 0)
+       /* Print nulls embedded in double quoted strings as \000 to
+          prevent ambiguity.  */
+       fprintf_filtered (stream, "\\000");
+      else
+       fprintf_filtered (stream, "\\%s", escape);
     }
-  else
+  else if (target_char_to_host (c, &host_char)
+           && host_char_print_literally (host_char))
     {
-      switch (c)
-       {
-       case '\n':
-         fputs_filtered ("\\n", stream);
-         break;
-       case '\b':
-         fputs_filtered ("\\b", stream);
-         break;
-       case '\t':
-         fputs_filtered ("\\t", stream);
-         break;
-       case '\f':
-         fputs_filtered ("\\f", stream);
-         break;
-       case '\r':
-         fputs_filtered ("\\r", stream);
-         break;
-       case '\033':
-         fputs_filtered ("\\e", stream);
-         break;
-       case '\007':
-         fputs_filtered ("\\a", stream);
-         break;
-       default:
-         fprintf_filtered (stream, "\\%.3o", (unsigned int) c);
-         break;
-       }
+      if (host_char == '\\' || host_char == quoter)
+        fputs_filtered ("\\", stream);
+      fprintf_filtered (stream, "%c", host_char);
     }
+  else
+    fprintf_filtered (stream, "\\%.3o", (unsigned int) c);
 }
 
 void
-c_printchar (c, stream)
-     int c;
-     struct ui_file *stream;
+c_printchar (int c, struct ui_file *stream)
 {
   fputc_filtered ('\'', stream);
   LA_EMIT_CHAR (c, stream, '\'');
@@ -99,12 +84,8 @@ c_printchar (c, stream)
    printing LENGTH characters, or if FORCE_ELLIPSES.  */
 
 void
-c_printstr (stream, string, length, width, force_ellipses)
-     struct ui_file *stream;
-     char *string;
-     unsigned int length;
-     int width;
-     int force_ellipses;
+c_printstr (struct ui_file *stream, char *string, unsigned int length,
+           int width, int force_ellipses)
 {
   register unsigned int i;
   unsigned int things_printed = 0;
@@ -117,7 +98,8 @@ c_printstr (stream, string, length, width, force_ellipses)
      style.  */
   if (!force_ellipses
       && length > 0
-  && extract_unsigned_integer (string + (length - 1) * width, width) == '\0')
+      && (extract_unsigned_integer (string + (length - 1) * width, width)
+          == '\0'))
     length--;
 
   if (length == 0)
@@ -223,9 +205,7 @@ c_printstr (stream, string, length, width, force_ellipses)
    debugging information supplied by the compiler.  fnf@cygnus.com */
 
 struct type *
-c_create_fundamental_type (objfile, typeid)
-     struct objfile *objfile;
-     int typeid;
+c_create_fundamental_type (struct objfile *objfile, int typeid)
 {
   register struct type *type = NULL;
 
@@ -250,13 +230,11 @@ c_create_fundamental_type (objfile, typeid)
       type = init_type (TYPE_CODE_BOOL,
                        TARGET_CHAR_BIT / TARGET_CHAR_BIT,
                        0, "bool", objfile);
-
       break;
     case FT_CHAR:
       type = init_type (TYPE_CODE_INT,
                        TARGET_CHAR_BIT / TARGET_CHAR_BIT,
-                       0, "char", objfile);
-      TYPE_FLAGS (type) |= TYPE_FLAG_NOSIGN;
+                       TYPE_FLAG_NOSIGN, "char", objfile);
       break;
     case FT_SIGNED_CHAR:
       type = init_type (TYPE_CODE_INT,
@@ -343,17 +321,161 @@ c_create_fundamental_type (objfile, typeid)
                        TARGET_LONG_DOUBLE_BIT / TARGET_CHAR_BIT,
                        0, "long double", objfile);
       break;
+    case FT_COMPLEX:
+      type = init_type (TYPE_CODE_FLT,
+                       2 * TARGET_FLOAT_BIT / TARGET_CHAR_BIT,
+                       0, "complex float", objfile);
+      TYPE_TARGET_TYPE (type)
+       = init_type (TYPE_CODE_FLT, TARGET_FLOAT_BIT / TARGET_CHAR_BIT,
+                    0, "float", objfile);
+      break;
+    case FT_DBL_PREC_COMPLEX:
+      type = init_type (TYPE_CODE_FLT,
+                       2 * TARGET_DOUBLE_BIT / TARGET_CHAR_BIT,
+                       0, "complex double", objfile);
+      TYPE_TARGET_TYPE (type)
+       = init_type (TYPE_CODE_FLT, TARGET_DOUBLE_BIT / TARGET_CHAR_BIT,
+                    0, "double", objfile);
+      break;
+    case FT_EXT_PREC_COMPLEX:
+      type = init_type (TYPE_CODE_FLT,
+                       2 * TARGET_LONG_DOUBLE_BIT / TARGET_CHAR_BIT,
+                       0, "complex long double", objfile);
+      TYPE_TARGET_TYPE (type)
+       = init_type (TYPE_CODE_FLT, TARGET_LONG_DOUBLE_BIT / TARGET_CHAR_BIT,
+                    0, "long double", objfile);
+      break;
     case FT_TEMPLATE_ARG:
       type = init_type (TYPE_CODE_TEMPLATE_ARG,
                        0,
                        0, "<template arg>", objfile);
-
       break;
     }
   return (type);
 }
 \f
+/* Preprocessing and parsing C and C++ expressions.  */
+
+
+/* When we find that lexptr (the global var defined in parse.c) is
+   pointing at a macro invocation, we expand the invocation, and call
+   scan_macro_expansion to save the old lexptr here and point lexptr
+   into the expanded text.  When we reach the end of that, we call
+   end_macro_expansion to pop back to the value we saved here.  The
+   macro expansion code promises to return only fully-expanded text,
+   so we don't need to "push" more than one level.
+
+   This is disgusting, of course.  It would be cleaner to do all macro
+   expansion beforehand, and then hand that to lexptr.  But we don't
+   really know where the expression ends.  Remember, in a command like
+
+     (gdb) break *ADDRESS if CONDITION
+
+   we evaluate ADDRESS in the scope of the current frame, but we
+   evaluate CONDITION in the scope of the breakpoint's location.  So
+   it's simply wrong to try to macro-expand the whole thing at once.  */
+static char *macro_original_text;
+static char *macro_expanded_text;
+
+
+void
+scan_macro_expansion (char *expansion)
+{
+  /* We'd better not be trying to push the stack twice.  */
+  gdb_assert (! macro_original_text);
+  gdb_assert (! macro_expanded_text);
+
+  /* Save the old lexptr value, so we can return to it when we're done
+     parsing the expanded text.  */
+  macro_original_text = lexptr;
+  lexptr = expansion;
+
+  /* Save the expanded text, so we can free it when we're finished.  */
+  macro_expanded_text = expansion;
+}
+
+
+int
+scanning_macro_expansion (void)
+{
+  return macro_original_text != 0;
+}
 
+
+void 
+finished_macro_expansion (void)
+{
+  /* There'd better be something to pop back to, and we better have
+     saved a pointer to the start of the expanded text.  */
+  gdb_assert (macro_original_text);
+  gdb_assert (macro_expanded_text);
+
+  /* Pop back to the original text.  */
+  lexptr = macro_original_text;
+  macro_original_text = 0;
+
+  /* Free the expanded text.  */
+  xfree (macro_expanded_text);
+  macro_expanded_text = 0;
+}
+
+
+static void
+scan_macro_cleanup (void *dummy)
+{
+  if (macro_original_text)
+    finished_macro_expansion ();
+}
+
+
+/* We set these global variables before calling c_parse, to tell it
+   how it to find macro definitions for the expression at hand.  */
+macro_lookup_ftype *expression_macro_lookup_func;
+void *expression_macro_lookup_baton;
+
+
+static struct macro_definition *
+null_macro_lookup (const char *name, void *baton)
+{
+  return 0;
+}
+
+
+static int
+c_preprocess_and_parse (void)
+{
+  /* Set up a lookup function for the macro expander.  */
+  struct macro_scope *scope = 0;
+  struct cleanup *back_to = make_cleanup (free_current_contents, &scope);
+
+  if (expression_context_block)
+    scope = sal_macro_scope (find_pc_line (expression_context_pc, 0));
+  else
+    scope = default_macro_scope ();
+
+  if (scope)
+    {
+      expression_macro_lookup_func = standard_macro_lookup;
+      expression_macro_lookup_baton = (void *) scope;
+    }
+  else
+    {
+      expression_macro_lookup_func = null_macro_lookup;
+      expression_macro_lookup_baton = 0;      
+    }
+
+  gdb_assert (! macro_original_text);
+  make_cleanup (scan_macro_cleanup, 0);
+
+  {
+    int result = c_parse ();
+    do_cleanups (back_to);
+    return result;
+  }
+}
+
+
+\f
 /* Table mapping opcodes into strings for printing operators
    and precedences of the operators.  */
 
@@ -391,26 +513,26 @@ const struct op_print c_op_print_tab[] =
   {NULL, 0, 0, 0}
 };
 \f
-struct type **CONST_PTR (c_builtin_types[]) =
+struct type **const (c_builtin_types[]) =
 {
   &builtin_type_int,
-    &builtin_type_long,
-    &builtin_type_short,
-    &builtin_type_char,
-    &builtin_type_float,
-    &builtin_type_double,
-    &builtin_type_void,
-    &builtin_type_long_long,
-    &builtin_type_signed_char,
-    &builtin_type_unsigned_char,
-    &builtin_type_unsigned_short,
-    &builtin_type_unsigned_int,
-    &builtin_type_unsigned_long,
-    &builtin_type_unsigned_long_long,
-    &builtin_type_long_double,
-    &builtin_type_complex,
-    &builtin_type_double_complex,
-    0
+  &builtin_type_long,
+  &builtin_type_short,
+  &builtin_type_char,
+  &builtin_type_float,
+  &builtin_type_double,
+  &builtin_type_void,
+  &builtin_type_long_long,
+  &builtin_type_signed_char,
+  &builtin_type_unsigned_char,
+  &builtin_type_unsigned_short,
+  &builtin_type_unsigned_int,
+  &builtin_type_unsigned_long,
+  &builtin_type_unsigned_long_long,
+  &builtin_type_long_double,
+  &builtin_type_complex,
+  &builtin_type_double_complex,
+  0
 };
 
 const struct language_defn c_language_defn =
@@ -420,7 +542,8 @@ const struct language_defn c_language_defn =
   c_builtin_types,
   range_check_off,
   type_check_off,
-  c_parse,
+  case_sensitive_on,
+  c_preprocess_and_parse,
   c_error,
   evaluate_subexp_standard,
   c_printchar,                 /* Print a character constant */
@@ -430,6 +553,8 @@ const struct language_defn c_language_defn =
   c_print_type,                        /* Print a type using appropriate syntax */
   c_val_print,                 /* Print a value using appropriate syntax */
   c_value_print,               /* Print a top-level value */
+  NULL,                                /* Language specific skip_trampoline */
+  NULL,                                /* Language specific symbol demangler */
   {"", "", "", ""},            /* Binary format info */
   {"0%lo", "0", "o", ""},      /* Octal format info */
   {"%ld", "", "d", ""},                /* Decimal format info */
@@ -444,24 +569,24 @@ const struct language_defn c_language_defn =
 struct type **const (cplus_builtin_types[]) =
 {
   &builtin_type_int,
-    &builtin_type_long,
-    &builtin_type_short,
-    &builtin_type_char,
-    &builtin_type_float,
-    &builtin_type_double,
-    &builtin_type_void,
-    &builtin_type_long_long,
-    &builtin_type_signed_char,
-    &builtin_type_unsigned_char,
-    &builtin_type_unsigned_short,
-    &builtin_type_unsigned_int,
-    &builtin_type_unsigned_long,
-    &builtin_type_unsigned_long_long,
-    &builtin_type_long_double,
-    &builtin_type_complex,
-    &builtin_type_double_complex,
-    &builtin_type_bool,
-    0
+  &builtin_type_long,
+  &builtin_type_short,
+  &builtin_type_char,
+  &builtin_type_float,
+  &builtin_type_double,
+  &builtin_type_void,
+  &builtin_type_long_long,
+  &builtin_type_signed_char,
+  &builtin_type_unsigned_char,
+  &builtin_type_unsigned_short,
+  &builtin_type_unsigned_int,
+  &builtin_type_unsigned_long,
+  &builtin_type_unsigned_long_long,
+  &builtin_type_long_double,
+  &builtin_type_complex,
+  &builtin_type_double_complex,
+  &builtin_type_bool,
+  0
 };
 
 const struct language_defn cplus_language_defn =
@@ -471,7 +596,8 @@ const struct language_defn cplus_language_defn =
   cplus_builtin_types,
   range_check_off,
   type_check_off,
-  c_parse,
+  case_sensitive_on,
+  c_preprocess_and_parse,
   c_error,
   evaluate_subexp_standard,
   c_printchar,                 /* Print a character constant */
@@ -481,6 +607,8 @@ const struct language_defn cplus_language_defn =
   c_print_type,                        /* Print a type using appropriate syntax */
   c_val_print,                 /* Print a value using appropriate syntax */
   c_value_print,               /* Print a top-level value */
+  NULL,                                /* Language specific skip_trampoline */
+  cplus_demangle,              /* Language specific symbol demangler */
   {"", "", "", ""},            /* Binary format info */
   {"0%lo", "0", "o", ""},      /* Octal format info */
   {"%ld", "", "d", ""},                /* Decimal format info */
@@ -499,7 +627,8 @@ const struct language_defn asm_language_defn =
   c_builtin_types,
   range_check_off,
   type_check_off,
-  c_parse,
+  case_sensitive_on,
+  c_preprocess_and_parse,
   c_error,
   evaluate_subexp_standard,
   c_printchar,                 /* Print a character constant */
@@ -509,6 +638,8 @@ const struct language_defn asm_language_defn =
   c_print_type,                        /* Print a type using appropriate syntax */
   c_val_print,                 /* Print a value using appropriate syntax */
   c_value_print,               /* Print a top-level value */
+  NULL,                                /* Language specific skip_trampoline */
+  NULL,                                /* Language specific symbol demangler */
   {"", "", "", ""},            /* Binary format info */
   {"0%lo", "0", "o", ""},      /* Octal format info */
   {"%ld", "", "d", ""},                /* Decimal format info */
@@ -521,7 +652,7 @@ const struct language_defn asm_language_defn =
 };
 
 void
-_initialize_c_language ()
+_initialize_c_language (void)
 {
   add_language (&c_language_defn);
   add_language (&cplus_language_defn);
This page took 0.062364 seconds and 4 git commands to generate.