diff options
-rw-r--r-- | gdb/ChangeLog | 5 | ||||
-rw-r--r-- | gdb/c-exp.h | 46 | ||||
-rw-r--r-- | gdb/c-lang.c | 126 |
3 files changed, 177 insertions, 0 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 5eb9dca..5dd7666 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,10 @@ 2021-03-08 Tom Tromey <tom@tromey.com> + * c-lang.c (c_string_operation::evaluate): New method. + * c-exp.h: New file. + +2021-03-08 Tom Tromey <tom@tromey.com> + * expop.h (class ternop_cond_operation): New. * ax-gdb.c (ternop_cond_operation::do_generate_ax): New method. diff --git a/gdb/c-exp.h b/gdb/c-exp.h new file mode 100644 index 0000000..5558a77 --- /dev/null +++ b/gdb/c-exp.h @@ -0,0 +1,46 @@ +/* Definitions for C expressions + + Copyright (C) 2020 Free Software Foundation, Inc. + + 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 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. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#ifndef C_EXP_H +#define C_EXP_H + +#include "expop.h" + +namespace expr +{ + +class c_string_operation + : public tuple_holding_operation<enum c_string_type_values, + std::vector<std::string>> +{ +public: + + using tuple_holding_operation::tuple_holding_operation; + + value *evaluate (struct type *expect_type, + struct expression *exp, + enum noside noside) override; + + enum exp_opcode opcode () const override + { return OP_STRING; } +}; + +}/* namespace expr */ + +#endif /* C_EXP_H */ diff --git a/gdb/c-lang.c b/gdb/c-lang.c index 16ff3c7..d191d07 100644 --- a/gdb/c-lang.c +++ b/gdb/c-lang.c @@ -37,6 +37,7 @@ #include "gdbcore.h" #include "gdbarch.h" #include "compile/compile-internal.h" +#include "c-exp.h" /* Given a C string type, STR_TYPE, return the corresponding target character set name. */ @@ -728,6 +729,131 @@ evaluate_subexp_c (struct type *expect_type, struct expression *exp, } return evaluate_subexp_standard (expect_type, exp, pos, noside); } + +namespace expr +{ + +value * +c_string_operation::evaluate (struct type *expect_type, + struct expression *exp, + enum noside noside) +{ + struct type *type; + struct value *result; + c_string_type dest_type; + const char *dest_charset; + int satisfy_expected = 0; + + auto_obstack output; + + dest_type = std::get<0> (m_storage); + + switch (dest_type & ~C_CHAR) + { + case C_STRING: + type = language_string_char_type (exp->language_defn, + exp->gdbarch); + break; + case C_WIDE_STRING: + type = lookup_typename (exp->language_defn, "wchar_t", NULL, 0); + break; + case C_STRING_16: + type = lookup_typename (exp->language_defn, "char16_t", NULL, 0); + break; + case C_STRING_32: + type = lookup_typename (exp->language_defn, "char32_t", NULL, 0); + break; + default: + internal_error (__FILE__, __LINE__, _("unhandled c_string_type")); + } + + /* Ensure TYPE_LENGTH is valid for TYPE. */ + check_typedef (type); + + /* If the caller expects an array of some integral type, + satisfy them. If something odder is expected, rely on the + caller to cast. */ + if (expect_type && expect_type->code () == TYPE_CODE_ARRAY) + { + struct type *element_type + = check_typedef (TYPE_TARGET_TYPE (expect_type)); + + if (element_type->code () == TYPE_CODE_INT + || element_type->code () == TYPE_CODE_CHAR) + { + type = element_type; + satisfy_expected = 1; + } + } + + dest_charset = charset_for_string_type (dest_type, exp->gdbarch); + + if (noside != EVAL_SKIP) + { + for (const std::string &item : std::get<1> (m_storage)) + parse_one_string (&output, item.c_str (), item.size (), + dest_charset, type); + } + + if (noside == EVAL_SKIP) + { + /* Return a dummy value of the appropriate type. */ + if (expect_type != NULL) + result = allocate_value (expect_type); + else if ((dest_type & C_CHAR) != 0) + result = allocate_value (type); + else + result = value_cstring ("", 0, type); + return result; + } + + if ((dest_type & C_CHAR) != 0) + { + LONGEST value; + + if (obstack_object_size (&output) != TYPE_LENGTH (type)) + error (_("Could not convert character " + "constant to target character set")); + value = unpack_long (type, (gdb_byte *) obstack_base (&output)); + result = value_from_longest (type, value); + } + else + { + int i; + + /* Write the terminating character. */ + for (i = 0; i < TYPE_LENGTH (type); ++i) + obstack_1grow (&output, 0); + + if (satisfy_expected) + { + LONGEST low_bound, high_bound; + int element_size = TYPE_LENGTH (type); + + if (!get_discrete_bounds (expect_type->index_type (), + &low_bound, &high_bound)) + { + low_bound = 0; + high_bound = (TYPE_LENGTH (expect_type) / element_size) - 1; + } + if (obstack_object_size (&output) / element_size + > (high_bound - low_bound + 1)) + error (_("Too many array elements")); + + result = allocate_value (expect_type); + memcpy (value_contents_raw (result), obstack_base (&output), + obstack_object_size (&output)); + } + else + result = value_cstring ((const char *) obstack_base (&output), + obstack_object_size (&output), + type); + } + return result; +} + +} /* namespace expr */ + /* See c-lang.h. */ |