gdb/make-target-delegates - gdb

Data types defined

Source code

  1. #!/usr/bin/perl

  2. # Copyright (C) 2013-2015 Free Software Foundation, Inc.
  3. #
  4. # This file is part of GDB.
  5. #
  6. # This program is free software; you can redistribute it and/or modify
  7. # it under the terms of the GNU General Public License as published by
  8. # the Free Software Foundation; either version 3 of the License, or
  9. # (at your option) any later version.
  10. #
  11. # This program is distributed in the hope that it will be useful,
  12. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. # GNU General Public License for more details.
  15. #
  16. # You should have received a copy of the GNU General Public License
  17. # along with this program.  If not, see <http://www.gnu.org/licenses/>.


  18. # Usage:
  19. #    make-target-delegates target.h > target-delegates.c

  20. # The line we search for in target.h that marks where we should start
  21. # looking for methods.
  22. $TRIGGER = qr,^struct target_ops$,;
  23. # The end of the methods part.
  24. $ENDER = qr,^\s*};$,;

  25. # Match a C symbol.
  26. $SYMBOL = qr,[a-zA-Z_][a-zA-Z0-9_]*,;
  27. # Match the name part of a method in struct target_ops.
  28. $NAME_PART = qr,\(\*(?<name>${SYMBOL}+)\)\s,;
  29. # Match the arguments to a method.
  30. $ARGS_PART = qr,(?<args>\(.*\)),;
  31. # We strip the indentation so here we only need the caret.
  32. $INTRO_PART = qr,^,;

  33. # Match the return type when it is "ordinary".
  34. $SIMPLE_RETURN_PART = qr,[^\(]+,;
  35. # Match the return type when it is a VEC.
  36. $VEC_RETURN_PART = qr,VEC\s*\([^\)]+\)[^\(]*,;

  37. # Match the TARGET_DEFAULT_* attribute for a method.
  38. $TARGET_DEFAULT_PART = qr,TARGET_DEFAULT_(?<style>[A-Z_]+)\s*\((?<default_arg>.*)\),;

  39. # Match the arguments and trailing attribute of a method definition.
  40. # Note we don't match the trailing ";".
  41. $METHOD_TRAILER = qr,\s*${TARGET_DEFAULT_PART}$,;

  42. # Match an entire method definition.
  43. $METHOD = ($INTRO_PART . "(?<return_type>" . $SIMPLE_RETURN_PART
  44.            . "|" . $VEC_RETURN_PART . ")"
  45.            . $NAME_PART . $ARGS_PART
  46.            . $METHOD_TRAILER);

  47. # Match TARGET_DEBUG_PRINTER in an argument type.
  48. # This must match the whole "sub-expression" including the parens.
  49. # Reference $1 must refer to the function argument.
  50. $TARGET_DEBUG_PRINTER = qr,\s*TARGET_DEBUG_PRINTER\s*\(([^)]*)\)\s*,;

  51. sub trim($) {
  52.     my ($result) = @_;

  53.     $result =~ s,^\s+,,;
  54.     $result =~ s,\s+$,,;

  55.     return $result;
  56. }

  57. # Read from the input files until we find the trigger line.
  58. # Die if not found.
  59. sub find_trigger() {
  60.     while (<>) {
  61.         chomp;
  62.         return if m/$TRIGGER/;
  63.     }

  64.     die "could not find trigger line\n";
  65. }

  66. # Scan target.h and return a list of possible target_ops method entries.
  67. sub scan_target_h() {
  68.     my $all_the_text = '';

  69.     find_trigger();
  70.     while (<>) {
  71.         chomp;
  72.         # Skip the open brace.
  73.         next if /{/;
  74.         last if m/$ENDER/;

  75.         # Just in case somebody ever uses C99.
  76.         $_ =~ s,//.*$,,;
  77.         $_ = trim ($_);

  78.         $all_the_text .= $_;
  79.     }

  80.     # Now strip out the C comments.
  81.     $all_the_text =~ s,/\*(.*?)\*/,,g;

  82.     return split (/;/, $all_the_text);
  83. }

  84. # Parse arguments into a list.
  85. sub parse_argtypes($) {
  86.     my ($typestr) = @_;

  87.     $typestr =~ s/^\((.*)\)$/\1/;

  88.     my (@typelist) = split (/,\s*/, $typestr);
  89.     my (@result, $iter, $onetype);

  90.     foreach $iter (@typelist) {
  91.         if ($iter =~ m/^(enum\s+${SYMBOL}\s*)(${SYMBOL})?$/) {
  92.             $onetype = $1;
  93.         } elsif ($iter =~ m/^(.*(enum\s+)?${SYMBOL}.*(\s|\*))${SYMBOL}+$/) {
  94.             $onetype = $1;
  95.         } elsif ($iter eq 'void') {
  96.             next;
  97.         } else {
  98.             $onetype = $iter;
  99.         }
  100.         push @result, trim ($onetype);
  101.     }

  102.     return @result;
  103. }

  104. sub dname($) {
  105.     my ($name) = @_;
  106.     $name =~ s/to_/delegate_/;
  107.     return $name;
  108. }

  109. # Write function header given name, return type, and argtypes.
  110. # Returns a list of actual argument names.
  111. sub write_function_header($$@) {
  112.     my ($name, $return_type, @argtypes) = @_;

  113.     print "static " . $return_type . "\n";
  114.     print $name . ' (';

  115.     my $iter;
  116.     my @argdecls;
  117.     my @actuals;
  118.     my $i = 0;
  119.     foreach $iter (@argtypes) {
  120.         my $val = $iter;

  121.         $val =~ s/$TARGET_DEBUG_PRINTER//;

  122.         if ($iter !~ m,\*$,) {
  123.             $val .= ' ';
  124.         }

  125.         my $vname;
  126.         if ($i == 0) {
  127.             # Just a random nicety.
  128.             $vname = 'self';
  129.         } else {
  130.             $vname .= "arg$i";
  131.         }
  132.         $val .= $vname;

  133.         push @argdecls, $val;
  134.         push @actuals, $vname;
  135.         ++$i;
  136.     }

  137.     print join (', ', @argdecls) . ")\n";
  138.     print "{\n";

  139.     return @actuals;
  140. }

  141. # Write out a delegation function.
  142. sub write_delegator($$@) {
  143.     my ($name, $return_type, @argtypes) = @_;

  144.     my (@names) = write_function_header (dname ($name), $return_type,
  145.                                          @argtypes);

  146.     print $names[0] = $names[0]->beneath;\n";
  147.     print "  ";
  148.     if ($return_type ne 'void') {
  149.         print "return ";
  150.     }
  151.     print "$names[0]->" . $name . " (";
  152.     print join (', ', @names);
  153.     print ");\n";
  154.     print "}\n\n";
  155. }

  156. sub tdname ($) {
  157.     my ($name) = @_;
  158.     $name =~ s/to_/tdefault_/;
  159.     return $name;
  160. }

  161. # Write out a default function.
  162. sub write_tdefault($$$$@) {
  163.     my ($content, $style, $name, $return_type, @argtypes) = @_;

  164.     if ($style eq 'FUNC') {
  165.         return $content;
  166.     }

  167.     write_function_header (tdname ($name), $return_type, @argtypes);

  168.     if ($style eq 'RETURN') {
  169.         print "  return $content;\n";
  170.     } elsif ($style eq 'NORETURN') {
  171.         print $content;\n";
  172.     } elsif ($style eq 'IGNORE') {
  173.         # Nothing.
  174.     } else {
  175.         die "unrecognized style: $style\n";
  176.     }

  177.     print "}\n\n";

  178.     return tdname ($name);
  179. }

  180. sub munge_type($) {
  181.     my ($typename) = @_;
  182.     my ($result);

  183.     if ($typename =~ m/$TARGET_DEBUG_PRINTER/) {
  184.         $result = $1;
  185.     } else {
  186.         ($result = $typename) =~ s/\s+$//;
  187.         $result =~ s/[ ()]/_/g;
  188.         $result =~ s/[*]/p/g;
  189.         $result = 'target_debug_print_' . $result;
  190.     }

  191.     return $result;
  192. }

  193. # Write out a debug method.
  194. sub write_debugmethod($$$$@) {
  195.     my ($content, $style, $name, $return_type, @argtypes) = @_;

  196.     my ($debugname) = $name;
  197.     $debugname =~ s/to_/debug_/;
  198.     my ($targetname) = $name;
  199.     $targetname =~ s/to_/target_/;

  200.     my (@names) = write_function_header ($debugname, $return_type, @argtypes);

  201.     if ($return_type ne 'void') {
  202.         print $return_type result;\n";
  203.     }

  204.     print "  fprintf_unfiltered (gdb_stdlog, \"-> %s->$name (...)\\n\", debug_target.to_shortname);\n";

  205.     # Delegate to the beneath target.
  206.     print "  ";
  207.     if ($return_type ne 'void') {
  208.         print "result = ";
  209.     }
  210.     print "debug_target." . $name . " (";
  211.     my @names2 = @names;
  212.     @names2[0] = "&debug_target";
  213.     print join (', ', @names2);
  214.     print ");\n";

  215.     # Now print the arguments.
  216.     print "  fprintf_unfiltered (gdb_stdlog, \"<- %s->$name (\", debug_target.to_shortname);\n";
  217.     for my $i (0 .. $#argtypes) {
  218.         print "  fputs_unfiltered (\", \", gdb_stdlog);\n" if $i > 0;
  219.         my $printer = munge_type ($argtypes[$i]);
  220.         print $printer ($names2[$i]);\n";
  221.     }
  222.     if ($return_type ne 'void') {
  223.         print "  fputs_unfiltered (\") = \", gdb_stdlog);\n";
  224.         my $printer = munge_type ($return_type);
  225.         print $printer (result);\n";
  226.         print "  fputs_unfiltered (\"\\n\", gdb_stdlog);\n";
  227.     } else {
  228.         print "  fputs_unfiltered (\")\\n\", gdb_stdlog);\n";
  229.     }

  230.     if ($return_type ne 'void') {
  231.         print "  return result;\n";
  232.     }

  233.     print "}\n\n";

  234.     return $debugname;
  235. }

  236. print "/* THIS FILE IS GENERATED -*- buffer-read-only: t -*- */\n";
  237. print "/* vi:set ro: */\n\n";
  238. print "/* To regenerate this file, run:*/\n";
  239. print "/*      make-target-delegates target.h > target-delegates.c */\n";

  240. @lines = scan_target_h();


  241. %tdefault_names = ();
  242. %debug_names = ();
  243. @delegators = ();
  244. foreach $current_line (@lines) {
  245.     next unless $current_line =~ m/$METHOD/;

  246.     $name = $+{name};
  247.     $current_line = $+{args};
  248.     $return_type = trim ($+{return_type});
  249.     $current_args = $+{args};
  250.     $tdefault = $+{default_arg};
  251.     $style = $+{style};

  252.     @argtypes = parse_argtypes ($current_args);

  253.     # The first argument must be "this" to be delegatable.
  254.     if ($argtypes[0] =~ /\s*struct\s+target_ops\s*\*\s*/) {
  255.         write_delegator ($name, $return_type, @argtypes);

  256.         push @delegators, $name;

  257.         $tdefault_names{$name} = write_tdefault ($tdefault, $style,
  258.                                                  $name, $return_type,
  259.                                                  @argtypes);

  260.         $debug_names{$name} = write_debugmethod ($tdefault, $style,
  261.                                                  $name, $return_type,
  262.                                                  @argtypes);
  263.     }
  264. }

  265. # Now the delegation code.
  266. print "static void\ninstall_delegators (struct target_ops *ops)\n{\n";

  267. for $iter (@delegators) {
  268.     print "  if (ops->" . $iter . " == NULL)\n";
  269.     print "    ops->" . $iter . " = " . dname ($iter) . ";\n";
  270. }
  271. print "}\n\n";

  272. # Now the default method code.
  273. print "static void\ninstall_dummy_methods (struct target_ops *ops)\n{\n";

  274. for $iter (@delegators) {
  275.     print "  ops->" . $iter . " = " . $tdefault_names{$iter} . ";\n";
  276. }
  277. print "}\n\n";

  278. # The debug method code.
  279. print "static void\ninit_debug_target (struct target_ops *ops)\n{\n";
  280. for $iter (@delegators) {
  281.     print "  ops->" . $iter . " = " . $debug_names{$iter} . ";\n";
  282. }
  283. print "}\n";