Add c-exp.h and c_string_operation
authorTom Tromey <tom@tromey.com>
Mon, 8 Mar 2021 14:27:57 +0000 (07:27 -0700)
committerTom Tromey <tom@tromey.com>
Mon, 8 Mar 2021 14:28:17 +0000 (07:28 -0700)
This adds the new file c-exp.h, where C operation classes will be
declared.  The first such class, c_string_operation, is also added
here.

gdb/ChangeLog
2021-03-08  Tom Tromey  <tom@tromey.com>

* c-lang.c (c_string_operation::evaluate): New method.
* c-exp.h: New file.

gdb/ChangeLog
gdb/c-exp.h [new file with mode: 0644]
gdb/c-lang.c

index 5eb9dcac3e9fcfa305d9398b6356cbbbc70a1f3d..5dd766606bbef4481af340498a2cf817ebdccf31 100644 (file)
@@ -1,3 +1,8 @@
+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.
diff --git a/gdb/c-exp.h b/gdb/c-exp.h
new file mode 100644 (file)
index 0000000..5558a77
--- /dev/null
@@ -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 */
index 16ff3c7378a91461ebae259a6049855d9a61c37e..d191d07a00abb787e2f643e024d77a4fd1c2d6c4 100644 (file)
@@ -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 */
+
 \f
 /* See c-lang.h.  */