summaryrefslogtreecommitdiffstats
path: root/perl_checker_fake_packages/gen.pl
diff options
context:
space:
mode:
Diffstat (limited to 'perl_checker_fake_packages/gen.pl')
-rwxr-xr-xperl_checker_fake_packages/gen.pl299
1 files changed, 94 insertions, 205 deletions
diff --git a/perl_checker_fake_packages/gen.pl b/perl_checker_fake_packages/gen.pl
index 6122f52..0902f54 100755
--- a/perl_checker_fake_packages/gen.pl
+++ b/perl_checker_fake_packages/gen.pl
@@ -1,216 +1,105 @@
-#!/usr/bin/perl
+#!/usr/bin/perl -w
+use strict;
use MDK::Common;
-sub gtk2 {
- my (@files) = @_;
-
- my @subroutines = (
- [ 'set_size_request', ' { my ($_self, $_x, $_y) = @_ }' ],
- [ 'set_popdown_strings', ' {}' ],
- [ 'signal_emit', ' {}' ],
- [ 'signal_emit_by_name', ' {}' ],
- [ 'signal_connect', ' { my ($_target, $_name, $_callback, $o_data) = @_ }' ],
- [ 'signal_connect_swapped', ' { my ($_target, $_name, $_callback, $o_data) = @_ }' ],
- [ 'signal_connect_after', ' { my ($_target, $_name, $_callback, $o_data) = @_ }' ],
- [ 'signal_handler_block', ' { my ($_target, $_closure) = @_ }' ],
- [ 'signal_handler_unblock', ' { my ($_target, $_closure) = @_ }' ],
- [ 'signal_disconnect', ' { my ($_target, $_closure) = @_ }' ],
- [ 'signal_is_connected', ' { my ($_target, $_closure) = @_ }' ],
- [ 'signal_stop_emission_by_name', ' { my ($_target, $_detailed_signal) = @_ }' ],
- [ 'timeout_add', ' { my ($_class, $_interval, $_func, $o_data) = @_ }' ],
- [ 'timeout_remove', ' { my ($_class, $_id) = @_ }' ],
- [ 'idle_add', ' { my ($_class, $_func, $o_data) = @_ }' ],
- [ 'idle_remove', ' { my ($_class, $_id) = @_ }' ],
- [ 'create_items', ' { my ($_factory, $_entries, $o_callback_data) = @_ }' ],
- [ 'style', ' { my ($_widget, $o_style) = @_ }' ],
- [ 'visible', ' { my ($_widget, $o_bool) = @_ }' ],
- [ 'white_gc', ' { my ($_style, $o_gc) = @_ }' ],
- [ 'black_gc', ' { my ($_style, $o_gc) = @_ }' ],
- [ 'get', ' {}' ],
- [ 'append_item', ' { my ($_self, $_text, $_tooltip, $_private, $_icon, $_callback, $o_user_data) = @_ }' ],
- [ 'toggle_expansion', ' { my ($_self, $_path, $o_open_all) = @_ }' ],
- [ 'get_path_at_pos', ' { my ($_self, $_x, $_y) = @_ }' ],
- [ 'allow_grow', ' { my ($_window, $o_bool) = @_ }' ],
- [ 'allow_shrink', ' { my ($_window, $o_bool) = @_ }' ],
- [ 'default_height', ' { my ($_window, $o_bool) = @_ }' ],
- [ 'default_width', ' { my ($_window, $o_bool) = @_ }' ],
- [ 'destroy_with_parent', ' { my ($_window, $o_bool) = @_ }' ],
- [ 'has_top_level_focus', ' { my ($_window, $o_bool) = @_ }' ],
- [ 'is_active', ' { my ($_window, $o_bool) = @_ }' ],
- [ 'modal', ' { my ($_window, $o_bool) = @_ }' ],
- [ 'resizable', ' { my ($_window, $o_bool) = @_ }' ],
- [ 'window_position', ' { my ($_window, $o_pos) = @_ }' ],
- [ 'expand_to_path', ' { my ($_treeview, $_path) = @_ }' ],
- [ 'fraction', ' { my ($_progress_bar, $o_fraction) = @_ }' ],
- [ 'orientation', ' { my ($_progress_bar, $o_orientation) = @_ }' ],
- [ 'get_selected_rows', ' { my ($_tree_selection) = @_ }' ],
- );
- my @added_subroutines;
- my $add = sub {
- member($_[0], map { $_->[0] } @subroutines) and return;
- push @added_subroutines, [ $_[0], $_[1] ];
- };
-
- my $pm_file = sub {
- my ($file) = @_;
- my @contents = cat_($file);
- each_index {
- if (/^\s*sub\s+(\w+)/) {
- my $fun = $1;
- my $line = $::i;
-
- #- obtain first statement of function
- local $_ = $_;
- if (/^\s*sub\s+\w+\s*{?\s*$/) {
- if ($contents[$::i+1] =~ /^\s*{\s*$/) {
- $_ .= $contents[++$line] . $contents[++$line];
- } else {
- $_ .= $contents[++$line];
- }
- }
-
- my $subroutine_decl = '^\s*sub\s+\w+\s*{\s*';
-
- #- one liner constants
- #- sub EXPOSURE_MASK { 'exposure-mask' }
- /$subroutine_decl('[^']+')|("[^"]+")\s*}/ and $add->($fun, '() {}');
- #- sub Sym_Hangul_J_Phieuf { 0xeed }
- /$subroutine_decl\d\S+\s*}/ and $add->($fun, '() {}');
-
- #- traditional form
- #- my ($class, $interval, $func, $data) = @_;
- if (/$subroutine_decl\my\s*\(([^\)]+)\)\s*=\s*\@_\s*;\s*$/) {
- my @args = map { /^\s*\$(.*)/ or goto skip_trad; '$_'.$1 } split /,/, $1;
- $add->($fun, ' { my ('.join(', ', @args).') = @_ }');
- skip_trad:
- }
-
- #- methods not naming arguments
- #- sub set_name { $_[0]->set_property('name', $_[1]) }
- if (/$subroutine_decl([^}]+)\s*}\s*$/) {
- my $statement = $1;
- if ($statement !~ /\$[a-zA-Z]/ && $statement !~ /\@_/ && $statement =~ /.*\$_\[(\d+)\]/) {
- $add->($fun, ' { my ('.join(', ', map { '$_DUMMY'.$_ } 0..$1).') = @_ }');
- }
- }
-
- #- methods with no argument
- #- my $values = shift->_get_size_request;
- if (/$subroutine_decl(my.*=)?\s*shift->\w+\s*((;)|(}))\s*$/) {
- $add->($fun, ' { my ($_self) = @_ }');
- }
-
- #- methods with variable list of arguments (which branch to different XS functions)
- #- Gtk2::_Helpers::check_usage(\@_, [ 'Gtk2::GSList group' ], [ 'Gtk2::GSList group', 'string label' ]);
- if (/Gtk2::_Helpers::check_usage\(\\\@_, (.*)/) {
- my $various = $1;
- while ($various !~ /\)\s*;\s*$/) {
- $various .= $contents[++$line];
- }
- $various =~ s/\)\s*;\s*$//;
-
- my $subroutine = ' { my (';
- my @various = split /\]\s*,/, $various;
- s/[\[\]]//g foreach @various;
- my @mandatory = split /,/, $various[0];
- my $proto2varname = sub { $_[0] =~ /\s*'\s*\S+\s+(.*)\s*'/; $1 };
- $subroutine .= join(', ', map { '$_'.$proto2varname->($_) } @mandatory);
- @mandatory and $subroutine .= ', ';
- my @optional = split /,/, $various[-1];
- @optional = splice @optional, @mandatory;
- $subroutine .= join(', ', map { '$o_'.$proto2varname->($_) } @optional);
- $add->($fun, "$subroutine) = \@_ }");
- }
-
- }
-
- } @contents;
- };
-
- my $c_file = sub {
- my ($file) = @_;
- my @contents = cat_($file);
- my $comment;
- each_index {
- m|/\*| and $comment = 1;
- m|\*/| and $comment = 0;
- s|/\*.*\*/||;
- s|//.*||;
- $comment and goto next_;
- /^#/ and goto next_;
- /^\s*static/ and goto next_;
- if (/^\S.*\s(\w+)\s*\((.*)/) {
- my $fun = $1;
- #- skip "internal" functions
- $fun =~ /__/ and goto next_;
- my $args = $2;
-
- #- guess function name
- $fun =~ s/^.*perl_//;
-
- my ($trimlast) = $file =~ /([A-Z]\w+)\.c$/;
- while ($trimlast =~ s/([a-z])([A-Z])/$1_$2/) {}
- $file =~ /\bGC\b/ or $trimlast =~ s/^G([A-Z])/$1/; #- glib case
- $file =~ m|Gdk/Event/src| and $trimlast = "event_$trimlast"; #- gdkevent case
- $trimlast = lc($trimlast);
- #- skip functions that will not be exported anyway because don't follow the naming scheme
- $fun =~ s/^\Q$trimlast\_// or goto next_;
-
- #- explore following lines if prototype was not complete
- my $line = $::i;
- while ($args !~ /\)/) {
- $line++;
- $args .= $contents[$line];
- }
- $args =~ s/\s+/ /g;
- $args =~ s/\).*//;
-
- my $proto2varname = sub { $_[0] =~ /(\w+)\s*$/; $1 };
- my @args = split /,/, $args;
-
- $add->($fun, ' { my (' . join(', ', map { '$_'.$proto2varname->($_) } @args) . ') = @_ }');
- }
- next_:
- } @contents;
- };
+my ($current_package, $current_prefix, $current_name);
+
+my %l;
+sub get_paras {
+ my ($name, $para) = @_;
+ $name =~ s/\Q$current_prefix//;
+ $current_name = $name;
+ $l{$current_package}{$name} = [ map {
+ if (/\Q.../) {
+ '@_more_paras';
+ } else {
+ my ($optional) = s/=(.*)//;
+ my $s = /.*\W(\w+)/ ? $1 : $_;
+ '$_' . ($optional ? 'o_' : '') . $s;
+ }
+ } grep { !/OUTLIST/ } split(',', $para) ];
+}
- foreach (@files) {
- /\.pm$/ and $pm_file->($_);
- /\.c$/ and $c_file->($_);
+sub parse_xs {
+ my ($file) = @_;
+ warn "parse_xs $file\n";
+ my $state = 'waiting_for_type';
+ ($current_package, $current_prefix) = ('', '');
+ my $multi_line;
+ foreach (cat_($file)) {
+ chomp;
+ my $orig_line = $_;
+
+ if (/^\s*#/ || (m!^\s*/\*! .. m!\*/!)) {
+ # forget it
+ } elsif ($state eq 'multi_line') {
+ if (/(.*)\)/) {
+ get_paras($current_name, $multi_line . $1);
+ $state = 'waiting_for_end';
+ } else {
+ $multi_line .= $_;
+ }
+# } elsif (/^\s*gperl_set_isa\s*\("(.*)", ".*"\)\s*;/) {
+ } elsif (/MODULE\s*=\s*\S+\s+PACKAGE\s*=\s*(\S+)\s+PREFIX\s*=\s*(\S+)/) {
+ ($current_package, $current_prefix) = ($1, $2);
+ } elsif (/MODULE\s*=\s*\S+\s+PACKAGE\s*=\s*(\S+)/) {
+ ($current_package, $current_prefix) = ($1, '');
+ } elsif (!$current_package) {
+ # waiting for the MODULE line
+ } elsif (/^\s*$/) {
+ $state = 'waiting_for_type';
+ } elsif (/^\w[^\(]*$/ && $state eq 'waiting_for_type') {
+ $state = 'waiting_for_function' if !/^BOOT:/ && !/;/;
+ } elsif (/^\s*ALIAS:\s*$/) {
+ $state = 'alias';
+ } elsif ($state eq 'alias') {
+ if (my ($f) = /^\s*(\S+)\s*=\s*\d+\s*$/) {
+ my $pkg = $f =~ s/(.*)::// ? $1 : $current_package;
+ $l{$pkg}{$f} ||= $l{$current_package}{$current_name};
+ } else {
+ warn "bad line $orig_line (state: $state)\n" if !/^\s*\w+:\s*$/ && !/^\s*$/;
+ $state = 'waiting_for_end';
+ }
+ } elsif ($state eq 'waiting_for_type' && s/^(const\s*)?\w+\s*(\*\s*)?// ||
+ $state eq 'waiting_for_function' && /^\w+/) {
+ if (my ($name, $para) = /^(\S+)\s*\((.*)\)\s*;?\s*$/) {
+ get_paras($name, $para);
+ $state = 'waiting_for_end';
+ } elsif (($name, $para) = /^(\S+)\s*\((.*)$/) {
+ $multi_line = $para;
+ $current_name = $name;
+ $state = 'multi_line';
+ } else {
+ warn "bad line $orig_line (state: $state)\n";
+ }
+ } else {
+ warn "bad line $orig_line (state: $state)\n" if
+ !(($state eq 'waiting_for_end' || $state eq 'waiting_for_type') &&
+ (/^\s/ || /^[{}]\s*$/ || /^(CODE|OUTPUT):\s*$/));
+ }
}
+}
- print
-"package Gtk2;
-our \@ISA = qw();
+my ($pkg_name, $dir) = @ARGV;
+my @xs_files = chomp_(`find $dir -name "*.xs"`);
+@ARGV == 2 && @xs_files or die "usage: gen.pl <Gtk2 or Glib> <dir where Gtk2.pm or Glib.pm is>\n";
-";
- @subroutines = sort { $a->[0] cmp $b->[0] } @subroutines, @added_subroutines;
- my @ok;
- foreach my $fun (uniq(map { $_->[0] } @subroutines)) {
- my @multiples = grep { $_->[0] eq $fun } @subroutines;
- if (@multiples != 1) {
- my $args = -1;
- foreach (@multiples) {
- my $a = split /,/, $_->[1];
- $args == -1 and $args = $a;
- #- ignore multiply defined functions that have different numbers of arguments
- $args != $a and $multiples[0][1] = ' {}';
- }
- my $i;
- $multiples[0][1] =~ s/\$_(\w+)/'$_DUMMY'.$i++/ge;
- push @ok, @multiples[0];
- } else {
- push @ok, @multiples;
- }
- }
+parse_xs($_) foreach @xs_files;
- print "sub Gtk2::$_->[0]$_->[1]\n" foreach @ok;
-}
+print "package $pkg_name;\nuse Glib;\n" if $pkg_name eq 'Gtk2';
-
-if ($ARGV[0] =~ /gtk2/) {
- shift @ARGV;
- gtk2(@ARGV);
+foreach my $pkg (sort keys %l) {
+ print "\npackage $pkg;\n";
+ print "our \@ISA = qw();\n";
+ foreach my $name (sort keys %{$l{$pkg}}) {
+ my $para = $l{$pkg}{$name};
+ $name = $pkg . '::' . $name if $name =~ /^(length|x|y|eq|foreach|format)$/;
+ if (@$para) {
+ print "sub $name { my (", join(", ", @$para), ") = \@_ }\n";
+ } else {
+ print "sub $name() {}\n";
+ }
+ }
}