{
print_subexp_standard,
operator_length_standard,
+ operator_check_standard,
op_name_standard,
dump_subexp_body_standard,
evaluate_subexp_standard
fprintf_filtered (file, _("Expression debugging is %s.\n"), value);
}
+
+/* Non-zero if an expression parser should set yydebug. */
+int parser_debug;
+
+static void
+show_parserdebug (struct ui_file *file, int from_tty,
+ struct cmd_list_element *c, const char *value)
+{
+ fprintf_filtered (file, _("Parser debugging is %s.\n"), value);
+}
+
+
static void free_funcalls (void *ignore);
static int prefixify_expression (struct expression *);
{
int val = arglist_len;
struct funcall *call = funcall_chain;
+
funcall_chain = call->next;
arglist_len = call->arglist_len;
xfree (call);
write_exp_elt_opcode (enum exp_opcode expelt)
{
union exp_element tmp;
- memset (&tmp, 0, sizeof (union exp_element));
+ memset (&tmp, 0, sizeof (union exp_element));
tmp.opcode = expelt;
-
write_exp_elt (tmp);
}
write_exp_elt_sym (struct symbol *expelt)
{
union exp_element tmp;
- memset (&tmp, 0, sizeof (union exp_element));
+ memset (&tmp, 0, sizeof (union exp_element));
tmp.symbol = expelt;
-
write_exp_elt (tmp);
}
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);
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);
write_exp_elt_longcst (LONGEST expelt)
{
union exp_element tmp;
- memset (&tmp, 0, sizeof (union exp_element));
+ memset (&tmp, 0, sizeof (union exp_element));
tmp.longconst = expelt;
-
write_exp_elt (tmp);
}
write_exp_elt_dblcst (DOUBLEST expelt)
{
union exp_element tmp;
- memset (&tmp, 0, sizeof (union exp_element));
+ memset (&tmp, 0, sizeof (union exp_element));
tmp.doubleconst = expelt;
-
write_exp_elt (tmp);
}
write_exp_elt_type (struct type *expelt)
{
union exp_element tmp;
- memset (&tmp, 0, sizeof (union exp_element));
+ memset (&tmp, 0, sizeof (union exp_element));
tmp.type = expelt;
-
write_exp_elt (tmp);
}
write_exp_elt_intern (struct internalvar *expelt)
{
union exp_element tmp;
- memset (&tmp, 0, sizeof (union exp_element));
+ memset (&tmp, 0, sizeof (union exp_element));
tmp.internalvar = expelt;
-
write_exp_elt (tmp);
}
int
length_of_subexp (struct expression *expr, int endpos)
{
- int oplen, args, i;
+ int oplen, args;
operator_length (expr, endpos, &oplen, &args);
operator takes. */
void
-operator_length (struct expression *expr, int endpos, int *oplenp, int *argsp)
+operator_length (const 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,
+operator_length_standard (const struct expression *expr, int endpos,
int *oplenp, int *argsp)
{
int oplen = 1;
args = 1;
break;
+ case OP_ADL_FUNC:
+ oplen = longest_to_int (expr->elts[endpos - 2].longconst);
+ oplen = 4 + BYTES_TO_EXP_ELEM (oplen + 1);
+ oplen++;
+ oplen++;
+ break;
+
case OP_LABELED:
case STRUCTOP_STRUCT:
case STRUCTOP_PTR:
int args;
int i;
int *arglens;
- enum exp_opcode opcode;
int result = -1;
operator_length (inexpr, inend, &oplen, &args);
for (i = 0; i < args; i++)
{
int r;
+
oplen = arglens[i];
inend += oplen;
r = prefixify_subexp (inexpr, outexpr, inend, outbeg);
{
volatile struct gdb_exception except;
struct cleanup *old_chain;
+ const struct language_defn *lang = NULL;
int subexp;
lexptr = *stringptr;
expression_context_pc = BLOCK_START (expression_context_block);
}
+ if (language_mode == language_mode_auto && block != NULL)
+ {
+ /* Find the language associated to the given context block.
+ Default to the current language if it can not be determined.
+
+ Note that using the language corresponding to the current frame
+ can sometimes give unexpected results. For instance, this
+ routine is often called several times during the inferior
+ startup phase to re-parse breakpoint expressions after
+ a new shared library has been loaded. The language associated
+ to the current frame at this moment is not relevant for
+ the breakpoint. Using it would therefore be silly, so it seems
+ better to rely on the current language rather than relying on
+ the current frame language to parse the expression. That's why
+ we do the following language detection only if the context block
+ has been specifically provided. */
+ struct symbol *func = block_linkage_function (block);
+
+ if (func != NULL)
+ lang = language_def (SYMBOL_LANGUAGE (func));
+ if (lang == NULL || lang->la_language == language_unknown)
+ lang = current_language;
+ }
+ else
+ lang = current_language;
+
expout_size = 10;
expout_ptr = 0;
expout = (struct expression *)
xmalloc (sizeof (struct expression) + EXP_ELEM_TO_BYTES (expout_size));
- expout->language_defn = current_language;
+ expout->language_defn = lang;
expout->gdbarch = get_current_arch ();
TRY_CATCH (except, RETURN_MASK_ALL)
{
- if (current_language->la_parser ())
- current_language->la_error (NULL);
+ if (lang->la_parser ())
+ lang->la_error (NULL);
}
if (except.reason < 0)
{
if (out_subexp)
*out_subexp = subexp;
- current_language->la_post_parser (&expout, void_context_p);
+ lang->la_post_parser (&expout, void_context_p);
if (expressiondebug)
dump_prefix_expression (expout, gdb_stdlog);
parse_expression (char *string)
{
struct expression *exp;
+
exp = parse_exp_1 (&string, 0, 0);
if (*string)
error (_("Junk after end of expression."));
parser_fprintf (FILE *x, const char *y, ...)
{
va_list args;
+
va_start (args, y);
if (x == stderr)
vfprintf_unfiltered (gdb_stderr, y, args);
va_end (args);
}
+/* Implementation of the exp_descriptor method operator_check. */
+
+int
+operator_check_standard (struct expression *exp, int pos,
+ int (*objfile_func) (struct objfile *objfile,
+ void *data),
+ void *data)
+{
+ const union exp_element *const elts = exp->elts;
+ struct type *type = NULL;
+ struct objfile *objfile = NULL;
+
+ /* Extended operators should have been already handled by exp_descriptor
+ iterate method of its specific language. */
+ gdb_assert (elts[pos].opcode < OP_EXTENDED0);
+
+ /* Track the callers of write_exp_elt_type for this table. */
+
+ switch (elts[pos].opcode)
+ {
+ case BINOP_VAL:
+ case OP_COMPLEX:
+ case OP_DECFLOAT:
+ case OP_DOUBLE:
+ case OP_LONG:
+ case OP_SCOPE:
+ case OP_TYPE:
+ case UNOP_CAST:
+ case UNOP_DYNAMIC_CAST:
+ case UNOP_REINTERPRET_CAST:
+ case UNOP_MAX:
+ case UNOP_MEMVAL:
+ case UNOP_MIN:
+ type = elts[pos + 1].type;
+ break;
+
+ case TYPE_INSTANCE:
+ {
+ LONGEST arg, nargs = elts[pos + 1].longconst;
+
+ for (arg = 0; arg < nargs; arg++)
+ {
+ struct type *type = elts[pos + 2 + arg].type;
+ struct objfile *objfile = TYPE_OBJFILE (type);
+
+ if (objfile && (*objfile_func) (objfile, data))
+ return 1;
+ }
+ }
+ break;
+
+ case UNOP_MEMVAL_TLS:
+ objfile = elts[pos + 1].objfile;
+ type = elts[pos + 2].type;
+ break;
+
+ case OP_VAR_VALUE:
+ {
+ const struct block *const block = elts[pos + 1].block;
+ const struct symbol *const symbol = elts[pos + 2].symbol;
+
+ /* Check objfile where the variable itself is placed.
+ SYMBOL_OBJ_SECTION (symbol) may be NULL. */
+ if ((*objfile_func) (SYMBOL_SYMTAB (symbol)->objfile, data))
+ return 1;
+
+ /* Check objfile where is placed the code touching the variable. */
+ objfile = lookup_objfile_from_block (block);
+
+ type = SYMBOL_TYPE (symbol);
+ }
+ break;
+ }
+
+ /* Invoke callbacks for TYPE and OBJFILE if they were set as non-NULL. */
+
+ if (type && TYPE_OBJFILE (type)
+ && (*objfile_func) (TYPE_OBJFILE (type), data))
+ return 1;
+ if (objfile && (*objfile_func) (objfile, data))
+ return 1;
+
+ return 0;
+}
+
+/* Call OBJFILE_FUNC for any TYPE and OBJFILE found being referenced by EXP.
+ The functions are never called with NULL OBJFILE. Functions get passed an
+ arbitrary caller supplied DATA pointer. If any of the functions returns
+ non-zero value then (any other) non-zero value is immediately returned to
+ the caller. Otherwise zero is returned after iterating through whole EXP.
+ */
+
+static int
+exp_iterate (struct expression *exp,
+ int (*objfile_func) (struct objfile *objfile, void *data),
+ void *data)
+{
+ int endpos;
+
+ for (endpos = exp->nelts; endpos > 0; )
+ {
+ int pos, args, oplen = 0;
+
+ operator_length (exp, endpos, &oplen, &args);
+ gdb_assert (oplen > 0);
+
+ pos = endpos - oplen;
+ if (exp->language_defn->la_exp_desc->operator_check (exp, pos,
+ objfile_func, data))
+ return 1;
+
+ endpos = pos;
+ }
+
+ return 0;
+}
+
+/* Helper for exp_uses_objfile. */
+
+static int
+exp_uses_objfile_iter (struct objfile *exp_objfile, void *objfile_voidp)
+{
+ struct objfile *objfile = objfile_voidp;
+
+ if (exp_objfile->separate_debug_objfile_backlink)
+ exp_objfile = exp_objfile->separate_debug_objfile_backlink;
+
+ return exp_objfile == objfile;
+}
+
+/* Return 1 if EXP uses OBJFILE (and will become dangling when OBJFILE
+ is unloaded), otherwise return 0. OBJFILE must not be a separate debug info
+ file. */
+
+int
+exp_uses_objfile (struct expression *exp, struct objfile *objfile)
+{
+ gdb_assert (objfile->separate_debug_objfile_backlink == NULL);
+
+ return exp_iterate (exp, exp_uses_objfile_iter, objfile);
+}
+
void
_initialize_parse (void)
{
NULL,
show_expressiondebug,
&setdebuglist, &showdebuglist);
+ add_setshow_boolean_cmd ("parser", class_maintenance,
+ &parser_debug, _("\
+Set parser debugging."), _("\
+Show parser debugging."), _("\
+When non-zero, expression parser tracing will be enabled."),
+ NULL,
+ show_parserdebug,
+ &setdebuglist, &showdebuglist);
}