made hook ids a gulong.

Sun Apr 29 00:37:34 2001  Tim Janik  <timj@gtk.org>

        * ghook.[hc]: made hook ids a gulong.

Sat Apr 28 23:39:42 2001  Tim Janik  <timj@gtk.org>

        * 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.
This commit is contained in:
Tim Janik 2001-04-29 03:04:27 +00:00 committed by Tim Janik
parent 655d467602
commit abc5cbbe3e
21 changed files with 1074 additions and 72 deletions

View File

@ -1,3 +1,7 @@
Sun Apr 29 00:37:34 2001 Tim Janik <timj@gtk.org>
* ghook.[hc]: made hook ids a gulong.
2001-04-20 Dan Winship <danw@ximian.com>
* configure.in: Add a check for the Darwin dynamic linker. Use

View File

@ -1,3 +1,7 @@
Sun Apr 29 00:37:34 2001 Tim Janik <timj@gtk.org>
* ghook.[hc]: made hook ids a gulong.
2001-04-20 Dan Winship <danw@ximian.com>
* configure.in: Add a check for the Darwin dynamic linker. Use

View File

@ -1,3 +1,7 @@
Sun Apr 29 00:37:34 2001 Tim Janik <timj@gtk.org>
* ghook.[hc]: made hook ids a gulong.
2001-04-20 Dan Winship <danw@ximian.com>
* configure.in: Add a check for the Darwin dynamic linker. Use

View File

@ -1,3 +1,7 @@
Sun Apr 29 00:37:34 2001 Tim Janik <timj@gtk.org>
* ghook.[hc]: made hook ids a gulong.
2001-04-20 Dan Winship <danw@ximian.com>
* configure.in: Add a check for the Darwin dynamic linker. Use

View File

@ -1,3 +1,7 @@
Sun Apr 29 00:37:34 2001 Tim Janik <timj@gtk.org>
* ghook.[hc]: made hook ids a gulong.
2001-04-20 Dan Winship <danw@ximian.com>
* configure.in: Add a check for the Darwin dynamic linker. Use

View File

@ -1,3 +1,7 @@
Sun Apr 29 00:37:34 2001 Tim Janik <timj@gtk.org>
* ghook.[hc]: made hook ids a gulong.
2001-04-20 Dan Winship <danw@ximian.com>
* configure.in: Add a check for the Darwin dynamic linker. Use

View File

@ -1,3 +1,7 @@
Sun Apr 29 00:37:34 2001 Tim Janik <timj@gtk.org>
* ghook.[hc]: made hook ids a gulong.
2001-04-20 Dan Winship <danw@ximian.com>
* configure.in: Add a check for the Darwin dynamic linker. Use

View File

@ -1,3 +1,7 @@
Sun Apr 29 00:37:34 2001 Tim Janik <timj@gtk.org>
* ghook.[hc]: made hook ids a gulong.
2001-04-20 Dan Winship <danw@ximian.com>
* configure.in: Add a check for the Darwin dynamic linker. Use

View File

@ -66,6 +66,7 @@ only one statement is expected by the compiler.
Portable way to copy <type>va_list</type> variables.
</para>
<!-- # Unused Parameters # -->
@ap1: the <type>va_list</type> variable to place a copy of @ap2 in.
@ap2: a <type>va_list</type>.

View File

@ -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;

View File

@ -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,

View File

@ -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;

View File

@ -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,

View File

@ -1,3 +1,15 @@
Sat Apr 28 23:39:42 2001 Tim Janik <timj@gtk.org>
* 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 <hp@redhat.com>
* gobject.c (g_object_get_valist): We were returning junk memory

View File

@ -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 \

View File

@ -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

399
gobject/glib-mkenums Executable file
View File

@ -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 =~ /<</) {
$seenbitshift = 1;
}
if (defined $options) {
my %options = parse_trigraph($options);
if (!defined $options{skip}) {
push @entries, [ $name, $options{nick} ];
}
} else {
push @entries, [ $name ];
}
} elsif (m@^\s*\#@) {
# ignore preprocessor directives
} else {
print STDERR "$0: $file_name:$.: Failed to parse `$_'\n";
}
}
return 0;
}
sub version {
print STDERR "glib-mkenums version glib-2.0\n"; # FIXME: autogen version?
print STDERR "glib-mkenums comes with ABSOLUTELY NO WARRANTY.\n";
print STDERR "You may redistribute copies of glib-mkenums under the terms of\n";
print STDERR "the GNU General Public License which can be found in the\n";
print STDERR "GLib source package. Sources, examples and contact\n";
print STDERR "information are available at http://www.gtk.org\n";
exit 0;
}
sub usage {
print STDERR "Usage: glib-mkenums [options] [files...]\n";
print STDERR " --fhead <text> output file header\n";
print STDERR " --fprod <text> per input file production\n";
print STDERR " --ftail <text> output file trailer\n";
print STDERR " --eprod <text> per enum text (produced prior to value itarations)\n";
print STDERR " --vhead <text> value header, produced before iterating over enum values\n";
print STDERR " --vprod <text> value text, produced for each enum value\n";
print STDERR " --vtail <text> value tail, produced after iterating over enum values\n";
print STDERR " --comments <text> 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";
}

148
gobject/glib-mkenums.1 Normal file
View File

@ -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 <text>
Put out <text> prior to processing input files.
.TP
\fI--fprod <text>
Put out <text> everytime a new input file is being processed.
.TP
\fI--ftail <text>
Put out <text> after all input files have been processed.
.TP
\fI--eprod <text>
Put out <text> everytime an enum is encountered in the input files.
.TP
\fI--vhead <text>
Put out <text> before iterating over the set of values of an enum.
.TP
\fI--vprod <text>
Put out <text> for every value of an enum.
.TP
\fI--vtail <text>
Put out <text> after iterating over all values of an enum.
.TP
\fI--comments <text>
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 <timj@gtk.org> and Owen Taylor <otaylor@redhat.com>.
.PP
This manual page was provided by Tim Janik <timj@gtk.org>.

399
gobject/glib-mkenums.in Executable file
View File

@ -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 =~ /<</) {
$seenbitshift = 1;
}
if (defined $options) {
my %options = parse_trigraph($options);
if (!defined $options{skip}) {
push @entries, [ $name, $options{nick} ];
}
} else {
push @entries, [ $name ];
}
} elsif (m@^\s*\#@) {
# ignore preprocessor directives
} else {
print STDERR "$0: $file_name:$.: Failed to parse `$_'\n";
}
}
return 0;
}
sub version {
print STDERR "glib-mkenums version glib-2.0\n"; # FIXME: autogen version?
print STDERR "glib-mkenums comes with ABSOLUTELY NO WARRANTY.\n";
print STDERR "You may redistribute copies of glib-mkenums under the terms of\n";
print STDERR "the GNU General Public License which can be found in the\n";
print STDERR "GLib source package. Sources, examples and contact\n";
print STDERR "information are available at http://www.gtk.org\n";
exit 0;
}
sub usage {
print STDERR "Usage: glib-mkenums [options] [files...]\n";
print STDERR " --fhead <text> output file header\n";
print STDERR " --fprod <text> per input file production\n";
print STDERR " --ftail <text> output file trailer\n";
print STDERR " --eprod <text> per enum text (produced prior to value itarations)\n";
print STDERR " --vhead <text> value header, produced before iterating over enum values\n";
print STDERR " --vprod <text> value text, produced for each enum value\n";
print STDERR " --vtail <text> value tail, produced after iterating over enum values\n";
print STDERR " --comments <text> 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";
}

View File

@ -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,

View File

@ -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,