+/* Print single argument of inferior function. ARG must be already
+ read in.
+
+ Errors are printed as if they would be the parameter value. Use zeroed ARG
+ iff it should not be printed accoring to user settings. */
+
+static void
+print_frame_arg (const frame_print_options &fp_opts,
+ const struct frame_arg *arg)
+{
+ struct ui_out *uiout = current_uiout;
+
+ string_file stb;
+
+ gdb_assert (!arg->val || !arg->error);
+ gdb_assert (arg->entry_kind == print_entry_values_no
+ || arg->entry_kind == print_entry_values_only
+ || (!uiout->is_mi_like_p ()
+ && arg->entry_kind == print_entry_values_compact));
+
+ annotate_arg_emitter arg_emitter;
+ ui_out_emit_tuple tuple_emitter (uiout, NULL);
+ fprintf_symbol_filtered (&stb, SYMBOL_PRINT_NAME (arg->sym),
+ SYMBOL_LANGUAGE (arg->sym), DMGL_PARAMS | DMGL_ANSI);
+ if (arg->entry_kind == print_entry_values_compact)
+ {
+ /* It is OK to provide invalid MI-like stream as with
+ PRINT_ENTRY_VALUE_COMPACT we never use MI. */
+ stb.puts ("=");
+
+ fprintf_symbol_filtered (&stb, SYMBOL_PRINT_NAME (arg->sym),
+ SYMBOL_LANGUAGE (arg->sym),
+ DMGL_PARAMS | DMGL_ANSI);
+ }
+ if (arg->entry_kind == print_entry_values_only
+ || arg->entry_kind == print_entry_values_compact)
+ stb.puts ("@entry");
+ uiout->field_stream ("name", stb, ui_out_style_kind::VARIABLE);
+ annotate_arg_name_end ();
+ uiout->text ("=");
+
+ if (!arg->val && !arg->error)
+ uiout->text ("...");
+ else
+ {
+ if (arg->error)
+ stb.printf (_("<error reading variable: %s>"), arg->error);
+ else
+ {
+ try
+ {
+ const struct language_defn *language;
+ struct value_print_options vp_opts;
+
+ /* Avoid value_print because it will deref ref parameters. We
+ just want to print their addresses. Print ??? for args whose
+ address we do not know. We pass 2 as "recurse" to val_print
+ because our standard indentation here is 4 spaces, and
+ val_print indents 2 for each recurse. */
+
+ annotate_arg_value (value_type (arg->val));
+
+ /* Use the appropriate language to display our symbol, unless the
+ user forced the language to a specific language. */
+ if (language_mode == language_mode_auto)
+ language = language_def (SYMBOL_LANGUAGE (arg->sym));
+ else
+ language = current_language;
+
+ get_no_prettyformat_print_options (&vp_opts);
+ vp_opts.deref_ref = 1;
+ vp_opts.raw = fp_opts.print_raw_frame_arguments;
+
+ /* True in "summary" mode, false otherwise. */
+ vp_opts.summary
+ = fp_opts.print_frame_arguments == print_frame_arguments_scalars;
+
+ common_val_print (arg->val, &stb, 2, &vp_opts, language);
+ }
+ catch (const gdb_exception_error &except)
+ {
+ stb.printf (_("<error reading variable: %s>"),
+ except.what ());
+ }
+ }
+ }
+
+ uiout->field_stream ("value", stb);
+}
+
+/* Read in inferior function local SYM at FRAME into ARGP. Caller is
+ responsible for xfree of ARGP->ERROR. This function never throws an
+ exception. */
+
+void
+read_frame_local (struct symbol *sym, struct frame_info *frame,
+ struct frame_arg *argp)
+{
+ argp->sym = sym;
+ argp->val = NULL;
+ argp->error = NULL;
+
+ try
+ {
+ argp->val = read_var_value (sym, NULL, frame);
+ }
+ catch (const gdb_exception_error &except)
+ {
+ argp->error = xstrdup (except.what ());
+ }
+}
+
+/* Read in inferior function parameter SYM at FRAME into ARGP. Caller is
+ responsible for xfree of ARGP->ERROR. This function never throws an
+ exception. */
+
+void
+read_frame_arg (const frame_print_options &fp_opts,
+ symbol *sym, frame_info *frame,
+ struct frame_arg *argp, struct frame_arg *entryargp)
+{
+ struct value *val = NULL, *entryval = NULL;
+ char *val_error = NULL, *entryval_error = NULL;
+ int val_equal = 0;
+
+ if (fp_opts.print_entry_values != print_entry_values_only
+ && fp_opts.print_entry_values != print_entry_values_preferred)
+ {
+ try
+ {
+ val = read_var_value (sym, NULL, frame);
+ }
+ catch (const gdb_exception_error &except)
+ {
+ val_error = (char *) alloca (except.message->size () + 1);
+ strcpy (val_error, except.what ());
+ }
+ }
+
+ if (SYMBOL_COMPUTED_OPS (sym) != NULL
+ && SYMBOL_COMPUTED_OPS (sym)->read_variable_at_entry != NULL
+ && fp_opts.print_entry_values != print_entry_values_no
+ && (fp_opts.print_entry_values != print_entry_values_if_needed
+ || !val || value_optimized_out (val)))
+ {
+ try
+ {
+ const struct symbol_computed_ops *ops;
+
+ ops = SYMBOL_COMPUTED_OPS (sym);
+ entryval = ops->read_variable_at_entry (sym, frame);
+ }
+ catch (const gdb_exception_error &except)
+ {
+ if (except.error != NO_ENTRY_VALUE_ERROR)
+ {
+ entryval_error = (char *) alloca (except.message->size () + 1);
+ strcpy (entryval_error, except.what ());
+ }
+ }
+
+ if (entryval != NULL && value_optimized_out (entryval))
+ entryval = NULL;
+
+ if (fp_opts.print_entry_values == print_entry_values_compact
+ || fp_opts.print_entry_values == print_entry_values_default)
+ {
+ /* For MI do not try to use print_entry_values_compact for ARGP. */
+
+ if (val && entryval && !current_uiout->is_mi_like_p ())
+ {
+ struct type *type = value_type (val);
+
+ if (value_lazy (val))
+ value_fetch_lazy (val);
+ if (value_lazy (entryval))
+ value_fetch_lazy (entryval);
+
+ if (value_contents_eq (val, 0, entryval, 0, TYPE_LENGTH (type)))
+ {
+ /* Initialize it just to avoid a GCC false warning. */
+ struct value *val_deref = NULL, *entryval_deref;
+
+ /* DW_AT_call_value does match with the current
+ value. If it is a reference still try to verify if
+ dereferenced DW_AT_call_data_value does not differ. */
+
+ try
+ {
+ struct type *type_deref;
+
+ val_deref = coerce_ref (val);
+ if (value_lazy (val_deref))
+ value_fetch_lazy (val_deref);
+ type_deref = value_type (val_deref);
+
+ entryval_deref = coerce_ref (entryval);
+ if (value_lazy (entryval_deref))
+ value_fetch_lazy (entryval_deref);
+
+ /* If the reference addresses match but dereferenced
+ content does not match print them. */
+ if (val != val_deref
+ && value_contents_eq (val_deref, 0,
+ entryval_deref, 0,
+ TYPE_LENGTH (type_deref)))
+ val_equal = 1;
+ }
+ catch (const gdb_exception_error &except)
+ {
+ /* If the dereferenced content could not be
+ fetched do not display anything. */
+ if (except.error == NO_ENTRY_VALUE_ERROR)
+ val_equal = 1;
+ else if (except.message != NULL)
+ {
+ entryval_error
+ = (char *) alloca (except.message->size () + 1);
+ strcpy (entryval_error, except.what ());
+ }
+ }
+
+ /* Value was not a reference; and its content matches. */
+ if (val == val_deref)
+ val_equal = 1;
+
+ if (val_equal)
+ entryval = NULL;
+ }
+ }
+
+ /* Try to remove possibly duplicate error message for ENTRYARGP even
+ in MI mode. */
+
+ if (val_error && entryval_error
+ && strcmp (val_error, entryval_error) == 0)
+ {
+ entryval_error = NULL;
+
+ /* Do not se VAL_EQUAL as the same error message may be shown for
+ the entry value even if no entry values are present in the
+ inferior. */
+ }
+ }
+ }
+
+ if (entryval == NULL)
+ {
+ if (fp_opts.print_entry_values == print_entry_values_preferred)
+ {
+ gdb_assert (val == NULL);
+
+ try
+ {
+ val = read_var_value (sym, NULL, frame);
+ }
+ catch (const gdb_exception_error &except)
+ {
+ val_error = (char *) alloca (except.message->size () + 1);
+ strcpy (val_error, except.what ());
+ }
+ }
+ if (fp_opts.print_entry_values == print_entry_values_only
+ || fp_opts.print_entry_values == print_entry_values_both
+ || (fp_opts.print_entry_values == print_entry_values_preferred
+ && (!val || value_optimized_out (val))))
+ {
+ entryval = allocate_optimized_out_value (SYMBOL_TYPE (sym));
+ entryval_error = NULL;
+ }
+ }
+ if ((fp_opts.print_entry_values == print_entry_values_compact
+ || fp_opts.print_entry_values == print_entry_values_if_needed
+ || fp_opts.print_entry_values == print_entry_values_preferred)
+ && (!val || value_optimized_out (val)) && entryval != NULL)
+ {
+ val = NULL;
+ val_error = NULL;
+ }
+
+ argp->sym = sym;
+ argp->val = val;
+ argp->error = val_error ? xstrdup (val_error) : NULL;
+ if (!val && !val_error)
+ argp->entry_kind = print_entry_values_only;
+ else if ((fp_opts.print_entry_values == print_entry_values_compact
+ || fp_opts.print_entry_values == print_entry_values_default)
+ && val_equal)
+ {
+ argp->entry_kind = print_entry_values_compact;
+ gdb_assert (!current_uiout->is_mi_like_p ());
+ }
+ else
+ argp->entry_kind = print_entry_values_no;
+
+ entryargp->sym = sym;
+ entryargp->val = entryval;
+ entryargp->error = entryval_error ? xstrdup (entryval_error) : NULL;
+ if (!entryval && !entryval_error)
+ entryargp->entry_kind = print_entry_values_no;
+ else
+ entryargp->entry_kind = print_entry_values_only;
+}
+