From abc5cbbe3e1f6e6bdc40d94741713e9efb6d580d Mon Sep 17 00:00:00 2001 From: Tim Janik Date: Sun, 29 Apr 2001 03:04:27 +0000 Subject: [PATCH] made hook ids a gulong. Sun Apr 29 00:37:34 2001 Tim Janik * ghook.[hc]: made hook ids a gulong. Sat Apr 28 23:39:42 2001 Tim Janik * gsignal.[hc]: made signal handler and emission hook ids gulongs. (signal_handlers_foreach_matched_R): only invoke callback for handlers that are not disconnected (id>0). (signal_emit_R): prevent invocation of signal handlers during the emission they were connected within. * glib-mkenums: publically installed perl-script to parse C code enums and generate descriptions thereof. * glib-mkenums.1: assorted man page. --- ChangeLog | 4 + ChangeLog.pre-2-0 | 4 + ChangeLog.pre-2-10 | 4 + ChangeLog.pre-2-12 | 4 + ChangeLog.pre-2-2 | 4 + ChangeLog.pre-2-4 | 4 + ChangeLog.pre-2-6 | 4 + ChangeLog.pre-2-8 | 4 + docs/reference/glib/tmpl/macros_misc.sgml | 1 + ghook.c | 4 +- ghook.h | 8 +- glib/ghook.c | 4 +- glib/ghook.h | 8 +- gobject/ChangeLog | 12 + gobject/Makefile.am | 9 +- gobject/glib-genmarshal.1 | 2 +- gobject/glib-mkenums | 399 ++++++++++++++++++++++++++++++ gobject/glib-mkenums.1 | 148 +++++++++++ gobject/glib-mkenums.in | 399 ++++++++++++++++++++++++++++++ gobject/gsignal.c | 102 ++++---- gobject/gsignal.h | 18 +- 21 files changed, 1074 insertions(+), 72 deletions(-) create mode 100755 gobject/glib-mkenums create mode 100644 gobject/glib-mkenums.1 create mode 100755 gobject/glib-mkenums.in diff --git a/ChangeLog b/ChangeLog index 57e3631..e556758 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +Sun Apr 29 00:37:34 2001 Tim Janik + + * ghook.[hc]: made hook ids a gulong. + 2001-04-20 Dan Winship * configure.in: Add a check for the Darwin dynamic linker. Use diff --git a/ChangeLog.pre-2-0 b/ChangeLog.pre-2-0 index 57e3631..e556758 100644 --- a/ChangeLog.pre-2-0 +++ b/ChangeLog.pre-2-0 @@ -1,3 +1,7 @@ +Sun Apr 29 00:37:34 2001 Tim Janik + + * ghook.[hc]: made hook ids a gulong. + 2001-04-20 Dan Winship * configure.in: Add a check for the Darwin dynamic linker. Use diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index 57e3631..e556758 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,3 +1,7 @@ +Sun Apr 29 00:37:34 2001 Tim Janik + + * ghook.[hc]: made hook ids a gulong. + 2001-04-20 Dan Winship * configure.in: Add a check for the Darwin dynamic linker. Use diff --git a/ChangeLog.pre-2-12 b/ChangeLog.pre-2-12 index 57e3631..e556758 100644 --- a/ChangeLog.pre-2-12 +++ b/ChangeLog.pre-2-12 @@ -1,3 +1,7 @@ +Sun Apr 29 00:37:34 2001 Tim Janik + + * ghook.[hc]: made hook ids a gulong. + 2001-04-20 Dan Winship * configure.in: Add a check for the Darwin dynamic linker. Use diff --git a/ChangeLog.pre-2-2 b/ChangeLog.pre-2-2 index 57e3631..e556758 100644 --- a/ChangeLog.pre-2-2 +++ b/ChangeLog.pre-2-2 @@ -1,3 +1,7 @@ +Sun Apr 29 00:37:34 2001 Tim Janik + + * ghook.[hc]: made hook ids a gulong. + 2001-04-20 Dan Winship * configure.in: Add a check for the Darwin dynamic linker. Use diff --git a/ChangeLog.pre-2-4 b/ChangeLog.pre-2-4 index 57e3631..e556758 100644 --- a/ChangeLog.pre-2-4 +++ b/ChangeLog.pre-2-4 @@ -1,3 +1,7 @@ +Sun Apr 29 00:37:34 2001 Tim Janik + + * ghook.[hc]: made hook ids a gulong. + 2001-04-20 Dan Winship * configure.in: Add a check for the Darwin dynamic linker. Use diff --git a/ChangeLog.pre-2-6 b/ChangeLog.pre-2-6 index 57e3631..e556758 100644 --- a/ChangeLog.pre-2-6 +++ b/ChangeLog.pre-2-6 @@ -1,3 +1,7 @@ +Sun Apr 29 00:37:34 2001 Tim Janik + + * ghook.[hc]: made hook ids a gulong. + 2001-04-20 Dan Winship * configure.in: Add a check for the Darwin dynamic linker. Use diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8 index 57e3631..e556758 100644 --- a/ChangeLog.pre-2-8 +++ b/ChangeLog.pre-2-8 @@ -1,3 +1,7 @@ +Sun Apr 29 00:37:34 2001 Tim Janik + + * ghook.[hc]: made hook ids a gulong. + 2001-04-20 Dan Winship * configure.in: Add a check for the Darwin dynamic linker. Use diff --git a/docs/reference/glib/tmpl/macros_misc.sgml b/docs/reference/glib/tmpl/macros_misc.sgml index a7768c7..994ffb7 100644 --- a/docs/reference/glib/tmpl/macros_misc.sgml +++ b/docs/reference/glib/tmpl/macros_misc.sgml @@ -66,6 +66,7 @@ only one statement is expected by the compiler. Portable way to copy va_list variables. + @ap1: the va_list variable to place a copy of @ap2 in. @ap2: a va_list. diff --git a/ghook.c b/ghook.c index 53963a1..0bce31c 100644 --- a/ghook.c +++ b/ghook.c @@ -157,7 +157,7 @@ g_hook_destroy_link (GHookList *hook_list, gboolean g_hook_destroy (GHookList *hook_list, - guint hook_id) + gulong hook_id) { GHook *hook; @@ -451,7 +451,7 @@ g_hook_next_valid (GHookList *hook_list, GHook* g_hook_get (GHookList *hook_list, - guint hook_id) + gulong hook_id) { GHook *hook; diff --git a/ghook.h b/ghook.h index 2f96d0d..8942e5a 100644 --- a/ghook.h +++ b/ghook.h @@ -60,7 +60,7 @@ typedef enum /* --- structures --- */ struct _GHookList { - guint seq_id; + gulong seq_id; guint hook_size : 16; guint is_setup : 1; GHook *hooks; @@ -73,7 +73,7 @@ struct _GHook GHook *next; GHook *prev; guint ref_count; - guint hook_id; + gulong hook_id; guint flags; gpointer func; GDestroyNotify destroy; @@ -109,7 +109,7 @@ void g_hook_ref (GHookList *hook_list, void g_hook_unref (GHookList *hook_list, GHook *hook); gboolean g_hook_destroy (GHookList *hook_list, - guint hook_id); + gulong hook_id); void g_hook_destroy_link (GHookList *hook_list, GHook *hook); void g_hook_prepend (GHookList *hook_list, @@ -121,7 +121,7 @@ void g_hook_insert_sorted (GHookList *hook_list, GHook *hook, GHookCompareFunc func); GHook* g_hook_get (GHookList *hook_list, - guint hook_id); + gulong hook_id); GHook* g_hook_find (GHookList *hook_list, gboolean need_valids, GHookFindFunc func, diff --git a/glib/ghook.c b/glib/ghook.c index 53963a1..0bce31c 100644 --- a/glib/ghook.c +++ b/glib/ghook.c @@ -157,7 +157,7 @@ g_hook_destroy_link (GHookList *hook_list, gboolean g_hook_destroy (GHookList *hook_list, - guint hook_id) + gulong hook_id) { GHook *hook; @@ -451,7 +451,7 @@ g_hook_next_valid (GHookList *hook_list, GHook* g_hook_get (GHookList *hook_list, - guint hook_id) + gulong hook_id) { GHook *hook; diff --git a/glib/ghook.h b/glib/ghook.h index 2f96d0d..8942e5a 100644 --- a/glib/ghook.h +++ b/glib/ghook.h @@ -60,7 +60,7 @@ typedef enum /* --- structures --- */ struct _GHookList { - guint seq_id; + gulong seq_id; guint hook_size : 16; guint is_setup : 1; GHook *hooks; @@ -73,7 +73,7 @@ struct _GHook GHook *next; GHook *prev; guint ref_count; - guint hook_id; + gulong hook_id; guint flags; gpointer func; GDestroyNotify destroy; @@ -109,7 +109,7 @@ void g_hook_ref (GHookList *hook_list, void g_hook_unref (GHookList *hook_list, GHook *hook); gboolean g_hook_destroy (GHookList *hook_list, - guint hook_id); + gulong hook_id); void g_hook_destroy_link (GHookList *hook_list, GHook *hook); void g_hook_prepend (GHookList *hook_list, @@ -121,7 +121,7 @@ void g_hook_insert_sorted (GHookList *hook_list, GHook *hook, GHookCompareFunc func); GHook* g_hook_get (GHookList *hook_list, - guint hook_id); + gulong hook_id); GHook* g_hook_find (GHookList *hook_list, gboolean need_valids, GHookFindFunc func, diff --git a/gobject/ChangeLog b/gobject/ChangeLog index 84dd1b5..76de021 100644 --- a/gobject/ChangeLog +++ b/gobject/ChangeLog @@ -1,3 +1,15 @@ +Sat Apr 28 23:39:42 2001 Tim Janik + + * gsignal.[hc]: made signal handler and emission hook ids gulongs. + (signal_handlers_foreach_matched_R): only invoke callback for handlers + that are not disconnected (id>0). + (signal_emit_R): prevent invocation of signal handlers during the + emission they were connected within. + + * glib-mkenums: publically installed perl-script to parse C code + enums and generate descriptions thereof. + * glib-mkenums.1: assorted man page. + 2001-04-19 Havoc Pennington * gobject.c (g_object_get_valist): We were returning junk memory diff --git a/gobject/Makefile.am b/gobject/Makefile.am index 2e02e11..c89f134 100644 --- a/gobject/Makefile.am +++ b/gobject/Makefile.am @@ -155,10 +155,12 @@ libgobject_1_3_la_SOURCES = $(gruntime_target_sources) # # programs to compile and install # -bin_PROGRAMS = gobject-query glib-genmarshal testgruntime +bin_PROGRAMS = gobject-query glib-genmarshal glib-mkenums +noinst_PROGRAMS = testgruntime # source files gobject_query_SOURCES = gobject-query.c glib_genmarshal_SOURCES = glib-genmarshal.c +glib_mkenums_SOURCES = glib-mkenums testgruntime_SOURCES = testgruntime.c # link programs against libgobject progs_LDADD = libgobject-1.3.la $(libglib) @@ -169,7 +171,7 @@ testgruntime_LDADD = $(progs_LDADD) # # manual pages to install # -man_MANS = glib-genmarshal.1 +man_MANS = glib-genmarshal.1 glib-mkenums.1 # # auxillary files @@ -179,7 +181,8 @@ EXTRA_DIST += \ makefile.msc.in \ gobject.def \ gobject.rc.in \ - glib-genmarshal.1 + glib-genmarshal.1 \ + glib-mkenums.1 BUILT_EXTRA_DIST = \ makefile.mingw \ diff --git a/gobject/glib-genmarshal.1 b/gobject/glib-genmarshal.1 index c35606a..f7d80ff 100644 --- a/gobject/glib-genmarshal.1 +++ b/gobject/glib-genmarshal.1 @@ -190,7 +190,7 @@ g_closure_set_marshal (cc_baz, g_cclosure_marshal_FLOAT__BOOLEAN_UCHAR); .SH SEE ALSO \fB -glib-config(1) +glib-mkenums(1) \fP .SH BUGS diff --git a/gobject/glib-mkenums b/gobject/glib-mkenums new file mode 100755 index 0000000..fc6588e --- /dev/null +++ b/gobject/glib-mkenums @@ -0,0 +1,399 @@ +#!/usr/bin/perl -w + +# glib-mkenums.pl +# Information about the current enumeration +my $flags; # Is enumeration a bitmask? +my $seenbitshift; # Have we seen bitshift operators? +my $enum_prefix; # Prefix for this enumeration +my $enumname; # Name for this enumeration +my $enumshort; # $enumname without prefix +my $enumindex = 0; # Global enum counter +my $firstenum = 1; # Is this the first enumeration per file? +my @entries; # [ $name, $val ] for each entry + +sub parse_trigraph { + my $opts = shift; + my @opts; + + for $opt (split /\s*,\s*/, $opts) { + $opt =~ s/^\s*//; + $opt =~ s/\s*$//; + my ($key,$val) = $opt =~ /(\w+)(?:=(.+))?/; + defined $val or $val = 1; + push @opts, $key, $val; + } + @opts; +} +sub parse_entries { + my $file = shift; + my $file_name = shift; + + while (<$file>) { + + # read lines until comment end is matched + while (m@/\*([^*]|\*[^/*])*\**$@x) { + my $new; + defined ($new = <>) || die "Unmatched comment in $ARGV"; + $_ .= $new; + } + # strip comments w/o options + s@/\*[^<]([^*]|\*[^/*])*\**\*/@@gx; + + # strip newlines + s/\n//; + + # skip empty lines + next if m@^\s*$@; + +# print STDERR "xxx $_\n"; + + # Handle include files + if (/^\#include\s*<([^>]*)>/ ) { + my $file= "../$1"; + open NEWFILE, $file or die "Cannot open include file $file: $!\n"; + + # read lines until comment end is matched + while (m@/\*([^*]|\*[^/*])*\**$@x) { + my $new; + defined ($new = <>) || die "Unmatched comment in $file_name"; + $_ .= $new; + } + # strip comments w/o options + s@/\*[^<]([^*]|\*[^/*])*\**\*/@@gx; + + if (parse_entries (\*NEWFILE, $NEWFILE)) { + return 1; + } else { + next; + } + } + + if (/^\s*\}\s*(\w+)/) { + $enumname = $1; + $enumindex++; + return 1; + } + + if (m@^\s* + (\w+)\s* # name + (?:=( # value + (?:[^,/]|/(?!\*))* + ))?,?\s* + (?:/\*< # options + (([^*]|\*(?!/))*) + >\s*\*/)?,? + \s*$ + @x) { + my ($name, $value, $options) = ($1,$2,$3); + +# print STDERR "xxx \"$name\" \"$value\" \"$otions\"\n"; + + if (!defined $flags && defined $value && $value =~ /< output file header\n"; + print STDERR " --fprod per input file production\n"; + print STDERR " --ftail output file trailer\n"; + print STDERR " --eprod per enum text (produced prior to value itarations)\n"; + print STDERR " --vhead value header, produced before iterating over enum values\n"; + print STDERR " --vprod value text, produced for each enum value\n"; + print STDERR " --vtail value tail, produced after iterating over enum values\n"; + print STDERR " --comments comment structure\n"; + print STDERR " -h, --help show this help message\n"; + print STDERR " -v, --version print version informations\n"; + print STDERR "Production text substitutions:\n"; + print STDERR " \@EnumName\@ PrefixTheXEnum\n"; + print STDERR " \@enum_name\@ prefix_the_xenum\n"; + print STDERR " \@ENUMNAME\@ PREFIX_THE_XENUM\n"; + print STDERR " \@ENUMSHORT\@ THE_XENUM\n"; + print STDERR " \@VALUENAME\@ PREFIX_THE_XVALUE\n"; + print STDERR " \@valuenick\@ the-xvalue\n"; + print STDERR " \@type\@ either enum or flags\n"; + print STDERR " \@Type\@ either Enum or Flags\n"; + print STDERR " \@TYPE\@ either ENUM or FLAGS\n"; + print STDERR " \@filename\@ name of current input file\n"; + exit 0; +} + +# production variables: +my $fhead = ""; # output file header +my $fprod = ""; # per input file production +my $ftail = ""; # output file trailer +my $eprod = ""; # per enum text (produced prior to value itarations) +my $vhead = ""; # value header, produced before iterating over enum values +my $vprod = ""; # value text, produced for each enum value +my $vtail = ""; # value tail, produced after iterating over enum values +# other options +my $comment_tmpl = "/* \@comment\@ */"; + +if (!defined $ARGV[0]) { + usage; +} +while ($_ = $ARGV[0], /^-/) { + shift; + last if /^--$/; + if (/^--fhead$/) { $fhead = $fhead . shift } + elsif (/^--fprod$/) { $fprod = $fprod . shift } + elsif (/^--ftail$/) { $ftail = $ftail . shift } + elsif (/^--eprod$/) { $eprod = $eprod . shift } + elsif (/^--vhead$/) { $vhead = $vhead . shift } + elsif (/^--vprod$/) { $vprod = $vprod . shift } + elsif (/^--vtail$/) { $vtail = $vtail . shift } + elsif (/^--comments$/) { $comment_tmpl = shift } + elsif (/^--help$/ || /^-h$/) { usage; } + elsif (/^--version$/ || /^-v$/) { version; } + else { usage; } +} + +# put auto-generation comment +{ + my $comment = $comment_tmpl; + $comment =~ s/\@comment\@/Generated data (by glib-mkenums)/; + print "\n" . $comment . "\n\n"; +} + +if (length($fhead)) { + my $prod = $fhead; + + $prod =~ s/\@filename\@/$ARGV/g; + $prod =~ s/\\a/\a/g; $prod =~ s/\\b/\b/g; $prod =~ s/\\t/\t/g; $prod =~ s/\\n/\n/g; + $prod =~ s/\\v/\v/g; $prod =~ s/\\f/\f/g; $prod =~ s/\\r/\r/g; + + print "$prod\n"; +} + +while (<>) { + if (eof) { + close (ARGV); # reset line numbering + $firstenum = 1; # Flag to print filename at next enum + } + + # read lines until comment end is matched + while (m@/\*([^*]|\*[^/*])*\**$@x) { + my $new; + defined ($new = <>) || die "Unmatched comment in $ARGV"; + $_ .= $new; + } + # strip comments w/o options + s@/\*[^<]([^*]|\*[^/*])*\**\*/@@gx; + +# print STDERR "xxx $_\n"; + + if (m@^\s*typedef\s+enum\s* + ({)?\s* + (?:/\*< + (([^*]|\*(?!/))*) + >\s*\*/)? + @x) { + if (defined $2) { + my %options = parse_trigraph ($2); + next if defined $options{skip}; + $enum_prefix = $options{prefix}; + $flags = $options{flags}; + } else { + $enum_prefix = undef; + $flags = undef; + } + # Didn't have trailing '{' look on next lines + if (!defined $1) { + while (<>) { + if (s/^\s*\{//) { + last; + } + } + } + + $seenbitshift = 0; + @entries = (); + + # Now parse the entries + parse_entries (\*ARGV, $ARGV); + + # figure out if this was a flags or enums enumeration + if (!defined $flags) { + $flags = $seenbitshift; + } + + # Autogenerate a prefix + if (!defined $enum_prefix) { + for (@entries) { + my $nick = $_->[1]; + if (!defined $nick) { + my $name = $_->[0]; + if (defined $enum_prefix) { + my $tmp = ~ ($name ^ $enum_prefix); + ($tmp) = $tmp =~ /(^\xff*)/; + $enum_prefix = $enum_prefix & $tmp; + } else { + $enum_prefix = $name; + } + } + } + if (!defined $enum_prefix) { + $enum_prefix = ""; + } else { + # Trim so that it ends in an underscore + $enum_prefix =~ s/_[^_]*$/_/; + } + } else { + # canonicalize user defined prefixes + $enum_prefix = uc($enum_prefix); + $enum_prefix =~ s/-/_/g; + $enum_prefix =~ s/(.*)([^_])$/$1$2_/; + } + + for $entry (@entries) { + my ($name,$nick) = @{$entry}; + if (!defined $nick) { + ($nick = $name) =~ s/^$enum_prefix//; + $nick =~ tr/_/-/; + $nick = lc($nick); + @{$entry} = ($name, $nick); + } + } + + + # Spit out the output + + # enumname is e.g. GMatchType + $enspace = $enumname; + $enspace =~ s/^([A-Z][a-z]*).*$/$1/; + + $enumshort = $enumname; + $enumshort =~ s/^[A-Z][a-z]*//; + $enumshort =~ s/([^A-Z])([A-Z])/$1_$2/g; + $enumshort =~ s/([A-Z][A-Z])([A-Z][0-9a-z])/$1_$2/g; + $enumshort = uc($enumshort); + + $enumlong = uc($enspace) . "_" . $enumshort; + $enumsym = lc($enspace) . "_" . lc($enumshort); + + if ($firstenum) { + $firstenum = 0; + + if (length($fprod)) { + my $prod = $fprod; + + $prod =~ s/\@filename\@/$ARGV/g; + $prod =~ s/\\a/\a/g; $prod =~ s/\\b/\b/g; $prod =~ s/\\t/\t/g; $prod =~ s/\\n/\n/g; + $prod =~ s/\\v/\v/g; $prod =~ s/\\f/\f/g; $prod =~ s/\\r/\r/g; + + print "$prod\n"; + } + } + + if (length($eprod)) { + my $prod = $eprod; + + $prod =~ s/\@enum_name\@/$enumsym/g; + $prod =~ s/\@EnumName\@/$enumname/g; + $prod =~ s/\@ENUMSHORT\@/$enumshort/g; + $prod =~ s/\@ENUMNAME\@/$enumlong/g; + if ($flags) { $prod =~ s/\@type\@/flags/g; } else { $prod =~ s/\@type\@/enum/g; } + if ($flags) { $prod =~ s/\@Type\@/Flags/g; } else { $prod =~ s/\@Type\@/Enum/g; } + if ($flags) { $prod =~ s/\@TYPE\@/FLAGS/g; } else { $prod =~ s/\@TYPE\@/ENUM/g; } + $prod =~ s/\\a/\a/g; $prod =~ s/\\b/\b/g; $prod =~ s/\\t/\t/g; $prod =~ s/\\n/\n/g; + $prod =~ s/\\v/\v/g; $prod =~ s/\\f/\f/g; $prod =~ s/\\r/\r/g; + + print "$prod\n"; + } + + if (length($vhead)) { + my $prod = $vhead; + + $prod =~ s/\@enum_name\@/$enumsym/g; + $prod =~ s/\@EnumName\@/$enumname/g; + $prod =~ s/\@ENUMSHORT\@/$enumshort/g; + $prod =~ s/\@ENUMNAME\@/$enumlong/g; + if ($flags) { $prod =~ s/\@type\@/flags/g; } else { $prod =~ s/\@type\@/enum/g; } + if ($flags) { $prod =~ s/\@Type\@/Flags/g; } else { $prod =~ s/\@Type\@/Enum/g; } + if ($flags) { $prod =~ s/\@TYPE\@/FLAGS/g; } else { $prod =~ s/\@TYPE\@/ENUM/g; } + $prod =~ s/\\a/\a/g; $prod =~ s/\\b/\b/g; $prod =~ s/\\t/\t/g; $prod =~ s/\\n/\n/g; + $prod =~ s/\\v/\v/g; $prod =~ s/\\f/\f/g; $prod =~ s/\\r/\r/g; + + print "$prod\n"; + } + + if (length($vprod)) { + my $prod = $vprod; + + $prod =~ s/\\a/\a/g; $prod =~ s/\\b/\b/g; $prod =~ s/\\t/\t/g; $prod =~ s/\\n/\n/g; + $prod =~ s/\\v/\v/g; $prod =~ s/\\f/\f/g; $prod =~ s/\\r/\r/g; + for (@entries) { + my ($name,$nick) = @{$_}; + my $tmp_prod = $vprod; + + $tmp_prod =~ s/\@VALUENAME\@/$name/g; + $tmp_prod =~ s/\@valuenick\@/$nick/g; + if ($flags) { $tmp_prod =~ s/\@type\@/flags/g; } else { $tmp_prod =~ s/\@type\@/enum/g; } + if ($flags) { $tmp_prod =~ s/\@Type\@/Flags/g; } else { $tmp_prod =~ s/\@Type\@/Enum/g; } + if ($flags) { $tmp_prod =~ s/\@TYPE\@/FLAGS/g; } else { $tmp_prod =~ s/\@TYPE\@/ENUM/g; } + + print "$tmp_prod\n"; + } + } + + if (length($vtail)) { + my $prod = $vtail; + + $prod =~ s/\@enum_name\@/$enumsym/g; + $prod =~ s/\@EnumName\@/$enumname/g; + $prod =~ s/\@ENUMSHORT\@/$enumshort/g; + $prod =~ s/\@ENUMNAME\@/$enumlong/g; + if ($flags) { $prod =~ s/\@type\@/flags/g; } else { $prod =~ s/\@type\@/enum/g; } + if ($flags) { $prod =~ s/\@Type\@/Flags/g; } else { $prod =~ s/\@Type\@/Enum/g; } + if ($flags) { $prod =~ s/\@TYPE\@/FLAGS/g; } else { $prod =~ s/\@TYPE\@/ENUM/g; } + $prod =~ s/\\a/\a/g; $prod =~ s/\\b/\b/g; $prod =~ s/\\t/\t/g; $prod =~ s/\\n/\n/g; + $prod =~ s/\\v/\v/g; $prod =~ s/\\f/\f/g; $prod =~ s/\\r/\r/g; + + print "$prod\n"; + } + } +} + +if (length($ftail)) { + my $prod = $ftail; + + $prod =~ s/\@filename\@/$ARGV/g; + $prod =~ s/\\a/\a/g; $prod =~ s/\\b/\b/g; $prod =~ s/\\t/\t/g; $prod =~ s/\\n/\n/g; + $prod =~ s/\\v/\v/g; $prod =~ s/\\f/\f/g; $prod =~ s/\\r/\r/g; + + print "$prod\n"; +} + +# put auto-generation comment +{ + my $comment = $comment_tmpl; + $comment =~ s/\@comment\@/Generated data ends here/; + print "\n" . $comment . "\n\n"; +} diff --git a/gobject/glib-mkenums.1 b/gobject/glib-mkenums.1 new file mode 100644 index 0000000..374ca95 --- /dev/null +++ b/gobject/glib-mkenums.1 @@ -0,0 +1,148 @@ +.TH GLIB-MKENUMS 1 "20 Apr 2001" +.SH NAME +glib-mkenums \- C language enum description generation utility +.SH SYNOPSIS + +\fBglib-mkenums\fP [\fIoptions\fP] [\fIfiles...\fP] + +.SH DESCRIPTION +\fBglib-mkenums\fP is a small perl-script utility that parses C code to extract enum +definitions and produces enum descriptions based on text templates specified +by the user. Most frequently this script is used to produce C code that contains +enum values as strings so programs can provide value name strings for introspection. + +.SH INVOCATION + +\fBglib-mkenums\fP takes a list of valid C code files as input. The options +specified controll the text that is output, certain substitutions are performed +on the text templates for keywords enclosed in @ characters. + + +.SS Options +.TP +\fI--fhead +Put out prior to processing input files. +.TP +\fI--fprod +Put out everytime a new input file is being processed. +.TP +\fI--ftail +Put out after all input files have been processed. +.TP +\fI--eprod +Put out everytime an enum is encountered in the input files. +.TP +\fI--vhead +Put out before iterating over the set of values of an enum. +.TP +\fI--vprod +Put out for every value of an enum. +.TP +\fI--vtail +Put out after iterating over all values of an enum. +.TP +\fI--comments +Template for auto-generated comments, the default (for C code generations) is +"/* @comment@ */". +.TP +\fI-h, --help\fP +Print brief help and exit. +.TP +\fI-v, --version\fP +Print version and exit. +.PP + + +.SS Production text substitutions +Certain keywords enclosed in @ characters will be substituted in the outputted +text. For the substitution examples of the keywords below, the following example +enum definition is assumed: +.PP +.RS +.nf +typedef enum +{ + PREFIX_THE_XVALUE = 1 << 3, + PREFIX_ANOTHER_VALUE = 1 << 4 +} PrefixTheXEnum; +.fi +.RE + +.TP 12 +\fI@EnumName@ +The name of the enum currently being processed, enum names are assumed to be +properly namespaced and to use mixed capitalization to seperate +words (e.g. PrefixTheXEnum). +.TP 12 +\fI@enum_name@ +The enum name with words lowercase and word-seperated by underscores (e.g. prefix_the_xenum). +.TP 12 +\fI@ENUMNAME@ +The enum name with words uppercase and word-seperated by underscores (e.g. PREFIX_THE_XENUM). +.TP 12 +\fI@ENUMSHORT@ +The enum name with words uppercase and word-seperated by underscores, prefix stripped (e.g. THE_XENUM). +.TP 12 +\fI@VALUENAME@ +The enum value name currently being processed with words uppercase and word-seperated by underscores, +this is the assumed literal notation of enum values in the C sources (e.g. PREFIX_THE_XVALUE). +.TP 12 +\fI@valuenick@ +A nick name for the enum value currently being processed, this is usually generated by stripping +common prefix words of all the enum values of the current enum, the words are lowercase and +underscores are subsituted by a minus (e.g. the-xvalue). +.TP 12 +\fI@type@ +This is substituted either by "enum" or "flags", depending on whether the enum value definitions +contained bit-shift operators or not (e.g. flags). +.TP 12 +\fI@Type@ +The same as \fI@type@\fP with the first letter capitalized (e.g. Flags). +.TP 12 +\fI@TYPE@ +The same as \fI@type@\fP with all letters uppercased (e.g. FLAGS). +.TP 12 +\fI@filename@ +The name of the input file currently being processed (e.g. foo.h). + +.SS Trigraph extensions +Some C comments are treated specially in the parsed enum definitions, such comments +start out with the trigraph sequence "/*<" and end with the trigraph sequence ">*/". +Per enum definition, the options "skip" and "flags" can be specified, to indicate +this enum definition to be skipped, or for it to be treated as a flags definition, or +to specify the common prefix to be stripped from all values to generate value nicknames, +respectively. +Per value definition, the options "skip" and "nick" are supported. The former causes the +value to be skipped, and the latter can be used to specify the otherwise auto-generated +nickname. +Examples: +.PP +.RS +.nf +typedef enum /*< skip >*/ +{ + PREFIX_FOO +} PrefixThisEnumWillBeSkipped; +typedef enum /*< flags,prefix=PREFIX >*/ +{ + PREFIX_THE_ZEROTH_VALUE, /*< skip >*/ + PREFIX_THE_FIRST_VALUE, + PREFIX_THE_SECOND_VALUE, + PREFIX_THE_THIRD_VALUE, /*< nick=the-last-value >*/ +} PrefixTheFlagsEnum; +.fi +.RE + +.SH SEE ALSO +\fB +glib-genmarshal(1) +\fP + +.SH BUGS +None known yet. + +.SH AUTHOR +.B glib-mkenums +was written by Tim Janik and Owen Taylor . +.PP +This manual page was provided by Tim Janik . diff --git a/gobject/glib-mkenums.in b/gobject/glib-mkenums.in new file mode 100755 index 0000000..fc6588e --- /dev/null +++ b/gobject/glib-mkenums.in @@ -0,0 +1,399 @@ +#!/usr/bin/perl -w + +# glib-mkenums.pl +# Information about the current enumeration +my $flags; # Is enumeration a bitmask? +my $seenbitshift; # Have we seen bitshift operators? +my $enum_prefix; # Prefix for this enumeration +my $enumname; # Name for this enumeration +my $enumshort; # $enumname without prefix +my $enumindex = 0; # Global enum counter +my $firstenum = 1; # Is this the first enumeration per file? +my @entries; # [ $name, $val ] for each entry + +sub parse_trigraph { + my $opts = shift; + my @opts; + + for $opt (split /\s*,\s*/, $opts) { + $opt =~ s/^\s*//; + $opt =~ s/\s*$//; + my ($key,$val) = $opt =~ /(\w+)(?:=(.+))?/; + defined $val or $val = 1; + push @opts, $key, $val; + } + @opts; +} +sub parse_entries { + my $file = shift; + my $file_name = shift; + + while (<$file>) { + + # read lines until comment end is matched + while (m@/\*([^*]|\*[^/*])*\**$@x) { + my $new; + defined ($new = <>) || die "Unmatched comment in $ARGV"; + $_ .= $new; + } + # strip comments w/o options + s@/\*[^<]([^*]|\*[^/*])*\**\*/@@gx; + + # strip newlines + s/\n//; + + # skip empty lines + next if m@^\s*$@; + +# print STDERR "xxx $_\n"; + + # Handle include files + if (/^\#include\s*<([^>]*)>/ ) { + my $file= "../$1"; + open NEWFILE, $file or die "Cannot open include file $file: $!\n"; + + # read lines until comment end is matched + while (m@/\*([^*]|\*[^/*])*\**$@x) { + my $new; + defined ($new = <>) || die "Unmatched comment in $file_name"; + $_ .= $new; + } + # strip comments w/o options + s@/\*[^<]([^*]|\*[^/*])*\**\*/@@gx; + + if (parse_entries (\*NEWFILE, $NEWFILE)) { + return 1; + } else { + next; + } + } + + if (/^\s*\}\s*(\w+)/) { + $enumname = $1; + $enumindex++; + return 1; + } + + if (m@^\s* + (\w+)\s* # name + (?:=( # value + (?:[^,/]|/(?!\*))* + ))?,?\s* + (?:/\*< # options + (([^*]|\*(?!/))*) + >\s*\*/)?,? + \s*$ + @x) { + my ($name, $value, $options) = ($1,$2,$3); + +# print STDERR "xxx \"$name\" \"$value\" \"$otions\"\n"; + + if (!defined $flags && defined $value && $value =~ /< output file header\n"; + print STDERR " --fprod per input file production\n"; + print STDERR " --ftail output file trailer\n"; + print STDERR " --eprod per enum text (produced prior to value itarations)\n"; + print STDERR " --vhead value header, produced before iterating over enum values\n"; + print STDERR " --vprod value text, produced for each enum value\n"; + print STDERR " --vtail value tail, produced after iterating over enum values\n"; + print STDERR " --comments comment structure\n"; + print STDERR " -h, --help show this help message\n"; + print STDERR " -v, --version print version informations\n"; + print STDERR "Production text substitutions:\n"; + print STDERR " \@EnumName\@ PrefixTheXEnum\n"; + print STDERR " \@enum_name\@ prefix_the_xenum\n"; + print STDERR " \@ENUMNAME\@ PREFIX_THE_XENUM\n"; + print STDERR " \@ENUMSHORT\@ THE_XENUM\n"; + print STDERR " \@VALUENAME\@ PREFIX_THE_XVALUE\n"; + print STDERR " \@valuenick\@ the-xvalue\n"; + print STDERR " \@type\@ either enum or flags\n"; + print STDERR " \@Type\@ either Enum or Flags\n"; + print STDERR " \@TYPE\@ either ENUM or FLAGS\n"; + print STDERR " \@filename\@ name of current input file\n"; + exit 0; +} + +# production variables: +my $fhead = ""; # output file header +my $fprod = ""; # per input file production +my $ftail = ""; # output file trailer +my $eprod = ""; # per enum text (produced prior to value itarations) +my $vhead = ""; # value header, produced before iterating over enum values +my $vprod = ""; # value text, produced for each enum value +my $vtail = ""; # value tail, produced after iterating over enum values +# other options +my $comment_tmpl = "/* \@comment\@ */"; + +if (!defined $ARGV[0]) { + usage; +} +while ($_ = $ARGV[0], /^-/) { + shift; + last if /^--$/; + if (/^--fhead$/) { $fhead = $fhead . shift } + elsif (/^--fprod$/) { $fprod = $fprod . shift } + elsif (/^--ftail$/) { $ftail = $ftail . shift } + elsif (/^--eprod$/) { $eprod = $eprod . shift } + elsif (/^--vhead$/) { $vhead = $vhead . shift } + elsif (/^--vprod$/) { $vprod = $vprod . shift } + elsif (/^--vtail$/) { $vtail = $vtail . shift } + elsif (/^--comments$/) { $comment_tmpl = shift } + elsif (/^--help$/ || /^-h$/) { usage; } + elsif (/^--version$/ || /^-v$/) { version; } + else { usage; } +} + +# put auto-generation comment +{ + my $comment = $comment_tmpl; + $comment =~ s/\@comment\@/Generated data (by glib-mkenums)/; + print "\n" . $comment . "\n\n"; +} + +if (length($fhead)) { + my $prod = $fhead; + + $prod =~ s/\@filename\@/$ARGV/g; + $prod =~ s/\\a/\a/g; $prod =~ s/\\b/\b/g; $prod =~ s/\\t/\t/g; $prod =~ s/\\n/\n/g; + $prod =~ s/\\v/\v/g; $prod =~ s/\\f/\f/g; $prod =~ s/\\r/\r/g; + + print "$prod\n"; +} + +while (<>) { + if (eof) { + close (ARGV); # reset line numbering + $firstenum = 1; # Flag to print filename at next enum + } + + # read lines until comment end is matched + while (m@/\*([^*]|\*[^/*])*\**$@x) { + my $new; + defined ($new = <>) || die "Unmatched comment in $ARGV"; + $_ .= $new; + } + # strip comments w/o options + s@/\*[^<]([^*]|\*[^/*])*\**\*/@@gx; + +# print STDERR "xxx $_\n"; + + if (m@^\s*typedef\s+enum\s* + ({)?\s* + (?:/\*< + (([^*]|\*(?!/))*) + >\s*\*/)? + @x) { + if (defined $2) { + my %options = parse_trigraph ($2); + next if defined $options{skip}; + $enum_prefix = $options{prefix}; + $flags = $options{flags}; + } else { + $enum_prefix = undef; + $flags = undef; + } + # Didn't have trailing '{' look on next lines + if (!defined $1) { + while (<>) { + if (s/^\s*\{//) { + last; + } + } + } + + $seenbitshift = 0; + @entries = (); + + # Now parse the entries + parse_entries (\*ARGV, $ARGV); + + # figure out if this was a flags or enums enumeration + if (!defined $flags) { + $flags = $seenbitshift; + } + + # Autogenerate a prefix + if (!defined $enum_prefix) { + for (@entries) { + my $nick = $_->[1]; + if (!defined $nick) { + my $name = $_->[0]; + if (defined $enum_prefix) { + my $tmp = ~ ($name ^ $enum_prefix); + ($tmp) = $tmp =~ /(^\xff*)/; + $enum_prefix = $enum_prefix & $tmp; + } else { + $enum_prefix = $name; + } + } + } + if (!defined $enum_prefix) { + $enum_prefix = ""; + } else { + # Trim so that it ends in an underscore + $enum_prefix =~ s/_[^_]*$/_/; + } + } else { + # canonicalize user defined prefixes + $enum_prefix = uc($enum_prefix); + $enum_prefix =~ s/-/_/g; + $enum_prefix =~ s/(.*)([^_])$/$1$2_/; + } + + for $entry (@entries) { + my ($name,$nick) = @{$entry}; + if (!defined $nick) { + ($nick = $name) =~ s/^$enum_prefix//; + $nick =~ tr/_/-/; + $nick = lc($nick); + @{$entry} = ($name, $nick); + } + } + + + # Spit out the output + + # enumname is e.g. GMatchType + $enspace = $enumname; + $enspace =~ s/^([A-Z][a-z]*).*$/$1/; + + $enumshort = $enumname; + $enumshort =~ s/^[A-Z][a-z]*//; + $enumshort =~ s/([^A-Z])([A-Z])/$1_$2/g; + $enumshort =~ s/([A-Z][A-Z])([A-Z][0-9a-z])/$1_$2/g; + $enumshort = uc($enumshort); + + $enumlong = uc($enspace) . "_" . $enumshort; + $enumsym = lc($enspace) . "_" . lc($enumshort); + + if ($firstenum) { + $firstenum = 0; + + if (length($fprod)) { + my $prod = $fprod; + + $prod =~ s/\@filename\@/$ARGV/g; + $prod =~ s/\\a/\a/g; $prod =~ s/\\b/\b/g; $prod =~ s/\\t/\t/g; $prod =~ s/\\n/\n/g; + $prod =~ s/\\v/\v/g; $prod =~ s/\\f/\f/g; $prod =~ s/\\r/\r/g; + + print "$prod\n"; + } + } + + if (length($eprod)) { + my $prod = $eprod; + + $prod =~ s/\@enum_name\@/$enumsym/g; + $prod =~ s/\@EnumName\@/$enumname/g; + $prod =~ s/\@ENUMSHORT\@/$enumshort/g; + $prod =~ s/\@ENUMNAME\@/$enumlong/g; + if ($flags) { $prod =~ s/\@type\@/flags/g; } else { $prod =~ s/\@type\@/enum/g; } + if ($flags) { $prod =~ s/\@Type\@/Flags/g; } else { $prod =~ s/\@Type\@/Enum/g; } + if ($flags) { $prod =~ s/\@TYPE\@/FLAGS/g; } else { $prod =~ s/\@TYPE\@/ENUM/g; } + $prod =~ s/\\a/\a/g; $prod =~ s/\\b/\b/g; $prod =~ s/\\t/\t/g; $prod =~ s/\\n/\n/g; + $prod =~ s/\\v/\v/g; $prod =~ s/\\f/\f/g; $prod =~ s/\\r/\r/g; + + print "$prod\n"; + } + + if (length($vhead)) { + my $prod = $vhead; + + $prod =~ s/\@enum_name\@/$enumsym/g; + $prod =~ s/\@EnumName\@/$enumname/g; + $prod =~ s/\@ENUMSHORT\@/$enumshort/g; + $prod =~ s/\@ENUMNAME\@/$enumlong/g; + if ($flags) { $prod =~ s/\@type\@/flags/g; } else { $prod =~ s/\@type\@/enum/g; } + if ($flags) { $prod =~ s/\@Type\@/Flags/g; } else { $prod =~ s/\@Type\@/Enum/g; } + if ($flags) { $prod =~ s/\@TYPE\@/FLAGS/g; } else { $prod =~ s/\@TYPE\@/ENUM/g; } + $prod =~ s/\\a/\a/g; $prod =~ s/\\b/\b/g; $prod =~ s/\\t/\t/g; $prod =~ s/\\n/\n/g; + $prod =~ s/\\v/\v/g; $prod =~ s/\\f/\f/g; $prod =~ s/\\r/\r/g; + + print "$prod\n"; + } + + if (length($vprod)) { + my $prod = $vprod; + + $prod =~ s/\\a/\a/g; $prod =~ s/\\b/\b/g; $prod =~ s/\\t/\t/g; $prod =~ s/\\n/\n/g; + $prod =~ s/\\v/\v/g; $prod =~ s/\\f/\f/g; $prod =~ s/\\r/\r/g; + for (@entries) { + my ($name,$nick) = @{$_}; + my $tmp_prod = $vprod; + + $tmp_prod =~ s/\@VALUENAME\@/$name/g; + $tmp_prod =~ s/\@valuenick\@/$nick/g; + if ($flags) { $tmp_prod =~ s/\@type\@/flags/g; } else { $tmp_prod =~ s/\@type\@/enum/g; } + if ($flags) { $tmp_prod =~ s/\@Type\@/Flags/g; } else { $tmp_prod =~ s/\@Type\@/Enum/g; } + if ($flags) { $tmp_prod =~ s/\@TYPE\@/FLAGS/g; } else { $tmp_prod =~ s/\@TYPE\@/ENUM/g; } + + print "$tmp_prod\n"; + } + } + + if (length($vtail)) { + my $prod = $vtail; + + $prod =~ s/\@enum_name\@/$enumsym/g; + $prod =~ s/\@EnumName\@/$enumname/g; + $prod =~ s/\@ENUMSHORT\@/$enumshort/g; + $prod =~ s/\@ENUMNAME\@/$enumlong/g; + if ($flags) { $prod =~ s/\@type\@/flags/g; } else { $prod =~ s/\@type\@/enum/g; } + if ($flags) { $prod =~ s/\@Type\@/Flags/g; } else { $prod =~ s/\@Type\@/Enum/g; } + if ($flags) { $prod =~ s/\@TYPE\@/FLAGS/g; } else { $prod =~ s/\@TYPE\@/ENUM/g; } + $prod =~ s/\\a/\a/g; $prod =~ s/\\b/\b/g; $prod =~ s/\\t/\t/g; $prod =~ s/\\n/\n/g; + $prod =~ s/\\v/\v/g; $prod =~ s/\\f/\f/g; $prod =~ s/\\r/\r/g; + + print "$prod\n"; + } + } +} + +if (length($ftail)) { + my $prod = $ftail; + + $prod =~ s/\@filename\@/$ARGV/g; + $prod =~ s/\\a/\a/g; $prod =~ s/\\b/\b/g; $prod =~ s/\\t/\t/g; $prod =~ s/\\n/\n/g; + $prod =~ s/\\v/\v/g; $prod =~ s/\\f/\f/g; $prod =~ s/\\r/\r/g; + + print "$prod\n"; +} + +# put auto-generation comment +{ + my $comment = $comment_tmpl; + $comment =~ s/\@comment\@/Generated data ends here/; + print "\n" . $comment . "\n\n"; +} diff --git a/gobject/gsignal.c b/gobject/gsignal.c index 845a955..6cf74d9 100644 --- a/gobject/gsignal.c +++ b/gobject/gsignal.c @@ -110,7 +110,7 @@ static void handler_insert (guint signal_id, gpointer instance, Handler *handler); static Handler* handler_lookup (gpointer instance, - guint handler_id, + gulong handler_id, guint *signal_id_p); static inline HandlerMatch* handler_match_prepend (HandlerMatch *list, Handler *handler, @@ -204,7 +204,7 @@ struct _HandlerList }; struct _Handler { - guint id; + gulong sequential_number; Handler *next; Handler *prev; GQuark detail; @@ -235,6 +235,7 @@ static Emission *g_recursive_emissions = NULL; static Emission *g_restart_emissions = NULL; static GTrashStack *g_handler_ts = NULL; static GTrashStack *g_emission_ts = NULL; +static gulong g_handler_sequential_number = 1; G_LOCK_DEFINE_STATIC (g_signal_mutex); @@ -339,7 +340,7 @@ handler_list_lookup (guint signal_id, static Handler* handler_lookup (gpointer instance, - guint handler_id, + gulong handler_id, guint *signal_id_p) { GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance); @@ -354,7 +355,7 @@ handler_lookup (gpointer instance, Handler *handler; for (handler = hlist->handlers; handler; handler = handler->next) - if (handler->id == handler_id) + if (handler->sequential_number == handler_id) { if (signal_id_p) *signal_id_p = hlist->signal_id; @@ -426,7 +427,7 @@ handlers_find (gpointer instance, mask = ~mask; for (handler = hlist ? hlist->handlers : NULL; handler; handler = handler->next) - if (handler->id && + if (handler->sequential_number && ((mask & G_SIGNAL_MATCH_DETAIL) || handler->detail == detail) && ((mask & G_SIGNAL_MATCH_CLOSURE) || handler->closure == closure) && ((mask & G_SIGNAL_MATCH_DATA) || handler->closure->data == data) && @@ -463,7 +464,7 @@ handlers_find (gpointer instance, } for (handler = hlist->handlers; handler; handler = handler->next) - if (handler->id && + if (handler->sequential_number && ((mask & G_SIGNAL_MATCH_DETAIL) || handler->detail == detail) && ((mask & G_SIGNAL_MATCH_CLOSURE) || handler->closure == closure) && ((mask & G_SIGNAL_MATCH_DATA) || handler->closure->data == data) && @@ -486,16 +487,15 @@ handlers_find (gpointer instance, static inline Handler* handler_new (gboolean after) { - static guint handler_id = 1; Handler *handler = g_generic_node_alloc (&g_handler_ts, sizeof (Handler), HANDLER_PRE_ALLOC); #ifndef G_DISABLE_CHECKS - if (handler_id == 0) + if (g_handler_sequential_number < 1) g_error (G_STRLOC ": handler id overflow, %s", REPORT_BUG); #endif - handler->id = handler_id++; + handler->sequential_number = g_handler_sequential_number++; handler->prev = NULL; handler->next = NULL; handler->detail = 0; @@ -742,14 +742,14 @@ signal_finalize_hook (GHookList *hook_list, } } -guint +gulong g_signal_add_emission_hook (guint signal_id, GQuark detail, GSignalEmissionHook hook_func, gpointer hook_data, GDestroyNotify data_destroy) { - static guint seq_hook_id = 1; + static gulong seq_hook_id = 1; SignalNode *node; GHook *hook; SignalHook *signal_hook; @@ -792,8 +792,8 @@ g_signal_add_emission_hook (guint signal_id, } void -g_signal_remove_emission_hook (guint signal_id, - guint hook_id) +g_signal_remove_emission_hook (guint signal_id, + gulong hook_id) { SignalNode *node; @@ -805,7 +805,7 @@ g_signal_remove_emission_hook (guint signal_id, if (!node || node->destroyed) g_warning ("%s: invalid signal id `%u'", G_STRLOC, signal_id); else if (!node->emission_hooks || !g_hook_destroy (node->emission_hooks, hook_id)) - g_warning ("%s: signal \"%s\" had no hook (%u) to remove", G_STRLOC, node->name, hook_id); + g_warning ("%s: signal \"%s\" had no hook (%lu) to remove", G_STRLOC, node->name, hook_id); G_UNLOCK (g_signal_mutex); } @@ -1209,7 +1209,7 @@ signal_destroy_R (SignalNode *signal_node) G_LOCK (g_signal_mutex); } -guint +gulong g_signal_connect_closure_by_id (gpointer instance, guint signal_id, GQuark detail, @@ -1217,7 +1217,7 @@ g_signal_connect_closure_by_id (gpointer instance, gboolean after) { SignalNode *node; - guint handler_id = 0; + gulong handler_seq_no = 0; g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0); g_return_val_if_fail (signal_id > 0, 0); @@ -1235,7 +1235,7 @@ g_signal_connect_closure_by_id (gpointer instance, { Handler *handler = handler_new (after); - handler_id = handler->id; + handler_seq_no = handler->sequential_number; handler->detail = detail; handler->closure = g_closure_ref (closure); g_closure_sink (closure); @@ -1248,16 +1248,17 @@ g_signal_connect_closure_by_id (gpointer instance, g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance); G_UNLOCK (g_signal_mutex); - return handler_id; + return handler_seq_no; } -guint +gulong g_signal_connect_closure (gpointer instance, const gchar *detailed_signal, GClosure *closure, gboolean after) { - guint signal_id, handler_id = 0; + guint signal_id; + gulong handler_seq_no = 0; GQuark detail = 0; GType itype; @@ -1280,7 +1281,7 @@ g_signal_connect_closure (gpointer instance, { Handler *handler = handler_new (after); - handler_id = handler->id; + handler_seq_no = handler->sequential_number; handler->detail = detail; handler->closure = g_closure_ref (closure); g_closure_sink (closure); @@ -1293,10 +1294,10 @@ g_signal_connect_closure (gpointer instance, g_warning ("%s: signal `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance); G_UNLOCK (g_signal_mutex); - return handler_id; + return handler_seq_no; } -guint +gulong g_signal_connect_data (gpointer instance, const gchar *detailed_signal, GCallback c_handler, @@ -1305,7 +1306,8 @@ g_signal_connect_data (gpointer instance, gboolean swapped, gboolean after) { - guint signal_id, handler_id = 0; + guint signal_id; + gulong handler_seq_no = 0; GQuark detail = 0; GType itype; @@ -1328,7 +1330,7 @@ g_signal_connect_data (gpointer instance, { Handler *handler = handler_new (after); - handler_id = handler->id; + handler_seq_no = handler->sequential_number; handler->detail = detail; handler->closure = g_closure_ref ((swapped ? g_cclosure_new_swap : g_cclosure_new) (c_handler, data, destroy_data)); g_closure_sink (handler->closure); @@ -1341,12 +1343,12 @@ g_signal_connect_data (gpointer instance, g_warning ("%s: signal `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance); G_UNLOCK (g_signal_mutex); - return handler_id; + return handler_seq_no; } void g_signal_handler_block (gpointer instance, - guint handler_id) + gulong handler_id) { Handler *handler; @@ -1361,17 +1363,16 @@ g_signal_handler_block (gpointer instance, if (handler->block_count >= HANDLER_MAX_BLOCK_COUNT - 1) g_error (G_STRLOC ": handler block_count overflow, %s", REPORT_BUG); #endif - handler->block_count += 1; } else - g_warning ("%s: instance `%p' has no handler with id `%u'", G_STRLOC, instance, handler_id); + g_warning ("%s: instance `%p' has no handler with id `%lu'", G_STRLOC, instance, handler_id); G_UNLOCK (g_signal_mutex); } void g_signal_handler_unblock (gpointer instance, - guint handler_id) + gulong handler_id) { Handler *handler; @@ -1385,16 +1386,16 @@ g_signal_handler_unblock (gpointer instance, if (handler->block_count) handler->block_count -= 1; else - g_warning (G_STRLOC ": handler `%u' of instance `%p' is not blocked", handler_id, instance); + g_warning (G_STRLOC ": handler `%lu' of instance `%p' is not blocked", handler_id, instance); } else - g_warning ("%s: instance `%p' has no handler with id `%u'", G_STRLOC, instance, handler_id); + g_warning ("%s: instance `%p' has no handler with id `%lu'", G_STRLOC, instance, handler_id); G_UNLOCK (g_signal_mutex); } void g_signal_handler_disconnect (gpointer instance, - guint handler_id) + gulong handler_id) { Handler *handler; guint signal_id; @@ -1406,12 +1407,12 @@ g_signal_handler_disconnect (gpointer instance, handler = handler_lookup (instance, handler_id, &signal_id); if (handler) { - handler->id = 0; + handler->sequential_number = 0; handler->block_count = 1; handler_unref_R (signal_id, instance, handler); } else - g_warning ("%s: instance `%p' has no handler with id `%u'", G_STRLOC, instance, handler_id); + g_warning ("%s: instance `%p' has no handler with id `%lu'", G_STRLOC, instance, handler_id); G_UNLOCK (g_signal_mutex); } @@ -1445,9 +1446,9 @@ g_signal_handlers_destroy (gpointer instance) /* cruel unlink, this works because _all_ handlers vanish */ tmp->next = NULL; tmp->prev = tmp; - if (tmp->id) + if (tmp->sequential_number) { - tmp->id = 0; + tmp->sequential_number = 0; handler_unref_R (0, NULL, tmp); } } @@ -1457,7 +1458,7 @@ g_signal_handlers_destroy (gpointer instance) G_UNLOCK (g_signal_mutex); } -guint +gulong g_signal_handler_find (gpointer instance, GSignalMatchType mask, guint signal_id, @@ -1466,7 +1467,7 @@ g_signal_handler_find (gpointer instance, gpointer func, gpointer data) { - guint handler_id = 0; + gulong handler_seq_no = 0; g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0); g_return_val_if_fail ((mask & ~G_SIGNAL_MATCH_MASK) == 0, 0); @@ -1479,13 +1480,13 @@ g_signal_handler_find (gpointer instance, mlist = handlers_find (instance, mask, signal_id, detail, closure, func, data, TRUE); if (mlist) { - handler_id = mlist->handler->id; + handler_seq_no = mlist->handler->sequential_number; handler_match_free1_R (mlist, instance); } G_UNLOCK (g_signal_mutex); } - return handler_id; + return handler_seq_no; } static guint @@ -1497,7 +1498,7 @@ signal_handlers_foreach_matched_R (gpointer instance, gpointer func, gpointer data, void (*callback) (gpointer instance, - guint handler_id)) + gulong handler_seq_no)) { HandlerMatch *mlist; guint n_handlers = 0; @@ -1506,9 +1507,12 @@ signal_handlers_foreach_matched_R (gpointer instance, while (mlist) { n_handlers++; - G_UNLOCK (g_signal_mutex); - callback (instance, mlist->handler->id); - G_LOCK (g_signal_mutex); + if (mlist->handler->sequential_number) + { + G_UNLOCK (g_signal_mutex); + callback (instance, mlist->handler->sequential_number); + G_LOCK (g_signal_mutex); + } mlist = handler_match_free1_R (mlist, instance); } @@ -1880,6 +1884,7 @@ signal_emit_R (SignalNode *node, Handler *handler_list = NULL; GValue *return_accu, accu = { 0, }; guint signal_id = node->signal_id; + gulong max_sequential_handler_number; gboolean return_value_altered = FALSE; #ifdef G_ENABLE_DEBUG @@ -1922,6 +1927,7 @@ signal_emit_R (SignalNode *node, if (handler_list) handler_unref_R (signal_id, instance, handler_list); + max_sequential_handler_number = g_handler_sequential_number; hlist = handler_list_lookup (signal_id, instance); handler_list = hlist ? hlist->handlers : NULL; if (handler_list) @@ -1999,7 +2005,8 @@ signal_emit_R (SignalNode *node, handler_list = handler; break; } - else if (!handler->block_count && (!handler->detail || handler->detail == detail)) + else if (!handler->block_count && (!handler->detail || handler->detail == detail) && + handler->sequential_number < max_sequential_handler_number) { G_UNLOCK (g_signal_mutex); g_closure_invoke (handler->closure, @@ -2066,7 +2073,8 @@ signal_emit_R (SignalNode *node, { Handler *tmp; - if (handler->after && !handler->block_count && (!handler->detail || handler->detail == detail)) + if (handler->after && !handler->block_count && (!handler->detail || handler->detail == detail) && + handler->sequential_number < max_sequential_handler_number) { G_UNLOCK (g_signal_mutex); g_closure_invoke (handler->closure, diff --git a/gobject/gsignal.h b/gobject/gsignal.h index 67b1fb4..4da55fd 100644 --- a/gobject/gsignal.h +++ b/gobject/gsignal.h @@ -149,13 +149,13 @@ gboolean g_signal_parse_name (const gchar *detailed_signal, void g_signal_stop_emission (gpointer instance, guint signal_id, GQuark detail); -guint g_signal_add_emission_hook (guint signal_id, +gulong g_signal_add_emission_hook (guint signal_id, GQuark quark, GSignalEmissionHook hook_func, gpointer hook_data, GDestroyNotify data_destroy); void g_signal_remove_emission_hook (guint signal_id, - guint hook_id); + gulong hook_id); /* --- signal handlers --- */ @@ -163,16 +163,16 @@ gboolean g_signal_has_handler_pending (gpointer instance, guint signal_id, GQuark detail, gboolean may_be_blocked); -guint g_signal_connect_closure_by_id (gpointer instance, +gulong g_signal_connect_closure_by_id (gpointer instance, guint signal_id, GQuark detail, GClosure *closure, gboolean after); -guint g_signal_connect_closure (gpointer instance, +gulong g_signal_connect_closure (gpointer instance, const gchar *detailed_signal, GClosure *closure, gboolean after); -guint g_signal_connect_data (gpointer instance, +gulong g_signal_connect_data (gpointer instance, const gchar *detailed_signal, GCallback c_handler, gpointer data, @@ -180,12 +180,12 @@ guint g_signal_connect_data (gpointer instance, gboolean swapped, gboolean after); void g_signal_handler_block (gpointer instance, - guint handler_id); + gulong handler_id); void g_signal_handler_unblock (gpointer instance, - guint handler_id); + gulong handler_id); void g_signal_handler_disconnect (gpointer instance, - guint handler_id); -guint g_signal_handler_find (gpointer instance, + gulong handler_id); +gulong g_signal_handler_find (gpointer instance, GSignalMatchType mask, guint signal_id, GQuark detail, -- 2.7.4