gdb: fix vfork with multiple threads
[deliverable/binutils-gdb.git] / gdb / m2-lang.c
index 785436c4f22bafa4d210fcf6f02e8d3633e2c37f..911d67d86721d1d665087c789fa482177077e6e6 100644 (file)
@@ -1,6 +1,6 @@
 /* Modula 2 language support routines for GDB, the GNU debugger.
 
-   Copyright (C) 1992-2020 Free Software Foundation, Inc.
+   Copyright (C) 1992-2021 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
 #include "c-lang.h"
 #include "valprint.h"
 #include "gdbarch.h"
+#include "m2-exp.h"
 
-static void m2_printchar (int, struct type *, struct ui_file *);
+/* A helper function for UNOP_HIGH.  */
 
-/* FIXME:  This is a copy of the same function from c-exp.y.  It should
-   be replaced with a true Modula version.  */
-
-static void
-m2_printchar (int c, struct type *type, struct ui_file *stream)
+struct value *
+eval_op_m2_high (struct type *expect_type, struct expression *exp,
+                enum noside noside,
+                struct value *arg1)
 {
-  fputs_filtered ("'", stream);
-  LA_EMIT_CHAR (c, type, stream, '\'');
-  fputs_filtered ("'", stream);
-}
-
-static struct value *
-evaluate_subexp_modula2 (struct type *expect_type, struct expression *exp,
-                        int *pos, enum noside noside)
-{
-  enum exp_opcode op = exp->elts[*pos].opcode;
-  struct value *arg1;
-  struct value *arg2;
-  struct type *type;
-
-  switch (op)
+  if (noside == EVAL_AVOID_SIDE_EFFECTS)
+    return arg1;
+  else
     {
-    case UNOP_HIGH:
-      (*pos)++;
-      arg1 = evaluate_subexp_with_coercion (exp, pos, noside);
-
-      if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS)
-       return arg1;
-      else
-       {
-         arg1 = coerce_ref (arg1);
-         type = check_typedef (value_type (arg1));
-
-         if (m2_is_unbounded_array (type))
-           {
-             struct value *temp = arg1;
-
-             type = type->field (1).type ();
-             /* i18n: Do not translate the "_m2_high" part!  */
-             arg1 = value_struct_elt (&temp, NULL, "_m2_high", NULL,
-                                      _("unbounded structure "
-                                        "missing _m2_high field"));
-         
-             if (value_type (arg1) != type)
-               arg1 = value_cast (type, arg1);
-           }
-       }
-      return arg1;
-
-    case BINOP_SUBSCRIPT:
-      (*pos)++;
-      arg1 = evaluate_subexp_with_coercion (exp, pos, noside);
-      arg2 = evaluate_subexp_with_coercion (exp, pos, noside);
-      if (noside == EVAL_SKIP)
-       goto nosideret;
-      /* If the user attempts to subscript something that is not an
-         array or pointer type (like a plain int variable for example),
-         then report this as an error.  */
-
       arg1 = coerce_ref (arg1);
-      type = check_typedef (value_type (arg1));
+      struct type *type = check_typedef (value_type (arg1));
 
       if (m2_is_unbounded_array (type))
        {
          struct value *temp = arg1;
-         type = type->field (0).type ();
-         if (type == NULL || (type->code () != TYPE_CODE_PTR))
-           {
-             warning (_("internal error: unbounded "
-                        "array structure is unknown"));
-             return evaluate_subexp_standard (expect_type, exp, pos, noside);
-           }
-         /* i18n: Do not translate the "_m2_contents" part!  */
-         arg1 = value_struct_elt (&temp, NULL, "_m2_contents", NULL,
+
+         type = type->field (1).type ();
+         /* i18n: Do not translate the "_m2_high" part!  */
+         arg1 = value_struct_elt (&temp, {}, "_m2_high", NULL,
                                   _("unbounded structure "
-                                    "missing _m2_contents field"));
-         
+                                    "missing _m2_high field"));
+
          if (value_type (arg1) != type)
            arg1 = value_cast (type, arg1);
-
-         check_typedef (value_type (arg1));
-         return value_ind (value_ptradd (arg1, value_as_long (arg2)));
        }
-      else
-       if (type->code () != TYPE_CODE_ARRAY)
-         {
-           if (type->name ())
-             error (_("cannot subscript something of type `%s'"),
-                    type->name ());
-           else
-             error (_("cannot subscript requested type"));
-         }
-
-      if (noside == EVAL_AVOID_SIDE_EFFECTS)
-       return value_zero (TYPE_TARGET_TYPE (type), VALUE_LVAL (arg1));
-      else
-       return value_subscript (arg1, value_as_long (arg2));
-
-    default:
-      return evaluate_subexp_standard (expect_type, exp, pos, noside);
     }
-
- nosideret:
-  return value_from_longest (builtin_type (exp->gdbarch)->builtin_int, 1);
+  return arg1;
 }
-\f
 
-/* Table of operators and their precedences for printing expressions.  */
+/* A helper function for BINOP_SUBSCRIPT.  */
 
-static const struct op_print m2_op_print_tab[] =
+struct value *
+eval_op_m2_subscript (struct type *expect_type, struct expression *exp,
+                     enum noside noside,
+                     struct value *arg1, struct value *arg2)
 {
-  {"+", BINOP_ADD, PREC_ADD, 0},
-  {"+", UNOP_PLUS, PREC_PREFIX, 0},
-  {"-", BINOP_SUB, PREC_ADD, 0},
-  {"-", UNOP_NEG, PREC_PREFIX, 0},
-  {"*", BINOP_MUL, PREC_MUL, 0},
-  {"/", BINOP_DIV, PREC_MUL, 0},
-  {"DIV", BINOP_INTDIV, PREC_MUL, 0},
-  {"MOD", BINOP_REM, PREC_MUL, 0},
-  {":=", BINOP_ASSIGN, PREC_ASSIGN, 1},
-  {"OR", BINOP_LOGICAL_OR, PREC_LOGICAL_OR, 0},
-  {"AND", BINOP_LOGICAL_AND, PREC_LOGICAL_AND, 0},
-  {"NOT", UNOP_LOGICAL_NOT, PREC_PREFIX, 0},
-  {"=", BINOP_EQUAL, PREC_EQUAL, 0},
-  {"<>", BINOP_NOTEQUAL, PREC_EQUAL, 0},
-  {"<=", BINOP_LEQ, PREC_ORDER, 0},
-  {">=", BINOP_GEQ, PREC_ORDER, 0},
-  {">", BINOP_GTR, PREC_ORDER, 0},
-  {"<", BINOP_LESS, PREC_ORDER, 0},
-  {"^", UNOP_IND, PREC_PREFIX, 0},
-  {"@", BINOP_REPEAT, PREC_REPEAT, 0},
-  {"CAP", UNOP_CAP, PREC_BUILTIN_FUNCTION, 0},
-  {"CHR", UNOP_CHR, PREC_BUILTIN_FUNCTION, 0},
-  {"ORD", UNOP_ORD, PREC_BUILTIN_FUNCTION, 0},
-  {"FLOAT", UNOP_FLOAT, PREC_BUILTIN_FUNCTION, 0},
-  {"HIGH", UNOP_HIGH, PREC_BUILTIN_FUNCTION, 0},
-  {"MAX", UNOP_MAX, PREC_BUILTIN_FUNCTION, 0},
-  {"MIN", UNOP_MIN, PREC_BUILTIN_FUNCTION, 0},
-  {"ODD", UNOP_ODD, PREC_BUILTIN_FUNCTION, 0},
-  {"TRUNC", UNOP_TRUNC, PREC_BUILTIN_FUNCTION, 0},
-  {NULL, OP_NULL, PREC_BUILTIN_FUNCTION, 0}
-};
-\f
-/* The built-in types of Modula-2.  */
-
-enum m2_primitive_types {
-  m2_primitive_type_char,
-  m2_primitive_type_int,
-  m2_primitive_type_card,
-  m2_primitive_type_real,
-  m2_primitive_type_bool,
-  nr_m2_primitive_types
-};
-
-const struct exp_descriptor exp_descriptor_modula2 = 
-{
-  print_subexp_standard,
-  operator_length_standard,
-  operator_check_standard,
-  op_name_standard,
-  dump_subexp_body_standard,
-  evaluate_subexp_modula2
-};
-
-/* Constant data describing the M2 language.  */
-
-extern const struct language_data m2_language_data =
-{
-  case_sensitive_on,
-  array_row_major,
-  macro_expansion_no,
-  &exp_descriptor_modula2,
-  m2_op_print_tab,             /* expression operators for printing */
-  &default_varobj_ops,
-};
-
-/* Class representing the M2 language.  */
-
-class m2_language : public language_defn
-{
-public:
-  m2_language ()
-    : language_defn (language_m2, m2_language_data)
-  { /* Nothing.  */ }
-
-  /* See language.h.  */
-
-  const char *name () const override
-  { return "modula-2"; }
-
-  /* See language.h.  */
+  /* If the user attempts to subscript something that is not an
+     array or pointer type (like a plain int variable for example),
+     then report this as an error.  */
 
-  const char *natural_name () const override
-  { return "Modula-2"; }
-
-  /* See language.h.  */
-  void language_arch_info (struct gdbarch *gdbarch,
-                          struct language_arch_info *lai) const override
-  {
-    const struct builtin_m2_type *builtin = builtin_m2_type (gdbarch);
-
-    lai->string_char_type = builtin->builtin_char;
-    lai->primitive_type_vector
-      = GDBARCH_OBSTACK_CALLOC (gdbarch, nr_m2_primitive_types + 1,
-                               struct type *);
-
-    lai->primitive_type_vector [m2_primitive_type_char]
-      = builtin->builtin_char;
-    lai->primitive_type_vector [m2_primitive_type_int]
-      = builtin->builtin_int;
-    lai->primitive_type_vector [m2_primitive_type_card]
-      = builtin->builtin_card;
-    lai->primitive_type_vector [m2_primitive_type_real]
-      = builtin->builtin_real;
-    lai->primitive_type_vector [m2_primitive_type_bool]
-      = builtin->builtin_bool;
-
-    lai->bool_type_symbol = "BOOLEAN";
-    lai->bool_type_default = builtin->builtin_bool;
-  }
-
-  /* See language.h.  */
-
-  void print_type (struct type *type, const char *varstring,
-                  struct ui_file *stream, int show, int level,
-                  const struct type_print_options *flags) const override
-  {
-    m2_print_type (type, varstring, stream, show, level, flags);
-  }
+  arg1 = coerce_ref (arg1);
+  struct type *type = check_typedef (value_type (arg1));
 
-  /* See language.h.  */
-
-  void value_print_inner
-       (struct value *val, struct ui_file *stream, int recurse,
-        const struct value_print_options *options) const override
-  {
-    return m2_value_print_inner (val, stream, recurse, options);
-  }
-
-  /* See language.h.  */
+  if (m2_is_unbounded_array (type))
+    {
+      struct value *temp = arg1;
+      type = type->field (0).type ();
+      if (type == NULL || (type->code () != TYPE_CODE_PTR))
+       error (_("internal error: unbounded "
+                "array structure is unknown"));
+      /* i18n: Do not translate the "_m2_contents" part!  */
+      arg1 = value_struct_elt (&temp, {}, "_m2_contents", NULL,
+                              _("unbounded structure "
+                                "missing _m2_contents field"));
+         
+      if (value_type (arg1) != type)
+       arg1 = value_cast (type, arg1);
 
-  int parser (struct parser_state *ps) const override
-  {
-    return m2_parse (ps);
-  }
+      check_typedef (value_type (arg1));
+      return value_ind (value_ptradd (arg1, value_as_long (arg2)));
+    }
+  else
+    if (type->code () != TYPE_CODE_ARRAY)
+      {
+       if (type->name ())
+         error (_("cannot subscript something of type `%s'"),
+                type->name ());
+       else
+         error (_("cannot subscript requested type"));
+      }
 
-  /* See language.h.  */
+  if (noside == EVAL_AVOID_SIDE_EFFECTS)
+    return value_zero (TYPE_TARGET_TYPE (type), VALUE_LVAL (arg1));
+  else
+    return value_subscript (arg1, value_as_long (arg2));
+}
 
-  void emitchar (int ch, struct type *chtype,
-                struct ui_file *stream, int quoter) const override
-  {
-    ch &= 0xFF;                        /* Avoid sign bit follies.  */
+\f
 
-    if (PRINT_LITERAL_FORM (ch))
-      {
-       if (ch == '\\' || ch == quoter)
-         fputs_filtered ("\\", stream);
-       fprintf_filtered (stream, "%c", ch);
-      }
-    else
-      {
-       switch (ch)
-         {
-         case '\n':
-           fputs_filtered ("\\n", stream);
-           break;
-         case '\b':
-           fputs_filtered ("\\b", stream);
-           break;
-         case '\t':
-           fputs_filtered ("\\t", stream);
-           break;
-         case '\f':
-           fputs_filtered ("\\f", stream);
-           break;
-         case '\r':
-           fputs_filtered ("\\r", stream);
-           break;
-         case '\033':
-           fputs_filtered ("\\e", stream);
-           break;
-         case '\007':
-           fputs_filtered ("\\a", stream);
-           break;
-         default:
-           fprintf_filtered (stream, "\\%.3o", (unsigned int) ch);
-           break;
-         }
-      }
-  }
+/* Single instance of the M2 language.  */
 
-  /* See language.h.  */
+static m2_language m2_language_defn;
 
-  void printchar (int ch, struct type *chtype,
-                 struct ui_file *stream) const override
-  {
-    m2_printchar (ch, chtype, stream);
-  }
+/* See language.h.  */
 
-  /* See language.h.  */
+void
+m2_language::language_arch_info (struct gdbarch *gdbarch,
+                                struct language_arch_info *lai) const
+{
+  const struct builtin_m2_type *builtin = builtin_m2_type (gdbarch);
 
-  void printstr (struct ui_file *stream, struct type *elttype,
-                const gdb_byte *string, unsigned int length,
-                const char *encoding, int force_ellipses,
-                const struct value_print_options *options) const override
+  /* Helper function to allow shorter lines below.  */
+  auto add  = [&] (struct type * t)
   {
-    unsigned int i;
-    unsigned int things_printed = 0;
-    int in_quotes = 0;
-    int need_comma = 0;
+    lai->add_primitive_type (t);
+  };
 
-    if (length == 0)
-      {
-       fputs_filtered ("\"\"", gdb_stdout);
-       return;
-      }
+  add (builtin->builtin_char);
+  add (builtin->builtin_int);
+  add (builtin->builtin_card);
+  add (builtin->builtin_real);
+  add (builtin->builtin_bool);
 
-    for (i = 0; i < length && things_printed < options->print_max; ++i)
-      {
-       /* Position of the character we are examining
-          to see whether it is repeated.  */
-       unsigned int rep1;
-       /* Number of repetitions we have detected so far.  */
-       unsigned int reps;
-
-       QUIT;
-
-       if (need_comma)
-         {
-           fputs_filtered (", ", stream);
-           need_comma = 0;
-         }
-
-       rep1 = i + 1;
-       reps = 1;
-       while (rep1 < length && string[rep1] == string[i])
-         {
-           ++rep1;
-           ++reps;
-         }
-
-       if (reps > options->repeat_count_threshold)
-         {
-           if (in_quotes)
-             {
-               fputs_filtered ("\", ", stream);
-               in_quotes = 0;
-             }
-           m2_printchar (string[i], elttype, stream);
-           fprintf_filtered (stream, " <repeats %u times>", reps);
-           i = rep1 - 1;
-           things_printed += options->repeat_count_threshold;
-           need_comma = 1;
-         }
-       else
-         {
-           if (!in_quotes)
-             {
-               fputs_filtered ("\"", stream);
-               in_quotes = 1;
-             }
-           LA_EMIT_CHAR (string[i], elttype, stream, '"');
-           ++things_printed;
-         }
-      }
+  lai->set_string_char_type (builtin->builtin_char);
+  lai->set_bool_type (builtin->builtin_bool, "BOOLEAN");
+}
 
-    /* Terminate the quotes if necessary.  */
-    if (in_quotes)
-      fputs_filtered ("\"", stream);
+/* See languge.h.  */
 
-    if (force_ellipses || i < length)
-      fputs_filtered ("...", stream);
-  }
+void
+m2_language::printchar (int c, struct type *type,
+                       struct ui_file *stream) const
+{
+  fputs_filtered ("'", stream);
+  emitchar (c, type, stream, '\'');
+  fputs_filtered ("'", stream);
+}
 
-  /* See language.h.  */
+/* See language.h.  */
 
-  void print_typedef (struct type *type, struct symbol *new_symbol,
-                     struct ui_file *stream) const override
-  {
-    m2_print_typedef (type, new_symbol, stream);
-  }
+void
+m2_language::printstr (struct ui_file *stream, struct type *elttype,
+                       const gdb_byte *string, unsigned int length,
+                       const char *encoding, int force_ellipses,
+                       const struct value_print_options *options) const
+{
+  unsigned int i;
+  unsigned int things_printed = 0;
+  int in_quotes = 0;
+  int need_comma = 0;
 
-  /* See language.h.  */
+  if (length == 0)
+    {
+      fputs_filtered ("\"\"", gdb_stdout);
+      return;
+    }
 
-  bool is_string_type_p (struct type *type) const override
-  {
-    type = check_typedef (type);
-    if (type->code () == TYPE_CODE_ARRAY
-       && TYPE_LENGTH (type) > 0
-       && TYPE_LENGTH (TYPE_TARGET_TYPE (type)) > 0)
-      {
-       struct type *elttype = check_typedef (TYPE_TARGET_TYPE (type));
+  for (i = 0; i < length && things_printed < options->print_max; ++i)
+    {
+      /* Position of the character we are examining
+        to see whether it is repeated.  */
+      unsigned int rep1;
+      /* Number of repetitions we have detected so far.  */
+      unsigned int reps;
 
-       if (TYPE_LENGTH (elttype) == 1
-           && (elttype->code () == TYPE_CODE_INT
-               || elttype->code () == TYPE_CODE_CHAR))
-         return true;
-      }
+      QUIT;
 
-    return false;
-  }
+      if (need_comma)
+       {
+         fputs_filtered (", ", stream);
+         need_comma = 0;
+       }
 
-  /* See language.h.  */
+      rep1 = i + 1;
+      reps = 1;
+      while (rep1 < length && string[rep1] == string[i])
+       {
+         ++rep1;
+         ++reps;
+       }
 
-  bool c_style_arrays_p () const override
-  { return false; }
+      if (reps > options->repeat_count_threshold)
+       {
+         if (in_quotes)
+           {
+             fputs_filtered ("\", ", stream);
+             in_quotes = 0;
+           }
+         printchar (string[i], elttype, stream);
+         fprintf_filtered (stream, " <repeats %u times>", reps);
+         i = rep1 - 1;
+         things_printed += options->repeat_count_threshold;
+         need_comma = 1;
+       }
+      else
+       {
+         if (!in_quotes)
+           {
+             fputs_filtered ("\"", stream);
+             in_quotes = 1;
+           }
+         emitchar (string[i], elttype, stream, '"');
+         ++things_printed;
+       }
+    }
 
-  /* See language.h.  Despite not having C-style arrays, Modula-2 uses 0
-     for its string lower bounds.  */
+  /* Terminate the quotes if necessary.  */
+  if (in_quotes)
+    fputs_filtered ("\"", stream);
 
-  char string_lower_bound () const override
-  { return 0; }
+  if (force_ellipses || i < length)
+    fputs_filtered ("...", stream);
+}
 
-  /* See language.h.  */
+/* See language.h.  */
 
-  bool range_checking_on_by_default () const override
-  { return true; }
-};
+void
+m2_language::emitchar (int ch, struct type *chtype,
+                      struct ui_file *stream, int quoter) const
+{
+  ch &= 0xFF;                  /* Avoid sign bit follies.  */
 
-/* Single instance of the M2 language.  */
+  if (PRINT_LITERAL_FORM (ch))
+    {
+      if (ch == '\\' || ch == quoter)
+       fputs_filtered ("\\", stream);
+      fprintf_filtered (stream, "%c", ch);
+    }
+  else
+    {
+      switch (ch)
+       {
+       case '\n':
+         fputs_filtered ("\\n", stream);
+         break;
+       case '\b':
+         fputs_filtered ("\\b", stream);
+         break;
+       case '\t':
+         fputs_filtered ("\\t", stream);
+         break;
+       case '\f':
+         fputs_filtered ("\\f", stream);
+         break;
+       case '\r':
+         fputs_filtered ("\\r", stream);
+         break;
+       case '\033':
+         fputs_filtered ("\\e", stream);
+         break;
+       case '\007':
+         fputs_filtered ("\\a", stream);
+         break;
+       default:
+         fprintf_filtered (stream, "\\%.3o", (unsigned int) ch);
+         break;
+       }
+    }
+}
 
-static m2_language m2_language_defn;
+/* Called during architecture gdbarch initialisation to create language
+   specific types.  */
 
 static void *
 build_m2_types (struct gdbarch *gdbarch)
This page took 0.029655 seconds and 4 git commands to generate.