#!/usr/bin/perl
-# Copyright (C) 2013-2014 Free Software Foundation, Inc.
+# Copyright (C) 2013-2016 Free Software Foundation, Inc.
#
# This file is part of GDB.
#
$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 start of arguments to a method.
-$ARGS_PART = qr,(?<args>\(.*)$,;
-# Match indentation.
-$INTRO_PART = qr,^\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,^,;
# Match the return type when it is "ordinary".
$SIMPLE_RETURN_PART = qr,[^\(]+,;
# Match the TARGET_DEFAULT_* attribute for a method.
$TARGET_DEFAULT_PART = qr,TARGET_DEFAULT_(?<style>[A-Z_]+)\s*\((?<default_arg>.*)\),;
-# Match the introductory line to a method definition.
+# 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 . "(?<return_type>" . $SIMPLE_RETURN_PART
. "|" . $VEC_RETURN_PART . ")"
- . $NAME_PART . $ARGS_PART);
+ . $NAME_PART . $ARGS_PART
+ . $METHOD_TRAILER);
-# Match the arguments and trailing attribute of a method definition.
-$METHOD_TRAILER = qr,(?<args>\(.+\))\s*${TARGET_DEFAULT_PART};$,;
+# 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*(\S*)\s*$,\1,;
+
+ $result =~ s,^\s+,,;
+ $result =~ s,\s+$,,;
+
return $result;
}
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/;
+
+ # Just in case somebody ever uses C99.
+ $_ =~ s,//.*$,,;
+ $_ = trim ($_);
+
+ $all_the_text .= $_;
+ }
+
+ # Now strip out the C comments.
+ $all_the_text =~ s,/\*(.*?)\*/,,g;
+
+ return split (/;/, $all_the_text);
+}
+
# Parse arguments into a list.
sub parse_argtypes($) {
my ($typestr) = @_;
foreach $iter (@argtypes) {
my $val = $iter;
+ $val =~ s/$TARGET_DEBUG_PRINTER//;
+
if ($iter !~ m,\*$,) {
$val .= ' ';
}
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 = 'target_debug_print_' . $result;
+ }
+
+ return $result;
+}
+
+# Write out a debug method.
+sub write_debugmethod($$$$@) {
+ my ($content, $style, $name, $return_type, @argtypes) = @_;
+
+ my ($debugname) = $name;
+ $debugname =~ s/to_/debug_/;
+ my ($targetname) = $name;
+ $targetname =~ s/to_/target_/;
+
+ my (@names) = write_function_header ($debugname, $return_type, @argtypes);
+
+ if ($return_type ne 'void') {
+ print " $return_type result;\n";
+ }
+
+ print " fprintf_unfiltered (gdb_stdlog, \"-> %s->$name (...)\\n\", debug_target.to_shortname);\n";
+
+ # Delegate to the beneath target.
+ print " ";
+ if ($return_type ne 'void') {
+ print "result = ";
+ }
+ print "debug_target." . $name . " (";
+ my @names2 = @names;
+ @names2[0] = "&debug_target";
+ print join (', ', @names2);
+ print ");\n";
+
+ # Now print the arguments.
+ print " fprintf_unfiltered (gdb_stdlog, \"<- %s->$name (\", debug_target.to_shortname);\n";
+ for my $i (0 .. $#argtypes) {
+ print " fputs_unfiltered (\", \", gdb_stdlog);\n" if $i > 0;
+ my $printer = munge_type ($argtypes[$i]);
+ print " $printer ($names2[$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";
-find_trigger();
+@lines = scan_target_h();
+
%tdefault_names = ();
+%debug_names = ();
@delegators = ();
-$current_line = '';
-while (<>) {
- chomp;
- last if m/$ENDER/;
-
- if ($current_line ne '') {
- s/^\s*//;
- $current_line .= $_;
- } elsif (m/$METHOD/) {
- $name = $+{name};
- $current_line = $+{args};
- $return_type = trim ($+{return_type});
- }
+foreach $current_line (@lines) {
+ next unless $current_line =~ m/$METHOD/;
- if ($current_line =~ /\);\s*$/) {
- if ($current_line =~ m,$METHOD_TRAILER,) {
- $current_args = $+{args};
- $tdefault = $+{default_arg};
- $style = $+{style};
+ $name = $+{name};
+ $current_line = $+{args};
+ $return_type = trim ($+{return_type});
+ $current_args = $+{args};
+ $tdefault = $+{default_arg};
+ $style = $+{style};
- @argtypes = parse_argtypes ($current_args);
+ @argtypes = parse_argtypes ($current_args);
- # The first argument must be "this" to be delegatable.
- if ($argtypes[0] =~ /\s*struct\s+target_ops\s*\*\s*/) {
- write_delegator ($name, $return_type, @argtypes);
+ # The first argument must be "this" to be delegatable.
+ if ($argtypes[0] =~ /\s*struct\s+target_ops\s*\*\s*/) {
+ write_delegator ($name, $return_type, @argtypes);
- push @delegators, $name;
+ push @delegators, $name;
- $tdefault_names{$name} = write_tdefault ($tdefault, $style,
- $name, $return_type,
- @argtypes);
- }
- }
+ $tdefault_names{$name} = write_tdefault ($tdefault, $style,
+ $name, $return_type,
+ @argtypes);
- $current_line = '';
+ $debug_names{$name} = write_debugmethod ($tdefault, $style,
+ $name, $return_type,
+ @argtypes);
}
}
for $iter (@delegators) {
print " ops->" . $iter . " = " . $tdefault_names{$iter} . ";\n";
}
+print "}\n\n";
+
+# The debug method code.
+print "static void\ninit_debug_target (struct target_ops *ops)\n{\n";
+for $iter (@delegators) {
+ print " ops->" . $iter . " = " . $debug_names{$iter} . ";\n";
+}
print "}\n";