/* Parse expressions for GDB.
- Copyright (C) 1986, 1989, 1990, 1991 Free Software Foundation, Inc.
+
+ Copyright (C) 1986, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
+ 1998, 1999, 2000, 2001, 2004, 2005, 2007, 2008, 2009
+ Free Software Foundation, Inc.
+
Modified from expread.y by the Department of Computer Science at the
State University of New York at Buffalo, 1991.
-This file is part of GDB.
+ This file is part of GDB.
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* Parse an expression from text in a string,
and return the result as a struct expression pointer.
What is important here is that it can be built up sequentially
during the process of parsing; the lower levels of the tree always
come first in the result. */
-
+
+#include <ctype.h>
+
#include "defs.h"
+#include "gdb_string.h"
#include "symtab.h"
#include "gdbtypes.h"
#include "frame.h"
#include "value.h"
#include "command.h"
#include "language.h"
+#include "f-lang.h"
#include "parser-defs.h"
-
+#include "gdbcmd.h"
+#include "symfile.h" /* for overlay functions */
+#include "inferior.h"
+#include "doublest.h"
+#include "gdb_assert.h"
+#include "block.h"
+#include "source.h"
+#include "objfiles.h"
+#include "exceptions.h"
+#include "user-regs.h"
+
+/* Standard set of definitions for printing, dumping, prefixifying,
+ * and evaluating expressions. */
+
+const struct exp_descriptor exp_descriptor_standard =
+ {
+ print_subexp_standard,
+ operator_length_standard,
+ op_name_standard,
+ dump_subexp_body_standard,
+ evaluate_subexp_standard
+ };
+\f
+/* Global variables declared in parser-defs.h (and commented there). */
+struct expression *expout;
+int expout_size;
+int expout_ptr;
+struct block *expression_context_block;
+CORE_ADDR expression_context_pc;
+struct block *innermost_block;
+int arglist_len;
+union type_stack_elt *type_stack;
+int type_stack_depth, type_stack_size;
+char *lexptr;
+char *prev_lexptr;
+int paren_depth;
+int comma_terminates;
+
+/* True if parsing an expression to find a field reference. This is
+ only used by completion. */
+int in_parse_field;
+
+/* The index of the last struct expression directly before a '.' or
+ '->'. This is set when parsing and is only used when completing a
+ field name. It is -1 if no dereference operation was found. */
+static int expout_last_struct = -1;
+
+/* A temporary buffer for identifiers, so we can null-terminate them.
+
+ We allocate this with xrealloc. parse_exp_1 used to allocate with
+ alloca, using the size of the whole expression as a conservative
+ estimate of the space needed. However, macro expansion can
+ introduce names longer than the original expression; there's no
+ practical way to know beforehand how large that might be. */
+char *namecopy;
+size_t namecopy_size;
+\f
+static int expressiondebug = 0;
static void
-prefixify_expression PARAMS ((struct expression *));
+show_expressiondebug (struct ui_file *file, int from_tty,
+ struct cmd_list_element *c, const char *value)
+{
+ fprintf_filtered (file, _("Expression debugging is %s.\n"), value);
+}
-static int
-length_of_subexp PARAMS ((struct expression *, int));
+static void free_funcalls (void *ignore);
-static void
-prefixify_subexp PARAMS ((struct expression *, struct expression *, int, int));
+static int prefixify_expression (struct expression *);
+
+static int prefixify_subexp (struct expression *, struct expression *, int,
+ int);
+
+static struct expression *parse_exp_in_context (char **, struct block *, int,
+ int, int *);
-/* Assign machine-independent names to certain registers
- (unless overridden by the REGISTER_NAMES table) */
+void _initialize_parse (void);
-struct std_regs std_regs[] = {
-#ifdef PC_REGNUM
- { "pc", PC_REGNUM },
-#endif
-#ifdef FP_REGNUM
- { "fp", FP_REGNUM },
-#endif
-#ifdef SP_REGNUM
- { "sp", SP_REGNUM },
-#endif
-#ifdef PS_REGNUM
- { "ps", PS_REGNUM },
-#endif
-};
+/* Data structure for saving values of arglist_len for function calls whose
+ arguments contain other function calls. */
-unsigned num_std_regs = (sizeof std_regs / sizeof std_regs[0]);
+struct funcall
+ {
+ struct funcall *next;
+ int arglist_len;
+ };
+static struct funcall *funcall_chain;
/* Begin counting arguments for a function call,
saving the data about any containing call. */
void
-start_arglist ()
+start_arglist (void)
{
- register struct funcall *new = (struct funcall *) xmalloc (sizeof (struct funcall));
+ struct funcall *new;
+ new = (struct funcall *) xmalloc (sizeof (struct funcall));
new->next = funcall_chain;
new->arglist_len = arglist_len;
arglist_len = 0;
and restore the data for the containing function call. */
int
-end_arglist ()
+end_arglist (void)
{
- register int val = arglist_len;
- register struct funcall *call = funcall_chain;
+ int val = arglist_len;
+ struct funcall *call = funcall_chain;
funcall_chain = call->next;
arglist_len = call->arglist_len;
- free ((PTR)call);
+ xfree (call);
return val;
}
/* Free everything in the funcall chain.
Used when there is an error inside parsing. */
-void
-free_funcalls ()
+static void
+free_funcalls (void *ignore)
{
- register struct funcall *call, *next;
+ struct funcall *call, *next;
for (call = funcall_chain; call; call = next)
{
next = call->next;
- free ((PTR)call);
+ xfree (call);
}
}
\f
a register through here */
void
-write_exp_elt (expelt)
- union exp_element expelt;
+write_exp_elt (union exp_element expelt)
{
if (expout_ptr >= expout_size)
{
expout_size *= 2;
- expout = (struct expression *) xrealloc ((char *) expout,
- sizeof (struct expression)
- + expout_size * sizeof (union exp_element));
+ expout = (struct expression *)
+ xrealloc ((char *) expout, sizeof (struct expression)
+ + EXP_ELEM_TO_BYTES (expout_size));
}
expout->elts[expout_ptr++] = expelt;
}
void
-write_exp_elt_opcode (expelt)
- enum exp_opcode expelt;
+write_exp_elt_opcode (enum exp_opcode expelt)
{
union exp_element tmp;
+ memset (&tmp, 0, sizeof (union exp_element));
tmp.opcode = expelt;
}
void
-write_exp_elt_sym (expelt)
- struct symbol *expelt;
+write_exp_elt_sym (struct symbol *expelt)
{
union exp_element tmp;
+ memset (&tmp, 0, sizeof (union exp_element));
tmp.symbol = expelt;
}
void
-write_exp_elt_longcst (expelt)
- LONGEST expelt;
+write_exp_elt_block (struct block *b)
+{
+ union exp_element tmp;
+ memset (&tmp, 0, sizeof (union exp_element));
+ tmp.block = b;
+ write_exp_elt (tmp);
+}
+
+void
+write_exp_elt_objfile (struct objfile *objfile)
+{
+ union exp_element tmp;
+ memset (&tmp, 0, sizeof (union exp_element));
+ tmp.objfile = objfile;
+ write_exp_elt (tmp);
+}
+
+void
+write_exp_elt_longcst (LONGEST expelt)
{
union exp_element tmp;
+ memset (&tmp, 0, sizeof (union exp_element));
tmp.longconst = expelt;
}
void
-write_exp_elt_dblcst (expelt)
- double expelt;
+write_exp_elt_dblcst (DOUBLEST expelt)
{
union exp_element tmp;
+ memset (&tmp, 0, sizeof (union exp_element));
tmp.doubleconst = expelt;
}
void
-write_exp_elt_type (expelt)
- struct type *expelt;
+write_exp_elt_decfloatcst (gdb_byte expelt[16])
+{
+ union exp_element tmp;
+ int index;
+
+ for (index = 0; index < 16; index++)
+ tmp.decfloatconst[index] = expelt[index];
+
+ write_exp_elt (tmp);
+}
+
+void
+write_exp_elt_type (struct type *expelt)
{
union exp_element tmp;
+ memset (&tmp, 0, sizeof (union exp_element));
tmp.type = expelt;
}
void
-write_exp_elt_intern (expelt)
- struct internalvar *expelt;
+write_exp_elt_intern (struct internalvar *expelt)
{
union exp_element tmp;
+ memset (&tmp, 0, sizeof (union exp_element));
tmp.internalvar = expelt;
}
/* Add a string constant to the end of the expression.
- Follow it by its length in bytes, as a separate exp_element. */
+
+ String constants are stored by first writing an expression element
+ that contains the length of the string, then stuffing the string
+ constant itself into however many expression elements are needed
+ to hold it, and then writing another expression element that contains
+ the length of the string. I.E. an expression element at each end of
+ the string records the string length, so you can skip over the
+ expression elements containing the actual string bytes from either
+ end of the string. Note that this also allows gdb to handle
+ strings with embedded null bytes, as is required for some languages.
+
+ Don't be fooled by the fact that the string is null byte terminated,
+ this is strictly for the convenience of debugging gdb itself.
+ Gdb does not depend up the string being null terminated, since the
+ actual length is recorded in expression elements at each end of the
+ string. The null byte is taken into consideration when computing how
+ many expression elements are required to hold the string constant, of
+ course. */
+
void
-write_exp_string (str)
- struct stoken str;
+write_exp_string (struct stoken str)
{
- register int len = str.length;
- register int lenelt
- = (len + sizeof (union exp_element)) / sizeof (union exp_element);
+ int len = str.length;
+ int lenelt;
+ char *strdata;
- expout_ptr += lenelt;
+ /* Compute the number of expression elements required to hold the string
+ (including a null byte terminator), along with one expression element
+ at each end to record the actual string length (not including the
+ null byte terminator). */
- if (expout_ptr >= expout_size)
+ lenelt = 2 + BYTES_TO_EXP_ELEM (len + 1);
+
+ /* 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 + 10);
+ expout_size = max (expout_size * 2, expout_ptr + lenelt + 10);
expout = (struct expression *)
xrealloc ((char *) expout, (sizeof (struct expression)
- + (expout_size * sizeof (union exp_element))));
+ + EXP_ELEM_TO_BYTES (expout_size)));
}
- memcpy ((char *) &expout->elts[expout_ptr - lenelt], str.ptr, len);
- ((char *) &expout->elts[expout_ptr - lenelt])[len] = 0;
+
+ /* Write the leading length expression element (which advances the current
+ expression element index), then write the string constant followed by a
+ terminating null byte, and then write the trailing length expression
+ element. */
+
+ write_exp_elt_longcst ((LONGEST) len);
+ strdata = (char *) &expout->elts[expout_ptr];
+ memcpy (strdata, str.ptr, len);
+ *(strdata + len) = '\0';
+ expout_ptr += lenelt - 2;
write_exp_elt_longcst ((LONGEST) len);
}
-\f
-/* Return a null-terminated temporary copy of the name
- of a string token. */
-char *
-copy_name (token)
- struct stoken token;
+/* Add a vector of string constants to the end of the expression.
+
+ This adds an OP_STRING operation, but encodes the contents
+ differently from write_exp_string. The language is expected to
+ handle evaluation of this expression itself.
+
+ After the usual OP_STRING header, TYPE is written into the
+ expression as a long constant. The interpretation of this field is
+ up to the language evaluator.
+
+ Next, each string in VEC is written. The length is written as a
+ long constant, followed by the contents of the string. */
+
+void
+write_exp_string_vector (int type, struct stoken_vector *vec)
{
- memcpy (namecopy, token.ptr, token.length);
- namecopy[token.length] = 0;
- return namecopy;
+ int i, n_slots, len;
+
+ /* Compute the size. We compute the size in number of slots to
+ avoid issues with string padding. */
+ n_slots = 0;
+ for (i = 0; i < vec->len; ++i)
+ {
+ /* One slot for the length of this element, plus the number of
+ slots needed for this string. */
+ n_slots += 1 + BYTES_TO_EXP_ELEM (vec->tokens[i].length);
+ }
+
+ /* One more slot for the type of the string. */
+ ++n_slots;
+
+ /* Now compute a phony string length. */
+ len = EXP_ELEM_TO_BYTES (n_slots) - 1;
+
+ n_slots += 4;
+ if ((expout_ptr + n_slots) >= expout_size)
+ {
+ expout_size = max (expout_size * 2, expout_ptr + n_slots + 10);
+ expout = (struct expression *)
+ xrealloc ((char *) expout, (sizeof (struct expression)
+ + EXP_ELEM_TO_BYTES (expout_size)));
+ }
+
+ write_exp_elt_opcode (OP_STRING);
+ write_exp_elt_longcst (len);
+ write_exp_elt_longcst (type);
+
+ for (i = 0; i < vec->len; ++i)
+ {
+ write_exp_elt_longcst (vec->tokens[i].length);
+ memcpy (&expout->elts[expout_ptr], vec->tokens[i].ptr,
+ vec->tokens[i].length);
+ expout_ptr += BYTES_TO_EXP_ELEM (vec->tokens[i].length);
+ }
+
+ write_exp_elt_longcst (len);
+ write_exp_elt_opcode (OP_STRING);
}
-\f
-/* Reverse an expression from suffix form (in which it is constructed)
- to prefix form (in which we can conveniently print or execute it). */
-static void
-prefixify_expression (expr)
- register struct expression *expr;
+/* 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 len = sizeof (struct expression) +
- expr->nelts * sizeof (union exp_element);
- register struct expression *temp;
- register int inpos = expr->nelts, outpos = 0;
+ int bits = str.length; /* length in bits */
+ int len = (bits + HOST_CHAR_BIT - 1) / HOST_CHAR_BIT;
+ int lenelt;
+ char *strdata;
- temp = (struct expression *) alloca (len);
+ /* 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. */
- /* Copy the original expression into temp. */
- memcpy (temp, expr, len);
+ 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. */
- prefixify_subexp (temp, expr, inpos, outpos);
+ 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);
}
-/* Return the number of exp_elements in the subexpression of EXPR
- whose last exp_element is at index ENDPOS - 1 in EXPR. */
+/* Add the appropriate elements for a minimal symbol to the end of
+ the expression. */
-static int
-length_of_subexp (expr, endpos)
- register struct expression *expr;
- register int endpos;
+void
+write_exp_msymbol (struct minimal_symbol *msymbol)
{
- register int oplen = 1;
- register int args = 0;
- register int i;
+ struct objfile *objfile = msymbol_objfile (msymbol);
+ struct gdbarch *gdbarch = get_objfile_arch (objfile);
+
+ CORE_ADDR addr = SYMBOL_VALUE_ADDRESS (msymbol);
+ struct obj_section *section = SYMBOL_OBJ_SECTION (msymbol);
+ enum minimal_symbol_type type = MSYMBOL_TYPE (msymbol);
+ CORE_ADDR pc;
+
+ /* The minimal symbol might point to a function descriptor;
+ resolve it to the actual code address instead. */
+ pc = gdbarch_convert_from_func_ptr_addr (gdbarch, addr, ¤t_target);
+ if (pc != addr)
+ {
+ /* In this case, assume we have a code symbol instead of
+ a data symbol. */
+ type = mst_text;
+ section = NULL;
+ addr = pc;
+ }
- if (endpos < 0)
- error ("?error in length_of_subexp");
+ if (overlay_debugging)
+ addr = symbol_overlayed_address (addr, section);
- i = (int) expr->elts[endpos - 1].opcode;
+ 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 (gdbarch)->builtin_core_addr);
+ write_exp_elt_longcst ((LONGEST) addr);
+ write_exp_elt_opcode (OP_LONG);
- switch (i)
+ if (section && section->the_bfd_section->flags & SEC_THREAD_LOCAL)
{
- /* C++ */
- case OP_SCOPE:
- oplen = 4 + ((expr->elts[endpos - 2].longconst
- + sizeof (union exp_element))
- / sizeof (union exp_element));
- break;
+ write_exp_elt_opcode (UNOP_MEMVAL_TLS);
+ write_exp_elt_objfile (objfile);
+ write_exp_elt_type (builtin_type (gdbarch)->nodebug_tls_symbol);
+ write_exp_elt_opcode (UNOP_MEMVAL_TLS);
+ return;
+ }
- case OP_LONG:
- case OP_DOUBLE:
- oplen = 4;
+ write_exp_elt_opcode (UNOP_MEMVAL);
+ switch (type)
+ {
+ case mst_text:
+ case mst_file_text:
+ case mst_solib_trampoline:
+ write_exp_elt_type (builtin_type (gdbarch)->nodebug_text_symbol);
break;
- case OP_TYPE:
- case OP_BOOL:
- case OP_VAR_VALUE:
- case OP_LAST:
- case OP_REGISTER:
- case OP_INTERNALVAR:
- oplen = 3;
+ case mst_data:
+ case mst_file_data:
+ case mst_bss:
+ case mst_file_bss:
+ write_exp_elt_type (builtin_type (gdbarch)->nodebug_data_symbol);
break;
- case OP_FUNCALL:
- oplen = 3;
- args = 1 + expr->elts[endpos - 2].longconst;
+ default:
+ write_exp_elt_type (builtin_type (gdbarch)->nodebug_unknown_symbol);
break;
+ }
+ write_exp_elt_opcode (UNOP_MEMVAL);
+}
- case UNOP_MAX:
- case UNOP_MIN:
- oplen = 3;
- args = 0;
- break;
+/* Mark the current index as the starting location of a structure
+ expression. This is used when completing on field names. */
- case BINOP_VAL:
- case UNOP_CAST:
- case UNOP_MEMVAL:
- oplen = 3;
- args = 1;
- break;
+void
+mark_struct_expression (void)
+{
+ expout_last_struct = expout_ptr;
+}
- case UNOP_ABS:
- case UNOP_CAP:
- case UNOP_CHR:
- case UNOP_FLOAT:
- case UNOP_HIGH:
- case UNOP_ODD:
- case UNOP_ORD:
- case UNOP_TRUNC:
- oplen = 1;
- args = 1;
- break;
+\f
+/* Recognize tokens that start with '$'. These include:
- case STRUCTOP_STRUCT:
- case STRUCTOP_PTR:
- args = 1;
- case OP_M2_STRING:
- case OP_STRING:
- oplen = 3 + ((expr->elts[endpos - 2].longconst
- + sizeof (union exp_element))
- / sizeof (union exp_element));
- break;
+ $regname A native register name or a "standard
+ register name".
- case TERNOP_COND:
- args = 3;
- break;
+ $variable A convenience variable with a name chosen
+ by the user.
- /* Modula-2 */
- case BINOP_MULTI_SUBSCRIPT:
- oplen=3;
- args = 1 + expr->elts[endpos- 2].longconst;
- break;
+ $digits Value history with index <digits>, starting
+ from the first value which has index 1.
- case BINOP_ASSIGN_MODIFY:
- oplen = 3;
- args = 2;
- break;
+ $$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.
- /* C++ */
- case OP_THIS:
- oplen = 2;
+ $ | $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)
+{
+ struct symbol *sym = NULL;
+ struct minimal_symbol *msym = NULL;
+ struct internalvar *isym = NULL;
+
+ /* 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;
+ }
- default:
- args = 1 + (i < (int) BINOP_END);
+ /* Handle tokens that refer to machine registers:
+ $ followed by a register name. */
+ i = user_reg_map_name_to_regnum (parse_gdbarch,
+ str.ptr + 1, str.length - 1);
+ if (i >= 0)
+ goto handle_register;
+
+ /* Any names starting with $ are probably debugger internal variables. */
+
+ isym = lookup_only_internalvar (copy_name (str) + 1);
+ if (isym)
+ {
+ write_exp_elt_opcode (OP_INTERNALVAR);
+ write_exp_elt_intern (isym);
+ write_exp_elt_opcode (OP_INTERNALVAR);
+ return;
}
+ /* On some systems, such as HP-UX and hppa-linux, certain system routines
+ have names beginning with $ or $$. Check for those, first. */
+
+ sym = lookup_symbol (copy_name (str), (struct block *) NULL,
+ VAR_DOMAIN, (int *) 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);
+ return;
+ }
+
+ /* Any other names are assumed to be debugger internal variables. */
+
+ write_exp_elt_opcode (OP_INTERNALVAR);
+ write_exp_elt_intern (create_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);
+ str.length--;
+ str.ptr++;
+ write_exp_string (str);
+ write_exp_elt_opcode (OP_REGISTER);
+ return;
+}
+
+
+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;
+}
+\f
+
+
+/* Return a null-terminated temporary copy of the name
+ of a string token. */
+
+char *
+copy_name (struct stoken token)
+{
+ /* Make sure there's enough space for the token. */
+ if (namecopy_size < token.length + 1)
+ {
+ namecopy_size = token.length + 1;
+ namecopy = xrealloc (namecopy, token.length + 1);
+ }
+
+ memcpy (namecopy, token.ptr, token.length);
+ namecopy[token.length] = 0;
+
+ return namecopy;
+}
+\f
+/* Reverse an expression from suffix form (in which it is constructed)
+ to prefix form (in which we can conveniently print or execute it).
+ Ordinarily this always returns -1. However, if EXPOUT_LAST_STRUCT
+ is not -1 (i.e., we are trying to complete a field name), it will
+ return the index of the subexpression which is the left-hand-side
+ of the struct operation at EXPOUT_LAST_STRUCT. */
+
+static int
+prefixify_expression (struct expression *expr)
+{
+ int len = sizeof (struct expression) + EXP_ELEM_TO_BYTES (expr->nelts);
+ struct expression *temp;
+ int inpos = expr->nelts, outpos = 0;
+
+ temp = (struct expression *) alloca (len);
+
+ /* Copy the original expression into temp. */
+ memcpy (temp, expr, len);
+
+ return prefixify_subexp (temp, expr, inpos, outpos);
+}
+
+/* Return the number of exp_elements in the postfix subexpression
+ of EXPR whose operator is at index ENDPOS - 1 in EXPR. */
+
+int
+length_of_subexp (struct expression *expr, int endpos)
+{
+ int oplen, args, i;
+
+ operator_length (expr, endpos, &oplen, &args);
+
while (args > 0)
{
oplen += length_of_subexp (expr, endpos - oplen);
return oplen;
}
-/* Copy the subexpression ending just before index INEND in INEXPR
- into OUTEXPR, starting at index OUTBEG.
- In the process, convert it from suffix to prefix form. */
+/* Sets *OPLENP to the length of the operator whose (last) index is
+ ENDPOS - 1 in EXPR, and sets *ARGSP to the number of arguments that
+ operator takes. */
-static void
-prefixify_subexp (inexpr, outexpr, inend, outbeg)
- register struct expression *inexpr;
- struct expression *outexpr;
- register int inend;
- int outbeg;
-{
- register int oplen = 1;
- register int args = 0;
- register int i;
- int *arglens;
- enum exp_opcode opcode;
+void
+operator_length (struct expression *expr, int endpos, int *oplenp, int *argsp)
+{
+ expr->language_defn->la_exp_desc->operator_length (expr, endpos,
+ oplenp, argsp);
+}
+
+/* Default value for operator_length in exp_descriptor vectors. */
+
+void
+operator_length_standard (struct expression *expr, int endpos,
+ int *oplenp, int *argsp)
+{
+ int oplen = 1;
+ int args = 0;
+ enum f90_range_type range_type;
+ int i;
+
+ if (endpos < 1)
+ error (_("?error in operator_length_standard"));
- /* Compute how long the last operation is (in OPLEN),
- and also how many preceding subexpressions serve as
- arguments for it (in ARGS). */
+ i = (int) expr->elts[endpos - 1].opcode;
- opcode = inexpr->elts[inend - 1].opcode;
- switch (opcode)
+ switch (i)
{
/* C++ */
case OP_SCOPE:
- oplen = 4 + ((inexpr->elts[inend - 2].longconst
- + sizeof (union exp_element))
- / sizeof (union exp_element));
+ oplen = longest_to_int (expr->elts[endpos - 2].longconst);
+ oplen = 5 + BYTES_TO_EXP_ELEM (oplen + 1);
break;
case OP_LONG:
case OP_DOUBLE:
+ case OP_DECFLOAT:
+ case OP_VAR_VALUE:
oplen = 4;
break;
case OP_TYPE:
case OP_BOOL:
- case OP_VAR_VALUE:
case OP_LAST:
- case OP_REGISTER:
case OP_INTERNALVAR:
oplen = 3;
break;
+ case OP_COMPLEX:
+ oplen = 3;
+ args = 2;
+ break;
+
case OP_FUNCALL:
+ case OP_F77_UNDETERMINED_ARGLIST:
oplen = 3;
- args = 1 + inexpr->elts[inend - 2].longconst;
+ args = 1 + longest_to_int (expr->elts[endpos - 2].longconst);
+ break;
+
+ case OP_OBJC_MSGCALL: /* Objective C message (method) call */
+ oplen = 4;
+ args = 1 + longest_to_int (expr->elts[endpos - 2].longconst);
break;
- case UNOP_MIN:
case UNOP_MAX:
+ case UNOP_MIN:
oplen = 3;
- args = 0;
break;
+ case BINOP_VAL:
case UNOP_CAST:
case UNOP_MEMVAL:
oplen = 3;
args = 1;
break;
+ case UNOP_MEMVAL_TLS:
+ oplen = 4;
+ args = 1;
+ break;
+
case UNOP_ABS:
case UNOP_CAP:
case UNOP_CHR:
case UNOP_ODD:
case UNOP_ORD:
case UNOP_TRUNC:
- oplen=1;
- args=1;
+ oplen = 1;
+ args = 1;
break;
- case STRUCTOP_STRUCT:
+ case OP_LABELED:
+ case STRUCTOP_STRUCT:
case STRUCTOP_PTR:
args = 1;
+ /* fall through */
+ case OP_REGISTER:
case OP_M2_STRING:
case OP_STRING:
- oplen = 3 + ((inexpr->elts[inend - 2].longconst
- + sizeof (union exp_element))
- / sizeof (union exp_element));
-
+ case OP_OBJC_NSSTRING: /* Objective C Foundation Class NSString constant */
+ case OP_OBJC_SELECTOR: /* Objective C "@selector" pseudo-op */
+ case OP_NAME:
+ oplen = longest_to_int (expr->elts[endpos - 2].longconst);
+ oplen = 4 + BYTES_TO_EXP_ELEM (oplen + 1);
+ break;
+
+ case OP_BITSTRING:
+ oplen = longest_to_int (expr->elts[endpos - 2].longconst);
+ oplen = (oplen + HOST_CHAR_BIT - 1) / HOST_CHAR_BIT;
+ oplen = 4 + BYTES_TO_EXP_ELEM (oplen);
+ break;
+
+ case OP_ARRAY:
+ oplen = 4;
+ args = longest_to_int (expr->elts[endpos - 2].longconst);
+ args -= longest_to_int (expr->elts[endpos - 3].longconst);
+ args += 1;
break;
case TERNOP_COND:
+ case TERNOP_SLICE:
+ case TERNOP_SLICE_COUNT:
args = 3;
break;
- case BINOP_ASSIGN_MODIFY:
+ /* Modula-2 */
+ case MULTI_SUBSCRIPT:
oplen = 3;
- args = 2;
+ args = 1 + longest_to_int (expr->elts[endpos - 2].longconst);
break;
- /* Modula-2 */
- case BINOP_MULTI_SUBSCRIPT:
- oplen=3;
- args = 1 + inexpr->elts[inend - 2].longconst;
+ case BINOP_ASSIGN_MODIFY:
+ oplen = 3;
+ args = 2;
break;
/* C++ */
case OP_THIS:
+ case OP_OBJC_SELF:
oplen = 2;
break;
+ case OP_F90_RANGE:
+ oplen = 3;
+
+ range_type = longest_to_int (expr->elts[endpos - 2].longconst);
+ switch (range_type)
+ {
+ case LOW_BOUND_DEFAULT:
+ case HIGH_BOUND_DEFAULT:
+ args = 1;
+ break;
+ case BOTH_BOUND_DEFAULT:
+ args = 0;
+ break;
+ case NONE_BOUND_DEFAULT:
+ args = 2;
+ break;
+ }
+
+ break;
+
default:
- args = 1 + ((int) opcode < (int) BINOP_END);
+ args = 1 + (i < (int) BINOP_END);
}
+ *oplenp = oplen;
+ *argsp = args;
+}
+
+/* Copy the subexpression ending just before index INEND in INEXPR
+ into OUTEXPR, starting at index OUTBEG.
+ In the process, convert it from suffix to prefix form.
+ If EXPOUT_LAST_STRUCT is -1, then this function always returns -1.
+ Otherwise, it returns the index of the subexpression which is the
+ left-hand-side of the expression at EXPOUT_LAST_STRUCT. */
+
+static int
+prefixify_subexp (struct expression *inexpr,
+ struct expression *outexpr, int inend, int outbeg)
+{
+ int oplen;
+ int args;
+ int i;
+ int *arglens;
+ enum exp_opcode opcode;
+ int result = -1;
+
+ operator_length (inexpr, inend, &oplen, &args);
+
/* Copy the final operator itself, from the end of the input
to the beginning of the output. */
inend -= oplen;
memcpy (&outexpr->elts[outbeg], &inexpr->elts[inend],
- oplen * sizeof (union exp_element));
+ EXP_ELEM_TO_BYTES (oplen));
outbeg += oplen;
+ if (expout_last_struct == inend)
+ result = outbeg - oplen;
+
/* Find the lengths of the arg subexpressions. */
arglens = (int *) alloca (args * sizeof (int));
for (i = args - 1; i >= 0; i--)
outbeg does similarly in the output. */
for (i = 0; i < args; i++)
{
+ int r;
oplen = arglens[i];
inend += oplen;
- prefixify_subexp (inexpr, outexpr, inend, outbeg);
+ r = prefixify_subexp (inexpr, outexpr, inend, outbeg);
+ if (r != -1)
+ {
+ /* Return immediately. We probably have only parsed a
+ partial expression, so we don't want to try to reverse
+ the other operands. */
+ return r;
+ }
outbeg += oplen;
}
+
+ return result;
}
\f
/* This page contains the two entry points to this file. */
If COMMA is nonzero, stop if a comma is reached. */
struct expression *
-parse_exp_1 (stringptr, block, comma)
- char **stringptr;
- struct block *block;
- int comma;
+parse_exp_1 (char **stringptr, struct block *block, int comma)
+{
+ return parse_exp_in_context (stringptr, block, comma, 0, NULL);
+}
+
+/* As for parse_exp_1, except that if VOID_CONTEXT_P, then
+ no value is expected from the expression.
+ OUT_SUBEXP is set when attempting to complete a field name; in this
+ case it is set to the index of the subexpression on the
+ left-hand-side of the struct op. If not doing such completion, it
+ is left untouched. */
+
+static struct expression *
+parse_exp_in_context (char **stringptr, struct block *block, int comma,
+ int void_context_p, int *out_subexp)
{
+ volatile struct gdb_exception except;
struct cleanup *old_chain;
+ int subexp;
lexptr = *stringptr;
+ prev_lexptr = NULL;
paren_depth = 0;
type_stack_depth = 0;
+ expout_last_struct = -1;
comma_terminates = comma;
if (lexptr == 0 || *lexptr == 0)
- error_no_arg ("expression to compute");
+ error_no_arg (_("expression to compute"));
- old_chain = make_cleanup (free_funcalls, 0);
+ old_chain = make_cleanup (free_funcalls, 0 /*ignore*/);
funcall_chain = 0;
- expression_context_block = block ? block : get_selected_block ();
+ expression_context_block = block;
+
+ /* If no context specified, try using the current frame, if any. */
+ if (!expression_context_block)
+ expression_context_block = get_selected_block (&expression_context_pc);
+ else
+ expression_context_pc = BLOCK_START (expression_context_block);
+
+ /* Fall back to using the current source static context, if any. */
+
+ if (!expression_context_block)
+ {
+ struct symtab_and_line cursal = get_current_source_symtab_and_line ();
+ if (cursal.symtab)
+ expression_context_block
+ = BLOCKVECTOR_BLOCK (BLOCKVECTOR (cursal.symtab), STATIC_BLOCK);
+ if (expression_context_block)
+ expression_context_pc = BLOCK_START (expression_context_block);
+ }
- namecopy = (char *) alloca (strlen (lexptr) + 1);
expout_size = 10;
expout_ptr = 0;
expout = (struct expression *)
- xmalloc (sizeof (struct expression)
- + expout_size * sizeof (union exp_element));
+ xmalloc (sizeof (struct expression) + EXP_ELEM_TO_BYTES (expout_size));
expout->language_defn = current_language;
- make_cleanup (free_current_contents, &expout);
+ expout->gdbarch = current_gdbarch;
- if (current_language->la_parser ())
- current_language->la_error (NULL);
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ if (current_language->la_parser ())
+ current_language->la_error (NULL);
+ }
+ if (except.reason < 0)
+ {
+ if (! in_parse_field)
+ {
+ xfree (expout);
+ throw_exception (except);
+ }
+ }
discard_cleanups (old_chain);
+
+ /* Record the actual number of expression elements, and then
+ reallocate the expression memory so that we free up any
+ excess elements. */
+
expout->nelts = expout_ptr;
expout = (struct expression *)
xrealloc ((char *) expout,
- sizeof (struct expression)
- + expout_ptr * sizeof (union exp_element));
- prefixify_expression (expout);
+ sizeof (struct expression) + EXP_ELEM_TO_BYTES (expout_ptr));;
+
+ /* Convert expression from postfix form as generated by yacc
+ parser, to a prefix form. */
+
+ if (expressiondebug)
+ dump_raw_expression (expout, gdb_stdlog,
+ "before conversion to prefix form");
+
+ subexp = prefixify_expression (expout);
+ if (out_subexp)
+ *out_subexp = subexp;
+
+ current_language->la_post_parser (&expout, void_context_p);
+
+ if (expressiondebug)
+ dump_prefix_expression (expout, gdb_stdlog);
+
*stringptr = lexptr;
return expout;
}
to use up all of the contents of STRING. */
struct expression *
-parse_expression (string)
- char *string;
+parse_expression (char *string)
{
- register struct expression *exp;
+ struct expression *exp;
exp = parse_exp_1 (&string, 0, 0);
if (*string)
- error ("Junk after end of expression.");
+ error (_("Junk after end of expression."));
return exp;
}
-void
-push_type (tp)
- enum type_pieces tp;
+/* Parse STRING as an expression. If parsing ends in the middle of a
+ field reference, return the type of the left-hand-side of the
+ reference; furthermore, if the parsing ends in the field name,
+ return the field name in *NAME. In all other cases, return NULL.
+ Returned non-NULL *NAME must be freed by the caller. */
+
+struct type *
+parse_field_expression (char *string, char **name)
{
- if (type_stack_depth == type_stack_size)
+ struct expression *exp = NULL;
+ struct value *val;
+ int subexp;
+ volatile struct gdb_exception except;
+
+ TRY_CATCH (except, RETURN_MASK_ALL)
{
- type_stack_size *= 2;
- type_stack = (union type_stack_elt *)
- xrealloc ((char *) type_stack, type_stack_size * sizeof (*type_stack));
+ in_parse_field = 1;
+ exp = parse_exp_in_context (&string, 0, 0, 0, &subexp);
}
- type_stack[type_stack_depth++].piece = tp;
+ in_parse_field = 0;
+ if (except.reason < 0 || ! exp)
+ return NULL;
+ if (expout_last_struct == -1)
+ {
+ xfree (exp);
+ return NULL;
+ }
+
+ *name = extract_field_op (exp, &subexp);
+ if (!*name)
+ {
+ xfree (exp);
+ return NULL;
+ }
+ /* (*NAME) is a part of the EXP memory block freed below. */
+ *name = xstrdup (*name);
+
+ val = evaluate_subexpression_type (exp, subexp);
+ xfree (exp);
+
+ return value_type (val);
}
+/* A post-parser that does nothing */
+
void
-push_type_int (n)
- int n;
+null_post_parser (struct expression **exp, int void_context_p)
+{
+}
+\f
+/* Stuff for maintaining a stack of types. Currently just used by C, but
+ probably useful for any language which declares its types "backwards". */
+
+static void
+check_type_stack_depth (void)
{
if (type_stack_depth == type_stack_size)
{
type_stack = (union type_stack_elt *)
xrealloc ((char *) type_stack, type_stack_size * sizeof (*type_stack));
}
+}
+
+void
+push_type (enum type_pieces tp)
+{
+ check_type_stack_depth ();
+ type_stack[type_stack_depth++].piece = tp;
+}
+
+void
+push_type_int (int n)
+{
+ check_type_stack_depth ();
type_stack[type_stack_depth++].int_val = n;
}
-enum type_pieces
-pop_type ()
+void
+push_type_address_space (char *string)
+{
+ push_type_int (address_space_name_to_int (string));
+}
+
+enum type_pieces
+pop_type (void)
{
if (type_stack_depth)
return type_stack[--type_stack_depth].piece;
}
int
-pop_type_int ()
+pop_type_int (void)
{
if (type_stack_depth)
return type_stack[--type_stack_depth].int_val;
return 0;
}
+/* Pop the type stack and return the type which corresponds to FOLLOW_TYPE
+ as modified by all the stuff on the stack. */
+struct type *
+follow_types (struct type *follow_type)
+{
+ int done = 0;
+ int make_const = 0;
+ int make_volatile = 0;
+ int make_addr_space = 0;
+ int array_size;
+ struct type *range_type;
+
+ while (!done)
+ switch (pop_type ())
+ {
+ case tp_end:
+ done = 1;
+ if (make_const)
+ follow_type = make_cv_type (make_const,
+ TYPE_VOLATILE (follow_type),
+ follow_type, 0);
+ if (make_volatile)
+ follow_type = make_cv_type (TYPE_CONST (follow_type),
+ make_volatile,
+ follow_type, 0);
+ if (make_addr_space)
+ follow_type = make_type_with_address_space (follow_type,
+ make_addr_space);
+ make_const = make_volatile = 0;
+ make_addr_space = 0;
+ break;
+ case tp_const:
+ make_const = 1;
+ break;
+ case tp_volatile:
+ make_volatile = 1;
+ break;
+ case tp_space_identifier:
+ make_addr_space = pop_type_int ();
+ break;
+ case tp_pointer:
+ follow_type = lookup_pointer_type (follow_type);
+ if (make_const)
+ follow_type = make_cv_type (make_const,
+ TYPE_VOLATILE (follow_type),
+ follow_type, 0);
+ if (make_volatile)
+ follow_type = make_cv_type (TYPE_CONST (follow_type),
+ make_volatile,
+ follow_type, 0);
+ if (make_addr_space)
+ follow_type = make_type_with_address_space (follow_type,
+ make_addr_space);
+ make_const = make_volatile = 0;
+ make_addr_space = 0;
+ break;
+ case tp_reference:
+ follow_type = lookup_reference_type (follow_type);
+ if (make_const)
+ follow_type = make_cv_type (make_const,
+ TYPE_VOLATILE (follow_type),
+ follow_type, 0);
+ if (make_volatile)
+ follow_type = make_cv_type (TYPE_CONST (follow_type),
+ make_volatile,
+ follow_type, 0);
+ if (make_addr_space)
+ follow_type = make_type_with_address_space (follow_type,
+ make_addr_space);
+ make_const = make_volatile = 0;
+ make_addr_space = 0;
+ break;
+ case tp_array:
+ array_size = pop_type_int ();
+ /* FIXME-type-allocation: need a way to free this type when we are
+ done with it. */
+ range_type =
+ create_range_type ((struct type *) NULL,
+ builtin_type_int32, 0,
+ array_size >= 0 ? array_size - 1 : 0);
+ follow_type =
+ create_array_type ((struct type *) NULL,
+ follow_type, range_type);
+ if (array_size < 0)
+ TYPE_ARRAY_UPPER_BOUND_IS_UNDEFINED (follow_type) = 1;
+ break;
+ case tp_function:
+ /* FIXME-type-allocation: need a way to free this type when we are
+ done with it. */
+ follow_type = lookup_function_type (follow_type);
+ break;
+ }
+ return follow_type;
+}
+\f
+/* This function avoids direct calls to fprintf
+ in the parser generated debug code. */
+void
+parser_fprintf (FILE *x, const char *y, ...)
+{
+ va_list args;
+ va_start (args, y);
+ if (x == stderr)
+ vfprintf_unfiltered (gdb_stderr, y, args);
+ else
+ {
+ fprintf_unfiltered (gdb_stderr, " Unknown FILE used.\n");
+ vfprintf_unfiltered (gdb_stderr, y, args);
+ }
+ va_end (args);
+}
+
void
-_initialize_parse ()
+_initialize_parse (void)
{
type_stack_size = 80;
type_stack_depth = 0;
type_stack = (union type_stack_elt *)
xmalloc (type_stack_size * sizeof (*type_stack));
+
+ add_setshow_zinteger_cmd ("expression", class_maintenance,
+ &expressiondebug, _("\
+Set expression debugging."), _("\
+Show expression debugging."), _("\
+When non-zero, the internal representation of expressions will be printed."),
+ NULL,
+ show_expressiondebug,
+ &setdebuglist, &showdebuglist);
}