+
+/* Add a bitstring constant to the end of the expression.
+
+ Bitstring constants are stored by first writing an expression element
+ that contains the length of the bitstring (in bits), then stuffing the
+ bitstring constant itself into however many expression elements are
+ needed to hold it, and then writing another expression element that
+ contains the length of the bitstring. I.E. an expression element at
+ each end of the bitstring records the bitstring length, so you can skip
+ over the expression elements containing the actual bitstring bytes from
+ either end of the bitstring. */
+
+void
+write_exp_bitstring (struct stoken str)
+{
+ register int bits = str.length; /* length in bits */
+ register int len = (bits + HOST_CHAR_BIT - 1) / HOST_CHAR_BIT;
+ register int lenelt;
+ register char *strdata;
+
+ /* Compute the number of expression elements required to hold the bitstring,
+ along with one expression element at each end to record the actual
+ bitstring length in bits. */
+
+ lenelt = 2 + BYTES_TO_EXP_ELEM (len);
+
+ /* Ensure that we have enough available expression elements to store
+ everything. */
+
+ if ((expout_ptr + lenelt) >= expout_size)
+ {
+ expout_size = max (expout_size * 2, expout_ptr + lenelt + 10);
+ expout = (struct expression *)
+ xrealloc ((char *) expout, (sizeof (struct expression)
+ + EXP_ELEM_TO_BYTES (expout_size)));
+ }
+
+ /* Write the leading length expression element (which advances the current
+ expression element index), then write the bitstring constant, and then
+ write the trailing length expression element. */
+
+ write_exp_elt_longcst ((LONGEST) bits);
+ strdata = (char *) &expout->elts[expout_ptr];
+ memcpy (strdata, str.ptr, len);
+ expout_ptr += lenelt - 2;
+ write_exp_elt_longcst ((LONGEST) bits);
+}
+
+/* Add the appropriate elements for a minimal symbol to the end of
+ the expression. The rationale behind passing in text_symbol_type and
+ data_symbol_type was so that Modula-2 could pass in WORD for
+ data_symbol_type. Perhaps it still is useful to have those types vary
+ based on the language, but they no longer have names like "int", so
+ the initial rationale is gone. */
+
+static struct type *msym_text_symbol_type;
+static struct type *msym_data_symbol_type;
+static struct type *msym_unknown_symbol_type;
+
+void
+write_exp_msymbol (struct minimal_symbol *msymbol,
+ struct type *text_symbol_type,
+ struct type *data_symbol_type)
+{
+ CORE_ADDR addr;
+
+ write_exp_elt_opcode (OP_LONG);
+ /* Let's make the type big enough to hold a 64-bit address. */
+ write_exp_elt_type (builtin_type_CORE_ADDR);
+
+ addr = SYMBOL_VALUE_ADDRESS (msymbol);
+ if (overlay_debugging)
+ addr = symbol_overlayed_address (addr, SYMBOL_BFD_SECTION (msymbol));
+ write_exp_elt_longcst ((LONGEST) addr);
+
+ write_exp_elt_opcode (OP_LONG);
+
+ write_exp_elt_opcode (UNOP_MEMVAL);
+ switch (msymbol->type)
+ {
+ case mst_text:
+ case mst_file_text:
+ case mst_solib_trampoline:
+ write_exp_elt_type (msym_text_symbol_type);
+ break;
+
+ case mst_data:
+ case mst_file_data:
+ case mst_bss:
+ case mst_file_bss:
+ write_exp_elt_type (msym_data_symbol_type);
+ break;
+
+ default:
+ write_exp_elt_type (msym_unknown_symbol_type);
+ break;
+ }
+ write_exp_elt_opcode (UNOP_MEMVAL);
+}
+\f
+/* Recognize tokens that start with '$'. These include:
+
+ $regname A native register name or a "standard
+ register name".
+
+ $variable A convenience variable with a name chosen
+ by the user.
+
+ $digits Value history with index <digits>, starting
+ from the first value which has index 1.
+
+ $$digits Value history with index <digits> relative
+ to the last value. I.E. $$0 is the last
+ value, $$1 is the one previous to that, $$2
+ is the one previous to $$1, etc.
+
+ $ | $0 | $$0 The last value in the value history.
+
+ $$ An abbreviation for the second to the last
+ value in the value history, I.E. $$1
+
+ */
+
+void
+write_dollar_variable (struct stoken str)
+{
+ /* Handle the tokens $digits; also $ (short for $0) and $$ (short for $$1)
+ and $$digits (equivalent to $<-digits> if you could type that). */
+
+ int negate = 0;
+ int i = 1;
+ /* Double dollar means negate the number and add -1 as well.
+ Thus $$ alone means -1. */
+ if (str.length >= 2 && str.ptr[1] == '$')
+ {
+ negate = 1;
+ i = 2;
+ }
+ if (i == str.length)
+ {
+ /* Just dollars (one or two) */
+ i = -negate;
+ goto handle_last;
+ }
+ /* Is the rest of the token digits? */
+ for (; i < str.length; i++)
+ if (!(str.ptr[i] >= '0' && str.ptr[i] <= '9'))
+ break;
+ if (i == str.length)
+ {
+ i = atoi (str.ptr + 1 + negate);
+ if (negate)
+ i = -i;
+ goto handle_last;
+ }
+
+ /* Handle tokens that refer to machine registers:
+ $ followed by a register name. */
+ i = target_map_name_to_register (str.ptr + 1, str.length - 1);
+ if (i >= 0)
+ goto handle_register;
+
+ if (SYMBOLS_CAN_START_WITH_DOLLAR)
+ {
+ struct symbol *sym = NULL;
+ struct minimal_symbol *msym = NULL;
+
+ /* 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. */
+
+ /* This code is not enabled on non HP-UX systems, since worst case
+ symbol table lookup performance is awful, to put it mildly. */
+
+ 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);
+ write_exp_elt_intern (lookup_internalvar (copy_name (str) + 1));
+ write_exp_elt_opcode (OP_INTERNALVAR);
+ return;
+handle_last:
+ write_exp_elt_opcode (OP_LAST);
+ write_exp_elt_longcst ((LONGEST) i);
+ write_exp_elt_opcode (OP_LAST);
+ return;
+handle_register:
+ write_exp_elt_opcode (OP_REGISTER);
+ write_exp_elt_longcst (i);
+ 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 (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;
+ 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);
+
+ /* 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;
+
+ return sym_var ? sym_var : sym_class; /* found */
+}
+
+char *
+find_template_name_end (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;
+}