public inbox for gdb-cvs@sourceware.org help / color / mirror / Atom feed
From: Tom Tromey <tromey@sourceware.org> To: gdb-cvs@sourceware.org Subject: [binutils-gdb] Rewrite make-target-delegates in Python Date: Wed, 2 Mar 2022 16:11:58 +0000 (GMT) [thread overview] Message-ID: <20220302161158.11D043857827@sourceware.org> (raw) https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=fb079cb5c419e03d400a0a139c3ccc4eedc33bef commit fb079cb5c419e03d400a0a139c3ccc4eedc33bef Author: Tom Tromey <tromey@adacore.com> Date: Mon Feb 14 10:19:06 2022 -0700 Rewrite make-target-delegates in Python I think gdb is probably better off having fewer languages involved when generating code. 'sh' is unavoidable for build-time generation, but for other things, let's use Python. This rewrites make-target-delegates in Python. I've stuck pretty closely to the original code in this rewrite, so it may look slightly weird from a Python perspective. The only output difference is that a copyright header is now generated, using the code introduced in the previous patch. make-target-delegates.py is simpler to invoke, as it knows the correct input file to scan and it creates the output file itself. Diff: --- gdb/make-target-delegates | 421 ------------------------------------------- gdb/make-target-delegates.py | 340 ++++++++++++++++++++++++++++++++++ gdb/target-delegates.c | 26 ++- 3 files changed, 363 insertions(+), 424 deletions(-) diff --git a/gdb/make-target-delegates b/gdb/make-target-delegates deleted file mode 100755 index f759b5507ca..00000000000 --- a/gdb/make-target-delegates +++ /dev/null @@ -1,421 +0,0 @@ -#!/usr/bin/perl - -# Copyright (C) 2013-2022 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/>. - - -# Usage: -# make-target-delegates target.h > target-delegates.c - -# The line we search for in target.h that marks where we should start -# looking for methods. -$TRIGGER = qr,^struct target_ops$,; -# The end of the methods part. -$ENDER = qr,^\s*};$,; - -# Match a C symbol. -$SYMBOL = qr,[a-zA-Z_][a-zA-Z0-9_]*,; -# Match the name part of a method in struct target_ops. -$NAME_PART = qr,(?<name>${SYMBOL}+)\s,; -# Match the arguments to a method. -$ARGS_PART = qr,(?<args>\(.*\)),; -# We strip the indentation so here we only need the caret. -$INTRO_PART = qr,^,; - -$POINTER_PART = qr,\s*(\*)?\s*,; - -# Match a C++ symbol, including scope operators and template -# parameters. E.g., 'std::vector<something>'. -$CP_SYMBOL = qr,[a-zA-Z_][a-zA-Z0-9_<>:]*,; -# Match the return type when it is "ordinary". -$SIMPLE_RETURN_PART = qr,((struct|class|enum|union)\s+)?${CP_SYMBOL}+,; - -# Match a return type. -$RETURN_PART = qr,((const|volatile)\s+)?(${SIMPLE_RETURN_PART})${POINTER_PART},; - -# Match "virtual". -$VIRTUAL_PART = qr,virtual\s,; - -# Match the TARGET_DEFAULT_* attribute for a method. -$TARGET_DEFAULT_PART = qr,TARGET_DEFAULT_(?<style>[A-Z_]+)\s*\((?<default_arg>.*)\),; - -# Match the arguments and trailing attribute of a method definition. -# Note we don't match the trailing ";". -$METHOD_TRAILER = qr,\s*${TARGET_DEFAULT_PART}$,; - -# Match an entire method definition. -$METHOD = ($INTRO_PART . $VIRTUAL_PART . "(?<return_type>" . $RETURN_PART . ")" - . $NAME_PART . $ARGS_PART - . $METHOD_TRAILER); - -# Match TARGET_DEBUG_PRINTER in an argument type. -# This must match the whole "sub-expression" including the parens. -# Reference $1 must refer to the function argument. -$TARGET_DEBUG_PRINTER = qr,\s*TARGET_DEBUG_PRINTER\s*\(([^)]*)\)\s*,; - -sub trim($) { - my ($result) = @_; - - $result =~ s,^\s+,,; - $result =~ s,\s+$,,; - - return $result; -} - -# Read from the input files until we find the trigger line. -# Die if not found. -sub find_trigger() { - while (<>) { - chomp; - return if m/$TRIGGER/; - } - - die "could not find trigger line\n"; -} - -# Scan target.h and return a list of possible target_ops method entries. -sub scan_target_h() { - my $all_the_text = ''; - - find_trigger(); - while (<>) { - chomp; - # Skip the open brace. - next if /{/; - last if m/$ENDER/; - - # Strip // comments. - $_ =~ s,//.*$,,; - - $all_the_text .= $_; - } - - # Now strip out the C comments. - $all_the_text =~ s,/\*(.*?)\*/,,g; - - # Replace sequences of tabs and/or whitespace with a single - # whitespace character. We need the whitespace because the method - # may have been split between multiple lines, like e.g.: - # - # virtual std::vector<long_type_name> - # my_long_method_name () - # TARGET_DEFAULT_IGNORE (); - # - # If we didn't preserve the whitespace, then we'd end up with: - # - # virtual std::vector<long_type_name>my_long_method_name ()TARGET_DEFAULT_IGNORE () - # - # ... which wouldn't later be parsed correctly. - $all_the_text =~ s/[\t\s]+/ /g; - - return split (/;/, $all_the_text); -} - -# Parse arguments into a list. -sub parse_argtypes($) { - my ($typestr) = @_; - - $typestr =~ s/^\((.*)\)$/\1/; - - my (@typelist) = split (/,\s*/, $typestr); - my (@result, $iter, $onetype); - - foreach $iter (@typelist) { - if ($iter =~ m/^(enum\s+${SYMBOL}\s*)(${SYMBOL})?$/) { - $onetype = $1; - } elsif ($iter =~ m/^(.*(enum\s+)?${SYMBOL}.*(\s|\*|&))${SYMBOL}+$/) { - $onetype = $1; - } elsif ($iter eq 'void') { - next; - } else { - $onetype = $iter; - } - push @result, trim ($onetype); - } - - return @result; -} - -sub dname($) { - my ($name) = @_; - return "target_ops::" . $name; -} - -# Write function header given name, return type, and argtypes. -# Returns a list of actual argument names. -sub write_function_header($$$@) { - my ($decl, $name, $return_type, @argtypes) = @_; - - print $return_type; - - if ($decl) { - if ($return_type !~ m,\*$,) { - print " "; - } - } else { - print "\n"; - } - - print $name . ' ('; - - my $iter; - my @argdecls; - my @actuals; - my $i = 0; - foreach $iter (@argtypes) { - my $val = $iter; - - $val =~ s/$TARGET_DEBUG_PRINTER//; - - if ($iter !~ m,(\*|&)$,) { - $val .= ' '; - } - - my $vname; - $vname .= "arg$i"; - $val .= $vname; - - push @argdecls, $val; - push @actuals, $vname; - ++$i; - } - - print join (', ', @argdecls) . ")"; - - if ($decl) { - print " override;\n"; - } else { - print "\n{\n"; - } - - return @actuals; -} - -# Write out a declaration. -sub write_declaration($$@) { - my ($name, $return_type, @argtypes) = @_; - - write_function_header (1, $name, $return_type, @argtypes); -} - -# Write out a delegation function. -sub write_delegator($$@) { - my ($name, $return_type, @argtypes) = @_; - - my (@names) = write_function_header (0, dname ($name), - $return_type, @argtypes); - - print " "; - if ($return_type ne 'void') { - print "return "; - } - print "this->beneath ()->" . $name . " ("; - print join (', ', @names); - print ");\n"; - print "}\n\n"; -} - -sub tdname ($) { - my ($name) = @_; - return "dummy_target::" . $name; -} - -# Write out a default function. -sub write_tdefault($$$$@) { - my ($content, $style, $name, $return_type, @argtypes) = @_; - - my (@names) = write_function_header (0, tdname ($name), - $return_type, @argtypes); - - if ($style eq 'FUNC') { - print " "; - if ($return_type ne 'void') { - print "return "; - } - print $content . " (this"; - if (@names) { - print ", "; - } - print join (', ', @names); - print ");\n"; - } elsif ($style eq 'RETURN') { - print " return $content;\n"; - } elsif ($style eq 'NORETURN') { - print " $content;\n"; - } elsif ($style eq 'IGNORE') { - # Nothing. - } else { - die "unrecognized style: $style\n"; - } - - print "}\n\n"; - - return tdname ($name); -} - -sub munge_type($) { - my ($typename) = @_; - my ($result); - - if ($typename =~ m/$TARGET_DEBUG_PRINTER/) { - $result = $1; - } else { - ($result = $typename) =~ s/\s+$//; - $result =~ s/[ ()<>:]/_/g; - $result =~ s/[*]/p/g; - $result =~ s/&/r/g; - - # Identifers with double underscores are reserved to the C++ - # implementation. - $result =~ s/_+/_/g; - - # Avoid ending the function name with underscore, for - # cosmetics. Trailing underscores appear after munging types - # with template parameters, like e.g. "foo<int>". - $result =~ s/_$//g; - - $result = 'target_debug_print_' . $result; - } - - return $result; -} - -# Write out a debug method. -sub write_debugmethod($$$@) { - my ($content, $name, $return_type, @argtypes) = @_; - - my ($debugname) = "debug_target::" . $name; - my ($targetname) = $name; - - my (@names) = write_function_header (0, $debugname, $return_type, @argtypes); - - if ($return_type ne 'void') { - print " $return_type result;\n"; - } - - print " fprintf_unfiltered (gdb_stdlog, \"-> %s->$name (...)\\n\", this->beneath ()->shortname ());\n"; - - # Delegate to the beneath target. - print " "; - if ($return_type ne 'void') { - print "result = "; - } - print "this->beneath ()->" . $name . " ("; - print join (', ', @names); - print ");\n"; - - # Now print the arguments. - print " fprintf_unfiltered (gdb_stdlog, \"<- %s->$name (\", this->beneath ()->shortname ());\n"; - for my $i (0 .. $#argtypes) { - if ($i > 0) { - print " fputs_unfiltered (\", \", gdb_stdlog);\n" - } - my $printer = munge_type ($argtypes[$i]); - print " $printer ($names[$i]);\n"; - } - if ($return_type ne 'void') { - print " fputs_unfiltered (\") = \", gdb_stdlog);\n"; - my $printer = munge_type ($return_type); - print " $printer (result);\n"; - print " fputs_unfiltered (\"\\n\", gdb_stdlog);\n"; - } else { - print " fputs_unfiltered (\")\\n\", gdb_stdlog);\n"; - } - - if ($return_type ne 'void') { - print " return result;\n"; - } - - print "}\n\n"; - - return $debugname; -} - -print "/* THIS FILE IS GENERATED -*- buffer-read-only: t -*- */\n"; -print "/* vi:set ro: */\n\n"; -print "/* To regenerate this file, run:*/\n"; -print "/* make-target-delegates target.h > target-delegates.c */\n"; -print "\n"; - -@lines = scan_target_h(); - -@delegators = (); -@return_types = (); -@tdefaults = (); -@styles = (); -@argtypes_array = (); - -foreach $current_line (@lines) { - # See comments in scan_target_h. Here we strip away the leading - # and trailing whitespace. - $current_line = trim ($current_line); - - next unless $current_line =~ m/$METHOD/; - - my $name = $+{name}; - my $current_line = $+{args}; - my $return_type = trim ($+{return_type}); - my $current_args = $+{args}; - my $tdefault = $+{default_arg}; - my $style = $+{style}; - - my @argtypes = parse_argtypes ($current_args); - - push @delegators, $name; - - $return_types{$name} = $return_type; - $tdefaults{$name} = $tdefault; - $styles{$name} = $style; - $argtypes_array{$name} = \@argtypes; -} - -sub print_class($) { - my ($name) = @_; - - print "struct " . $name . " : public target_ops\n"; - print "{\n"; - print " const target_info &info () const override;\n"; - print "\n"; - print " strata stratum () const override;\n"; - print "\n"; - - for $name (@delegators) { - my $return_type = $return_types{$name}; - my @argtypes = @{$argtypes_array{$name}}; - - print " "; - write_declaration ($name, $return_type, @argtypes); - } - - print "};\n\n"; -} - -print_class ("dummy_target"); -print_class ("debug_target"); - -for $name (@delegators) { - my $tdefault = $tdefaults{$name}; - my $return_type = $return_types{$name}; - my $style = $styles{$name}; - my @argtypes = @{$argtypes_array{$name}}; - - write_delegator ($name, $return_type, @argtypes); - - write_tdefault ($tdefault, $style, $name, $return_type, @argtypes); - - write_debugmethod ($tdefault, $name, $return_type, @argtypes); -} diff --git a/gdb/make-target-delegates.py b/gdb/make-target-delegates.py new file mode 100755 index 00000000000..97178072a37 --- /dev/null +++ b/gdb/make-target-delegates.py @@ -0,0 +1,340 @@ +#!/usr/bin/env python3 + +# Copyright (C) 2013-2022 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/>. + +# Usage: +# make-target-delegates.py + +import re +import gdbcopyright + + +# The line we search for in target.h that marks where we should start +# looking for methods. +TRIGGER = re.compile(r"^struct target_ops$") +# The end of the methods part. +ENDER = re.compile(r"^\s*};$") + +# Match a C symbol. +SYMBOL = "[a-zA-Z_][a-zA-Z0-9_]*" +# Match the name part of a method in struct target_ops. +NAME_PART = r"(?P<name>" + SYMBOL + ")\s" +# Match the arguments to a method. +ARGS_PART = r"(?P<args>\(.*\))" +# We strip the indentation so here we only need the caret. +INTRO_PART = r"^" + +POINTER_PART = r"\s*(\*)?\s*" + +# Match a C++ symbol, including scope operators and template +# parameters. E.g., 'std::vector<something>'. +CP_SYMBOL = r"[a-zA-Z_][a-zA-Z0-9_<>:]*" +# Match the return type when it is "ordinary". +SIMPLE_RETURN_PART = r"((struct|class|enum|union)\s+)?" + CP_SYMBOL + +# Match a return type. +RETURN_PART = r"((const|volatile)\s+)?(" + SIMPLE_RETURN_PART + ")" + POINTER_PART + +# Match "virtual". +VIRTUAL_PART = r"virtual\s" + +# Match the TARGET_DEFAULT_* attribute for a method. +TARGET_DEFAULT_PART = r"TARGET_DEFAULT_(?P<style>[A-Z_]+)\s*\((?P<default_arg>.*)\)" + +# Match the arguments and trailing attribute of a method definition. +# Note we don't match the trailing ";". +METHOD_TRAILER = r"\s*" + TARGET_DEFAULT_PART + "$" + +# Match an entire method definition. +METHOD = re.compile( + INTRO_PART + + VIRTUAL_PART + + "(?P<return_type>" + + RETURN_PART + + ")" + + NAME_PART + + ARGS_PART + + METHOD_TRAILER +) + +# Regular expression used to dissect argument types. +ARGTYPES = re.compile( + "^(" + + r"(?P<E>enum\s+" + + SYMBOL + + r"\s*)(" + + SYMBOL + + ")?" + + r"|(?P<T>.*(enum\s+)?" + + SYMBOL + + r".*(\s|\*|&))" + + SYMBOL + + ")$" +) + +# Match TARGET_DEBUG_PRINTER in an argument type. +# This must match the whole "sub-expression" including the parens. +TARGET_DEBUG_PRINTER = r"\s*TARGET_DEBUG_PRINTER\s*\((?P<arg>[^)]*)\)\s*" + + +def scan_target_h(): + found_trigger = False + all_the_text = "" + with open("target.h", "r") as target_h: + for line in target_h: + line = line.strip() + if not found_trigger: + if TRIGGER.match(line): + found_trigger = True + elif "{" in line: + # Skip the open brace. + pass + elif ENDER.match(line): + break + else: + # Strip // comments. + line = re.split("//", line)[0] + all_the_text = all_the_text + " " + line + if not found_trigger: + raise "Could not find trigger line" + # Now strip out the C comments. + all_the_text = re.sub(r"/\*(.*?)\*/", "", all_the_text) + # Replace sequences whitespace with a single space character. + # We need the space because the method may have been split + # between multiple lines, like e.g.: + # + # virtual std::vector<long_type_name> + # my_long_method_name () + # TARGET_DEFAULT_IGNORE (); + # + # If we didn't preserve the space, then we'd end up with: + # + # virtual std::vector<long_type_name>my_long_method_name ()TARGET_DEFAULT_IGNORE () + # + # ... which wouldn't later be parsed correctly. + all_the_text = re.sub(r"\s+", " ", all_the_text) + return all_the_text.split(";") + + +# Parse arguments into a list. +def parse_argtypes(typestr): + # Remove the outer parens. + typestr = re.sub(r"^\((.*)\)$", r"\1", typestr) + result = [] + for item in re.split(r",\s*", typestr): + if item == "void" or item == "": + continue + m = ARGTYPES.match(item) + if m: + if m.group("E"): + onetype = m.group("E") + else: + onetype = m.group("T") + else: + onetype = item + result.append(onetype.strip()) + return result + + +# Write function header given name, return type, and argtypes. +# Returns a list of actual argument names. +def write_function_header(f, decl, name, return_type, argtypes): + print(return_type, file=f, end="") + if decl: + if not return_type.endswith("*"): + print(" ", file=f, end="") + else: + print("", file=f) + print(name + " (", file=f, end="") + argdecls = [] + actuals = [] + for i in range(len(argtypes)): + val = re.sub(TARGET_DEBUG_PRINTER, "", argtypes[i]) + if not val.endswith("*") and not val.endswith("&"): + val = val + " " + vname = "arg" + str(i) + val = val + vname + argdecls.append(val) + actuals.append(vname) + print(", ".join(argdecls) + ")", file=f, end="") + if decl: + print(" override;", file=f) + else: + print("\n{", file=f) + return actuals + + +# Write out a declaration. +def write_declaration(f, name, return_type, argtypes): + write_function_header(f, True, name, return_type, argtypes) + + +# Write out a delegation function. +def write_delegator(f, name, return_type, argtypes): + names = write_function_header( + f, False, "target_ops::" + name, return_type, argtypes + ) + print(" ", file=f, end="") + if return_type != "void": + print("return ", file=f, end="") + print("this->beneath ()->" + name + " (", file=f, end="") + print(", ".join(names), file=f, end="") + print(");", file=f) + print("}\n", file=f) + + +# Write out a default function. +def write_tdefault(f, content, style, name, return_type, argtypes): + name = "dummy_target::" + name + names = write_function_header(f, False, name, return_type, argtypes) + if style == "FUNC": + print(" ", file=f, end="") + if return_type != "void": + print("return ", file=f, end="") + print(content + " (", file=f, end="") + names.insert(0, "this") + print(", ".join(names) + ");", file=f) + elif style == "RETURN": + print(" return " + content + ";", file=f) + elif style == "NORETURN": + print(" " + content + ";", file=f) + elif style == "IGNORE": + # Nothing. + pass + else: + raise "unrecognized style: " + style + print("}\n", file=f) + + +def munge_type(typename): + m = re.search(TARGET_DEBUG_PRINTER, typename) + if m: + return m.group("arg") + typename = typename.rstrip() + typename = re.sub("[ ()<>:]", "_", typename) + typename = re.sub("[*]", "p", typename) + typename = re.sub("&", "r", typename) + # Identifers with double underscores are reserved to the C++ + # implementation. + typename = re.sub("_+", "_", typename) + # Avoid ending the function name with underscore, for + # cosmetics. Trailing underscores appear after munging types + # with template parameters, like e.g. "foo<int>". + typename = re.sub("_+$", "", typename) + return "target_debug_print_" + typename + + +# Write out a debug method. +def write_debugmethod(f, content, name, return_type, argtypes): + debugname = "debug_target::" + name + names = write_function_header(f, False, debugname, return_type, argtypes) + if return_type != "void": + print(" " + return_type + " result;", file=f) + print( + ' fprintf_unfiltered (gdb_stdlog, "-> %s->' + + name + + ' (...)\\n", this->beneath ()->shortname ());', + file=f, + ) + + # Delegate to the beneath target. + print(" ", file=f, end="") + if return_type != "void": + print("result = ", file=f, end="") + print("this->beneath ()->" + name + " (", file=f, end="") + print(", ".join(names), file=f, end="") + print(");", file=f) + + # Now print the arguments. + print( + ' fprintf_unfiltered (gdb_stdlog, "<- %s->' + + name + + ' (", this->beneath ()->shortname ());', + file=f, + ) + for i in range(len(argtypes)): + if i > 0: + print(' fputs_unfiltered (", ", gdb_stdlog);', file=f) + printer = munge_type(argtypes[i]) + print(" " + printer + " (" + names[i] + ");", file=f) + if return_type != "void": + print(' fputs_unfiltered (") = ", gdb_stdlog);', file=f) + printer = munge_type(return_type) + print(" " + printer + " (result);", file=f) + print(' fputs_unfiltered ("\\n", gdb_stdlog);', file=f) + else: + print(' fputs_unfiltered (")\\n", gdb_stdlog);', file=f) + + if return_type != "void": + print(" return result;", file=f) + + print("}\n", file=f) + + +def print_class(f, class_name, delegators, entries): + print("struct " + class_name + " : public target_ops", file=f) + print("{", file=f) + print(" const target_info &info () const override;", file=f) + print("", file=f) + print(" strata stratum () const override;", file=f) + print("", file=f) + + for name in delegators: + return_type = entries[name]["return_type"] + argtypes = entries[name]["argtypes"] + print(" ", file=f, end="") + write_declaration(f, name, return_type, argtypes) + + print("};\n", file=f) + + +delegators = [] +entries = {} +for current_line in scan_target_h(): + # See comments in scan_target_h. Here we strip away the leading + # and trailing whitespace. + current_line = current_line.strip() + m = METHOD.match(current_line) + if not m: + continue + data = m.groupdict() + data["argtypes"] = parse_argtypes(data["args"]) + data["return_type"] = data["return_type"].strip() + entries[data["name"]] = data + + delegators.append(data["name"]) + +with open("target-delegates.c", "w") as f: + print( + gdbcopyright.copyright( + "make-target-delegates.py", "Boilerplate target methods for GDB" + ), + file=f, + ) + print_class(f, "dummy_target", delegators, entries) + print_class(f, "debug_target", delegators, entries) + + for name in delegators: + tdefault = entries[name]["default_arg"] + return_type = entries[name]["return_type"] + style = entries[name]["style"] + argtypes = entries[name]["argtypes"] + + write_delegator(f, name, return_type, argtypes) + write_tdefault(f, tdefault, style, name, return_type, argtypes) + write_debugmethod(f, tdefault, name, return_type, argtypes) diff --git a/gdb/target-delegates.c b/gdb/target-delegates.c index ca1734f86ba..fd01b640f7c 100644 --- a/gdb/target-delegates.c +++ b/gdb/target-delegates.c @@ -1,8 +1,28 @@ -/* THIS FILE IS GENERATED -*- buffer-read-only: t -*- */ +/* *INDENT-OFF* */ /* THIS FILE IS GENERATED -*- buffer-read-only: t -*- */ /* vi:set ro: */ -/* To regenerate this file, run:*/ -/* make-target-delegates target.h > target-delegates.c */ +/* Boilerplate target methods for GDB + + Copyright (C) 2013-2022 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/>. */ + +/* To regenerate this file, run: + ./make-target-delegates.py +*/ struct dummy_target : public target_ops {
reply other threads:[~2022-03-02 16:11 UTC|newest] Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20220302161158.11D043857827@sourceware.org \ --to=tromey@sourceware.org \ --cc=gdb-cvs@sourceware.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).