From 790e2a12487890559d692d60bdaefaef9b9b45b1 Mon Sep 17 00:00:00 2001 From: Andrew Burgess Date: Fri, 14 Aug 2020 14:50:48 +0100 Subject: [PATCH] gdb: move Modula2 language class into a header file Move the m2_language class from m2-lang.c into m2-lang.h. The benefit of this move is that we can remove trampoline functions. Currently the language implementation is split of different m2-* files with m2-lang.h including declaration for all the language implementation functions. Currently the m2_language class in m2-lang.c has member functions that then call the global functions declared in m2-lang.h. After this change the m2_language class is declared in m2-lang.h, and the member functions are the implementations defined in all the m2-* files. There should be no user visible changes after this commit. gdb/ChangeLog: * m2-exp.y (m2_parse): Rename to... (m2_language::parser): ...this. Update function signature. * m2-lang.c (m2_printchar): Renamed to m2_language::printchar. (m2_op_print): Rename to... (m2_language::op_print_tab): ...this, and make const. (exp_descriptor_modula2): Rename to... (m2_language::exp_descriptor_modula2): ...this. (class m2_language): Move to m2-lang.h. (m2_language::language_arch_info): New function, moved out of class declaration. (m2_language::printchar): New function, body from m2_printchar. (m2_language::printstr): New function, moved out of class declaration. (m2_language::emitchar): Likewise. * m2-lang.h (m2_parse): Delete declaration. (m2_print_typedef): Delete declaration. (m2_value_print_inner): Delete declaration. (class m2_language): Class declaration moved from m2-lang.c, larger functions are left in m2-lang.c. * m2-typeprint.c (m2_print_typedef): Rename to... (m2_language::print_typedef): ...this, and update function signature. * m2-valprint.c (m2_value_print_inner): Rename to... (m2_language::value_print_inner): ...this, replace use of LA_PRINT_STRING with a direct call to printstr member function, and update recursive call. --- gdb/ChangeLog | 29 ++++ gdb/m2-exp.y | 2 +- gdb/m2-lang.c | 402 +++++++++++++++++---------------------------- gdb/m2-lang.h | 130 +++++++++++++-- gdb/m2-typeprint.c | 4 +- gdb/m2-valprint.c | 11 +- 6 files changed, 308 insertions(+), 270 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 8de837632a6..e9ab8ec2226 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,32 @@ +2020-10-23 Andrew Burgess + + * m2-exp.y (m2_parse): Rename to... + (m2_language::parser): ...this. Update function signature. + * m2-lang.c (m2_printchar): Renamed to m2_language::printchar. + (m2_op_print): Rename to... + (m2_language::op_print_tab): ...this, and make const. + (exp_descriptor_modula2): Rename to... + (m2_language::exp_descriptor_modula2): ...this. + (class m2_language): Move to m2-lang.h. + (m2_language::language_arch_info): New function, moved out of + class declaration. + (m2_language::printchar): New function, body from m2_printchar. + (m2_language::printstr): New function, moved out of class + declaration. + (m2_language::emitchar): Likewise. + * m2-lang.h (m2_parse): Delete declaration. + (m2_print_typedef): Delete declaration. + (m2_value_print_inner): Delete declaration. + (class m2_language): Class declaration moved from m2-lang.c, + larger functions are left in m2-lang.c. + * m2-typeprint.c (m2_print_typedef): Rename to... + (m2_language::print_typedef): ...this, and update function + signature. + * m2-valprint.c (m2_value_print_inner): Rename to... + (m2_language::value_print_inner): ...this, replace use of + LA_PRINT_STRING with a direct call to printstr member function, + and update recursive call. + 2020-10-23 Andrew Burgess * language.c (default_is_string_type_p): Delete, implementation diff --git a/gdb/m2-exp.y b/gdb/m2-exp.y index c79c1f25828..5924e895c70 100644 --- a/gdb/m2-exp.y +++ b/gdb/m2-exp.y @@ -1031,7 +1031,7 @@ yylex (void) } int -m2_parse (struct parser_state *par_state) +m2_language::parser (struct parser_state *par_state) const { /* Setting up the parser state. */ scoped_restore pstate_restore = make_scoped_restore (&pstate); diff --git a/gdb/m2-lang.c b/gdb/m2-lang.c index 3cc0364b4a1..2f671eff08f 100644 --- a/gdb/m2-lang.c +++ b/gdb/m2-lang.c @@ -29,19 +29,6 @@ #include "valprint.h" #include "gdbarch.h" -static void m2_printchar (int, struct type *, struct ui_file *); - -/* 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) -{ - 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) @@ -140,7 +127,7 @@ evaluate_subexp_modula2 (struct type *expect_type, struct expression *exp, /* Table of operators and their precedences for printing expressions. */ -static const struct op_print m2_op_print_tab[] = +const struct op_print m2_language::op_print_tab[] = { {"+", BINOP_ADD, PREC_ADD, 0}, {"+", UNOP_PLUS, PREC_PREFIX, 0}, @@ -185,7 +172,7 @@ enum m2_primitive_types { nr_m2_primitive_types }; -const struct exp_descriptor exp_descriptor_modula2 = +const struct exp_descriptor m2_language::exp_descriptor_modula2 = { print_subexp_standard, operator_length_standard, @@ -195,262 +182,173 @@ const struct exp_descriptor exp_descriptor_modula2 = evaluate_subexp_modula2 }; -/* Class representing the M2 language. */ - -class m2_language : public language_defn -{ -public: - m2_language () - : language_defn (language_m2) - { /* Nothing. */ } - - /* See language.h. */ - - const char *name () const override - { return "modula-2"; } - - /* See language.h. */ - - 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); - } - - /* 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. */ - - int parser (struct parser_state *ps) const override - { - return m2_parse (ps); - } - - /* See language.h. */ - - void emitchar (int ch, struct type *chtype, - struct ui_file *stream, int quoter) const override - { - ch &= 0xFF; /* Avoid sign bit follies. */ - - 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; - } - } - } - - /* See language.h. */ - - void printchar (int ch, struct type *chtype, - struct ui_file *stream) const override - { - m2_printchar (ch, chtype, stream); - } - - /* See language.h. */ - - 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 - { - unsigned int i; - unsigned int things_printed = 0; - int in_quotes = 0; - int need_comma = 0; - - if (length == 0) - { - fputs_filtered ("\"\"", gdb_stdout); - return; - } - - 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, " ", 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; - } - } - - /* Terminate the quotes if necessary. */ - if (in_quotes) - fputs_filtered ("\"", stream); +/* Single instance of the M2 language. */ - if (force_ellipses || i < length) - fputs_filtered ("...", stream); - } +static m2_language m2_language_defn; - /* 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::language_arch_info (struct gdbarch *gdbarch, + struct language_arch_info *lai) const +{ + 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. */ +/* See languge.h. */ - 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)); +void +m2_language::printchar (int c, struct type *type, + struct ui_file *stream) const +{ + fputs_filtered ("'", stream); + emitchar (c, type, stream, '\''); + fputs_filtered ("'", stream); +} - if (TYPE_LENGTH (elttype) == 1 - && (elttype->code () == TYPE_CODE_INT - || elttype->code () == TYPE_CODE_CHAR)) - return true; - } +/* See language.h. */ - return false; - } +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 c_style_arrays_p () const override - { return false; } + 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; - /* See language.h. Despite not having C-style arrays, Modula-2 uses 0 - for its string lower bounds. */ + QUIT; - char string_lower_bound () const override - { return 0; } + 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 range_checking_on_by_default () const override - { return true; } + if (reps > options->repeat_count_threshold) + { + if (in_quotes) + { + fputs_filtered ("\", ", stream); + in_quotes = 0; + } + printchar (string[i], elttype, stream); + fprintf_filtered (stream, " ", 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. */ + /* Terminate the quotes if necessary. */ + if (in_quotes) + fputs_filtered ("\"", stream); - const struct exp_descriptor *expression_ops () const override - { return &exp_descriptor_modula2; } + if (force_ellipses || i < length) + fputs_filtered ("...", stream); +} - /* See language.h. */ +/* See language.h. */ - const struct op_print *opcode_print_table () const override - { return m2_op_print_tab; } -}; +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) diff --git a/gdb/m2-lang.h b/gdb/m2-lang.h index de477e58d5a..3cf32587030 100644 --- a/gdb/m2-lang.h +++ b/gdb/m2-lang.h @@ -23,23 +23,13 @@ struct type_print_options; struct parser_state; -extern int m2_parse (struct parser_state *); /* Defined in m2-exp.y */ - /* Defined in m2-typeprint.c */ extern void m2_print_type (struct type *, const char *, struct ui_file *, int, int, const struct type_print_options *); -extern void m2_print_typedef (struct type *, struct symbol *, - struct ui_file *); - extern int m2_is_long_set (struct type *type); extern int m2_is_unbounded_array (struct type *type); -/* Implement la_value_print_inner for Modula-2. */ - -extern void m2_value_print_inner (struct value *, struct ui_file *, int, - const struct value_print_options *); - extern int get_long_set_bounds (struct type *type, LONGEST *low, LONGEST *high); @@ -57,4 +47,124 @@ struct builtin_m2_type /* Return the Modula-2 type table for the specified architecture. */ extern const struct builtin_m2_type *builtin_m2_type (struct gdbarch *gdbarch); +/* Class representing the M2 language. */ + +class m2_language : public language_defn +{ +public: + m2_language () + : language_defn (language_m2) + { /* Nothing. */ } + + /* See language.h. */ + + const char *name () const override + { return "modula-2"; } + + /* See language.h. */ + + 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; + + /* 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); + } + + /* See language.h. */ + + void value_print_inner (struct value *val, struct ui_file *stream, + int recurse, + const struct value_print_options *options) const override; + + /* See language.h. */ + + int parser (struct parser_state *ps) const override; + + /* See language.h. */ + + void emitchar (int ch, struct type *chtype, + struct ui_file *stream, int quoter) const override; + + /* See language.h. */ + + void printchar (int ch, struct type *chtype, + struct ui_file *stream) const override; + + /* See language.h. */ + + 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; + + /* See language.h. */ + + void print_typedef (struct type *type, struct symbol *new_symbol, + struct ui_file *stream) const override; + + /* See language.h. */ + + 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)); + + if (TYPE_LENGTH (elttype) == 1 + && (elttype->code () == TYPE_CODE_INT + || elttype->code () == TYPE_CODE_CHAR)) + return true; + } + + return false; + } + + /* See language.h. */ + + bool c_style_arrays_p () const override + { return false; } + + /* See language.h. Despite not having C-style arrays, Modula-2 uses 0 + for its string lower bounds. */ + + char string_lower_bound () const override + { return 0; } + + /* See language.h. */ + + bool range_checking_on_by_default () const override + { return true; } + + /* See language.h. */ + + const struct exp_descriptor *expression_ops () const override + { return &exp_descriptor_modula2; } + + /* See language.h. */ + + const struct op_print *opcode_print_table () const override + { return op_print_tab; } + +private: + /* Table of expression handling functions for use by EXPRESSION_OPS + member function. */ + static const struct exp_descriptor exp_descriptor_modula2; + + /* Table of opcode data for use by OPCODE_PRINT_TABLE member function. */ + static const struct op_print op_print_tab[]; +}; + #endif /* M2_LANG_H */ diff --git a/gdb/m2-typeprint.c b/gdb/m2-typeprint.c index 963d12596be..dbe112c4fcc 100644 --- a/gdb/m2-typeprint.c +++ b/gdb/m2-typeprint.c @@ -158,8 +158,8 @@ m2_print_type (struct type *type, const char *varstring, which to print. */ void -m2_print_typedef (struct type *type, struct symbol *new_symbol, - struct ui_file *stream) +m2_language::print_typedef (struct type *type, struct symbol *new_symbol, + struct ui_file *stream) const { type = check_typedef (type); fprintf_filtered (stream, "TYPE "); diff --git a/gdb/m2-valprint.c b/gdb/m2-valprint.c index c285543f4bf..fdccbaf500d 100644 --- a/gdb/m2-valprint.c +++ b/gdb/m2-valprint.c @@ -298,8 +298,9 @@ static const struct generic_val_print_decorations m2_decorations = /* See m2-lang.h. */ void -m2_value_print_inner (struct value *val, struct ui_file *stream, int recurse, - const struct value_print_options *options) +m2_language::value_print_inner (struct value *val, struct ui_file *stream, + int recurse, + const struct value_print_options *options) const { unsigned len; struct type *elttype; @@ -336,8 +337,8 @@ m2_value_print_inner (struct value *val, struct ui_file *stream, int recurse, len = temp_len; } - LA_PRINT_STRING (stream, TYPE_TARGET_TYPE (type), - valaddr, len, NULL, 0, options); + printstr (stream, TYPE_TARGET_TYPE (type), valaddr, len, + NULL, 0, options); } else { @@ -445,7 +446,7 @@ m2_value_print_inner (struct value *val, struct ui_file *stream, int recurse, if (TYPE_LENGTH (type) == TYPE_LENGTH (TYPE_TARGET_TYPE (type))) { struct value *v = value_cast (TYPE_TARGET_TYPE (type), val); - m2_value_print_inner (v, stream, recurse, options); + value_print_inner (v, stream, recurse, options); break; } /* FALLTHROUGH */ -- 2.30.2