* windres.c: add verbose option
[deliverable/binutils-gdb.git] / gdb / parse.c
index f90cece80e3c53a2d99d267865e6305da3f26401..76ed1b6f32459417f16bcc7e1d956e43ab1aa2c2 100644 (file)
@@ -30,6 +30,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
    
 #include "defs.h"
 #include "gdb_string.h"
+#include <ctype.h>
 #include "symtab.h"
 #include "gdbtypes.h"
 #include "frame.h"
@@ -40,6 +41,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #include "parser-defs.h"
 #include "gdbcmd.h"
 #include "symfile.h"   /* for overlay functions */
+#include <ctype.h>
 \f
 /* Global variables declared in parser-defs.h (and commented there).  */
 struct expression *expout;
@@ -55,9 +57,9 @@ char *namecopy;
 int paren_depth;
 int comma_terminates;
 \f
-#ifdef MAINTENANCE_CMDS
 static int expressiondebug = 0;
-#endif
+
+extern int hp_som_som_object_present;
 
 static void
 free_funcalls PARAMS ((void));
@@ -477,6 +479,9 @@ write_dollar_variable (str)
   /* Handle the tokens $digits; also $ (short for $0) and $$ (short for $$1)
      and $$digits (equivalent to $<-digits> if you could type that). */
 
+  struct symbol * sym = NULL;
+  struct minimal_symbol * msym = NULL;
+
   int negate = 0;
   int i = 1;
   /* Double dollar means negate the number and add -1 as well.
@@ -510,6 +515,29 @@ write_dollar_variable (str)
   if( i >= 0 )
     goto handle_register;
 
+  /* On HP-UX, certain system routines (millicode) have names beginning
+     with $ or $$, e.g. $$dyncall, which handles inter-space procedure
+     calls on PA-RISC. Check for those, first. */
+
+  sym = lookup_symbol (copy_name (str), (struct block *) NULL,
+                       VAR_NAMESPACE, (int *) NULL, (struct symtab **) NULL);
+  if (sym)
+    {
+      write_exp_elt_opcode (OP_VAR_VALUE);
+      write_exp_elt_block (block_found); /* set by lookup_symbol */
+      write_exp_elt_sym (sym);
+      write_exp_elt_opcode (OP_VAR_VALUE);
+      return;
+    }
+  msym = lookup_minimal_symbol (copy_name (str), NULL, NULL);
+  if (msym)
+    {
+      write_exp_msymbol (msym,
+                         lookup_function_type (builtin_type_int),
+                         builtin_type_int);
+      return;
+    }
+  
   /* Any other names starting in $ are debugger internal variables.  */
 
   write_exp_elt_opcode (OP_INTERNALVAR);
@@ -527,6 +555,257 @@ write_dollar_variable (str)
   write_exp_elt_opcode (OP_REGISTER); 
   return;
 }
+
+
+/* Parse a string that is possibly a namespace / nested class
+   specification, i.e., something of the form A::B::C::x.  Input
+   (NAME) is the entire string; LEN is the current valid length; the
+   output is a string, TOKEN, which points to the largest recognized
+   prefix which is a series of namespaces or classes.  CLASS_PREFIX is
+   another output, which records whether a nested class spec was
+   recognized (= 1) or a fully qualified variable name was found (=
+   0).  ARGPTR is side-effected (if non-NULL) to point to beyond the
+   string recognized and consumed by this routine.
+
+   The return value is a pointer to the symbol for the base class or
+   variable if found, or NULL if not found.  Callers must check this
+   first -- if NULL, the outputs may not be correct. 
+
+   This function is used c-exp.y.  This is used specifically to get
+   around HP aCC (and possibly other compilers), which insists on
+   generating names with embedded colons for namespace or nested class
+   members.
+
+   (Argument LEN is currently unused. 1997-08-27)
+
+   Callers must free memory allocated for the output string TOKEN.  */
+
+static const char coloncolon[2] = {':',':'};
+
+struct symbol *
+parse_nested_classes_for_hpacc (name, len, token, class_prefix, argptr)
+  char * name;
+  int len;
+  char ** token;
+  int * class_prefix;
+  char ** argptr;
+{
+   /* Comment below comes from decode_line_1 which has very similar
+      code, which is called for "break" command parsing. */
+  
+   /* We have what looks like a class or namespace
+     scope specification (A::B), possibly with many
+     levels of namespaces or classes (A::B::C::D).
+
+     Some versions of the HP ANSI C++ compiler (as also possibly
+     other compilers) generate class/function/member names with
+     embedded double-colons if they are inside namespaces. To
+     handle this, we loop a few times, considering larger and
+     larger prefixes of the string as though they were single
+     symbols.  So, if the initially supplied string is
+     A::B::C::D::foo, we have to look up "A", then "A::B",
+     then "A::B::C", then "A::B::C::D", and finally
+     "A::B::C::D::foo" as single, monolithic symbols, because
+     A, B, C or D may be namespaces.
+
+     Note that namespaces can nest only inside other
+     namespaces, and not inside classes.  So we need only
+     consider *prefixes* of the string; there is no need to look up
+     "B::C" separately as a symbol in the previous example. */
+
+  register char * p;
+  char * start, * end;
+  char * prefix = NULL;
+  char * tmp;
+  struct symbol * sym_class = NULL;
+  struct symbol * sym_var = NULL;
+  struct type * t;
+  register int i;
+  int colons_found = 0;
+  int prefix_len = 0;
+  int done = 0;
+  char * q; 
+
+  /* Check for HP-compiled executable -- in other cases
+     return NULL, and caller must default to standard GDB
+     behaviour. */
+
+  if (!hp_som_som_object_present)
+    return (struct symbol *) NULL;
+
+  p = name;
+
+  /* Skip over whitespace and possible global "::" */ 
+  while (*p && (*p == ' ' || *p == '\t')) p++;
+  if (p[0] == ':' && p[1] == ':')
+    p += 2;
+  while (*p && (*p == ' ' || *p == '\t')) p++;
+  
+  while (1)
+    {
+      /* Get to the end of the next namespace or class spec. */
+      /* If we're looking at some non-token, fail immediately */
+      start = p;
+      if (!(isalpha (*p) || *p == '$' || *p == '_'))
+        return (struct symbol *) NULL;
+      p++;
+      while (*p && (isalnum (*p) || *p == '$' || *p == '_')) p++;
+
+      if (*p == '<') 
+        {
+          /* If we have the start of a template specification,
+             scan right ahead to its end */ 
+          q = find_template_name_end (p);
+          if (q)
+            p = q;
+        }
+        
+      end = p;
+
+      /* Skip over "::" and whitespace for next time around */ 
+      while (*p && (*p == ' ' || *p == '\t')) p++;
+      if (p[0] == ':' && p[1] == ':')
+        p += 2;
+      while (*p && (*p == ' ' || *p == '\t')) p++;
+
+      /* Done with tokens? */ 
+      if (!*p || !(isalpha (*p) || *p == '$' || *p == '_'))
+        done = 1;
+
+      tmp = (char *) alloca (prefix_len + end - start + 3);
+      if (prefix)
+        {
+          memcpy (tmp, prefix, prefix_len);
+          memcpy (tmp + prefix_len, coloncolon, 2);
+          memcpy (tmp + prefix_len + 2, start, end - start);
+          tmp[prefix_len + 2 + end - start] = '\000';
+        }
+      else
+        {
+          memcpy (tmp, start, end - start);
+          tmp[end - start] = '\000';
+        }
+      
+      prefix = tmp;
+      prefix_len = strlen (prefix);
+      
+#if 0 /* DEBUGGING */ 
+      printf ("Searching for nested class spec: Prefix is %s\n", prefix);
+#endif      
+
+      /* See if the prefix we have now is something we know about */
+
+      if (!done) 
+        {
+          /* More tokens to process, so this must be a class/namespace */
+          sym_class = lookup_symbol (prefix, 0, STRUCT_NAMESPACE,
+                                     0, (struct symtab **) NULL);
+        }
+      else
+        {
+          /* No more tokens, so try as a variable first */ 
+          sym_var = lookup_symbol (prefix, 0, VAR_NAMESPACE,
+                               0, (struct symtab **) NULL);
+          /* If failed, try as class/namespace */ 
+          if (!sym_var)
+            sym_class = lookup_symbol (prefix, 0, STRUCT_NAMESPACE,
+                                       0, (struct symtab **) NULL);
+        }
+
+      if (sym_var ||
+          (sym_class &&
+           (t = check_typedef (SYMBOL_TYPE (sym_class)),
+            (TYPE_CODE (t) == TYPE_CODE_STRUCT
+             || TYPE_CODE (t) == TYPE_CODE_UNION))))
+        {
+          /* We found a valid token */
+          *token = (char *) xmalloc (prefix_len + 1 );
+          memcpy (*token, prefix, prefix_len);
+          (*token)[prefix_len] = '\000';
+          break;
+        }
+
+      /* No variable or class/namespace found, no more tokens */ 
+      if (done)
+        return (struct symbol *) NULL;
+    }
+
+  /* Out of loop, so we must have found a valid token */
+  if (sym_var)
+    *class_prefix = 0;
+  else
+    *class_prefix = 1;
+
+  if (argptr)
+    *argptr = done ? p : end;
+
+#if 0 /* DEBUGGING */ 
+  printf ("Searching for nested class spec: Token is %s, class_prefix %d\n", *token, *class_prefix);
+#endif
+
+  return sym_var ? sym_var : sym_class; /* found */ 
+}
+
+char *
+find_template_name_end (p)
+  char * p;
+{
+  int depth = 1;
+  int just_seen_right = 0;
+  int just_seen_colon = 0;
+  int just_seen_space = 0;
+  
+  if (!p || (*p != '<'))
+    return 0;
+
+  while (*++p)
+    {
+      switch (*p)
+        {
+          case '\'': case '\"':
+          case '{': case '}':
+            /* In future, may want to allow these?? */ 
+            return 0;
+          case '<':
+            depth++;                /* start nested template */ 
+            if (just_seen_colon || just_seen_right || just_seen_space)    
+              return 0;             /* but not after : or :: or > or space */ 
+            break;
+          case '>': 
+            if (just_seen_colon || just_seen_right)
+              return 0;             /* end a (nested?) template */
+            just_seen_right = 1;    /* but not after : or :: */ 
+            if (--depth == 0)       /* also disallow >>, insist on > > */ 
+              return ++p;           /* if outermost ended, return */ 
+            break;
+          case ':':
+            if (just_seen_space || (just_seen_colon > 1))
+              return 0;             /* nested class spec coming up */ 
+            just_seen_colon++;      /* we allow :: but not :::: */ 
+            break;
+          case ' ':
+            break;
+          default:
+            if (!((*p >= 'a' && *p <= 'z') ||   /* allow token chars */ 
+                  (*p >= 'A' && *p <= 'Z') ||
+                  (*p >= '0' && *p <= '9') ||
+                  (*p == '_') || (*p == ',') || /* commas for template args */
+                  (*p == '&') || (*p == '*') || /* pointer and ref types */
+                  (*p == '(') || (*p == ')') || /* function types */ 
+                  (*p == '[') || (*p == ']') )) /* array types */  
+              return 0;
+        }
+      if (*p != ' ')
+        just_seen_space = 0;
+      if (*p != ':')
+        just_seen_colon = 0;
+      if (*p != '>')
+        just_seen_right = 0;
+    }
+  return 0;
+}
+
+
 \f
 /* Return a null-terminated temporary copy of the name
    of a string token.  */
@@ -916,19 +1195,15 @@ parse_exp_1 (stringptr, block, comma)
   /* Convert expression from postfix form as generated by yacc
      parser, to a prefix form. */
 
-#ifdef MAINTENANCE_CMDS
   if (expressiondebug)
     dump_prefix_expression (expout, gdb_stdout,
                            "before conversion to prefix form");
-#endif /* MAINTENANCE_CMDS */
 
   prefixify_expression (expout);
 
-#ifdef MAINTENANCE_CMDS
   if (expressiondebug)
     dump_postfix_expression (expout, gdb_stdout,
                             "after conversion to prefix form");
-#endif /* MAINTENANCE_CMDS */
 
   *stringptr = lexptr;
   return expout;
@@ -1059,7 +1334,6 @@ _initialize_parse ()
               "<variable (not text or data), no debug info>",
               NULL);
 
-#ifdef MAINTENANCE_CMDS
   add_show_from_set (
      add_set_cmd ("expressiondebug", class_maintenance, var_zinteger,
                  (char *)&expressiondebug,
@@ -1067,5 +1341,4 @@ _initialize_parse ()
 When non-zero, the internal representation of expressions will be printed.",
                  &setlist),
      &showlist);
-#endif
 }
This page took 0.026714 seconds and 4 git commands to generate.