[kdbus] Do not set body message if signature field is empty
[platform/upstream/glib.git] / gobject / glib-mkenums.in
index 2f8bb05..b776e1f 100755 (executable)
@@ -1,15 +1,29 @@
-#!@PERL_PATH@ -w
+#! @PERL_PATH@
+
+use warnings;
+use File::Basename;
+use Safe;
 
 # glib-mkenums.pl 
 # Information about the current enumeration
 my $flags;                     # Is enumeration a bitmask?
+my $option_underscore_name;    # Overriden underscore variant of the enum name
+                               # for example to fix the cases we don't get the
+                               # mixed-case -> underscorized transform right.
+my $option_lowercase_name;     # DEPRECATED.  A lower case name to use as part
+                               # of the *_get_type() function, instead of the
+                               # one that we guess. For instance, when an enum
+                               # uses abnormal capitalization and we can not
+                               # guess where to put the underscores.
 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 $enumname_prefix;           # prefix of $enumname
 my $enumindex = 0;             # Global enum counter
 my $firstenum = 1;             # Is this the first enumeration per file?
 my @entries;                   # [ $name, $val ] for each entry
+my $sandbox = Safe->new;        # sandbox for safe evaluation of expressions
 
 sub parse_trigraph {
     my $opts = shift;
@@ -81,7 +95,9 @@ sub parse_entries {
         if (m@^\s*
               (\w+)\s*                   # name
               (?:=(                      # value
-                   (?:[^,/]|/(?!\*))*
+                  \s*\w+\s*\(.*\)\s*       # macro with multiple args
+                  |                        # OR
+                   (?:[^,/]|/(?!\*))*       # anything but a comma or comment
                   ))?,?\s*
               (?:/\*<                    # options
                 (([^*]|\*(?!/))*)
@@ -97,10 +113,10 @@ sub parse_entries {
            if (defined $options) {
                my %options = parse_trigraph($options);
                if (!defined $options{skip}) {
-                   push @entries, [ $name, $options{nick} ];
+                   push @entries, [ $name, $value, $options{nick} ];
                }
            } else {
-               push @entries, [ $name ];
+               push @entries, [ $name, $value ];
            }
        } elsif (m@^\s*\#@) {
            # ignore preprocessor directives
@@ -113,41 +129,52 @@ sub parse_entries {
 }
 
 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";
+    print "glib-mkenums version glib-@GLIB_VERSION@\n";
+    print "glib-mkenums comes with ABSOLUTELY NO WARRANTY.\n";
+    print "You may redistribute copies of glib-mkenums under the terms of\n";
+    print "the GNU General Public License which can be found in the\n";
+    print "GLib source package. Sources, examples and contact\n";
+    print "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";
+    print "Usage:\n";
+    print "  glib-mkenums [OPTION...] [FILES...]\n\n";
+    print "Help Options:\n";
+    print "  -h, --help            Show this help message\n\n";
+    print "Utility Options:\n";
+    print "  --identifier-prefix <text>   Identifier prefix\n";
+    print "  --symbol-prefix <text>       Symbol prefix\n";
+    print "  --fhead <text>               Output file header\n";
+    print "  --fprod <text>               Per input file production\n";
+    print "  --ftail <text>               Output file trailer\n";
+    print "  --eprod <text>               Per enum text (produced prior to value itarations)\n";
+    print "  --vhead <text>               Value header, produced before iterating over enum values\n";
+    print "  --vprod <text>               Value text, produced for each enum value\n";
+    print "  --vtail <text>               Value tail, produced after iterating over enum values\n";
+    print "  --comments <text>            Comment structure\n";
+    print "  --template file              Template file\n";
+    print "  -v, --version                Print version informations\n\n";
+    print "Production text substitutions:\n";
+    print "  \@EnumName\@            PrefixTheXEnum\n";
+    print "  \@enum_name\@           prefix_the_xenum\n";
+    print "  \@ENUMNAME\@            PREFIX_THE_XENUM\n";
+    print "  \@ENUMSHORT\@           THE_XENUM\n";
+    print "  \@ENUMPREFIX\@          PREFIX\n";
+    print "  \@VALUENAME\@           PREFIX_THE_XVALUE\n";
+    print "  \@valuenick\@           the-xvalue\n";
+    print "  \@valuenum\@            the integer value (limited support, Since: 2.26)\n";
+    print "  \@type\@                either enum or flags\n";
+    print "  \@Type\@                either Enum or Flags\n";
+    print "  \@TYPE\@                either ENUM or FLAGS\n";
+    print "  \@filename\@            name of current input file\n";
+    print "  \@basename\@            base name of the current input file (Since: 2.22)\n";
     exit 0;
 }
 
 # production variables:
+my $idprefix = "";    # "G", "Gtk", etc
+my $symprefix = "";   # "g", "gtk", etc, if not just lc($idprefix)
 my $fhead = "";   # output file header
 my $fprod = "";   # per input file production
 my $ftail = "";   # output file trailer
@@ -155,26 +182,75 @@ 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\@ */";
+my $comment_tmpl = "";   # comment template
+
+sub read_template_file {
+  my ($file) = @_;
+  my %tmpl = ('file-header', $fhead, 
+             'file-production', $fprod, 
+             'file-tail', $ftail, 
+             'enumeration-production', $eprod,
+             'value-header', $vhead,
+             'value-production', $vprod,
+             'value-tail', $vtail,
+             'comment', $comment_tmpl);
+  my $in = 'junk';
+  open (FILE, $file) || die "Can't open $file: $!\n";
+  while (<FILE>) {
+    if (/^\/\*\*\*\s+(BEGIN|END)\s+([\w-]+)\s+\*\*\*\//) {
+      if (($in eq 'junk') && ($1 eq 'BEGIN') && (exists($tmpl{$2}))) {
+       $in = $2;
+       next;
+      }
+      elsif (($in eq $2) && ($1 eq 'END') && (exists($tmpl{$2}))) {
+       $in = 'junk';
+       next;
+      } else {
+         die "Malformed template file $file\n";
+      }
+    }
+    if (!($in eq 'junk')) {
+       $tmpl{$in} .= $_;
+    }
+  }
+  close (FILE);
+  if (!($in eq 'junk')) {
+      die "Malformed template file $file\n";
+  }
+  $fhead = $tmpl{'file-header'};
+  $fprod = $tmpl{'file-production'};
+  $ftail = $tmpl{'file-tail'};
+  $eprod = $tmpl{'enumeration-production'};
+  $vhead = $tmpl{'value-header'};
+  $vprod = $tmpl{'value-production'};
+  $vtail = $tmpl{'value-tail'};
+  $comment_tmpl = $tmpl{'comment'};
+
+  # default to C-style comments
+  $comment_tmpl = "/* \@comment\@ */" if $comment_tmpl eq "";
+}
 
 if (!defined $ARGV[0]) {
     usage;
 }
-while ($_ = $ARGV[0], /^-/) {
+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; }
+    if (/^--template$/)                      { read_template_file (shift); }
+    elsif (/^--identifier-prefix$/)          { $idprefix = shift }
+    elsif (/^--symbol-prefix$/)              { $symprefix = shift }
+    elsif (/^--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; }
+    last if not defined($ARGV[0]);
 }
 
 # put auto-generation comment
@@ -186,10 +262,13 @@ while ($_ = $ARGV[0], /^-/) {
 
 if (length($fhead)) {
     my $prod = $fhead;
+    my $base = basename ($ARGV[0]);
 
-    $prod =~ s/\@filename\@/$ARGV/g;
+    $prod =~ s/\@filename\@/$ARGV[0]/g;
+    $prod =~ s/\@basename\@/$base/g;
     $prod =~ s/\\a/\a/g; $prod =~ s/\\b/\b/g; $prod =~ s/\\t/\t/g; $prod =~ s/\\n/\n/g;
     $prod =~ s/\\f/\f/g; $prod =~ s/\\r/\r/g;
+    chomp ($prod);
                
     print "$prod\n";
 }
@@ -211,24 +290,43 @@ while (<>) {
        ([^*]+|\*(?!/))*
        \*/@@gx;
        
+    # ignore forward declarations
+    next if /^\s*typedef\s+enum.*;/;
+
     if (m@^\s*typedef\s+enum\s*
            ({)?\s*
            (?:/\*<
              (([^*]|\*(?!/))*)
             >\s*\*/)?
+           \s*({)?
          @x) {
        if (defined $2) {
            my %options = parse_trigraph ($2);
            next if defined $options{skip};
            $enum_prefix = $options{prefix};
            $flags = $options{flags};
+           $option_lowercase_name = $options{lowercase_name};
+           $option_underscore_name = $options{underscore_name};
        } else {
            $enum_prefix = undef;
            $flags = undef;
+           $option_lowercase_name = undef;
+           $option_underscore_name = undef;
+       }
+       if (defined $option_lowercase_name) {
+           if (defined $option_underscore_name) {
+               print STDERR "$0: $ARGV:$.: lowercase_name overriden with underscore_name\n";
+               $option_lowercase_name = undef;
+           } else {
+               print STDERR "$0: $ARGV:$.: lowercase_name is deprecated, use underscore_name\n";
+           }
        }
        # Didn't have trailing '{' look on next lines
-       if (!defined $1) {
+       if (!defined $1 && !defined $4) {
            while (<>) {
+               if (eof) {
+                   die "Hit end of file while parsing enum in $ARGV";
+               }
                if (s/^\s*\{//) {
                    last;
                }
@@ -249,7 +347,7 @@ while (<>) {
        # Autogenerate a prefix
        if (!defined $enum_prefix) {
            for (@entries) {
-               my $nick = $_->[1];
+               my $nick = $_->[2];
                if (!defined $nick) {
                    my $name = $_->[0];
                    if (defined $enum_prefix) {
@@ -275,40 +373,75 @@ while (<>) {
        }
        
        for $entry (@entries) {
-           my ($name,$nick) = @{$entry};
+           my ($name,$num,$nick) = @{$entry};
             if (!defined $nick) {
                ($nick = $name) =~ s/^$enum_prefix//;
                $nick =~ tr/_/-/;
                $nick = lc($nick);
-               @{$entry} = ($name, $nick);
+               @{$entry} = ($name, $num, $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);
+       if (defined $option_underscore_name) {
+           $enumlong = uc $option_underscore_name;
+           $enumsym = lc $option_underscore_name;
+           $enumshort = $enumlong;
+           $enumshort =~ s/^[A-Z][A-Z0-9]*_//;
+
+           $enumname_prefix = $enumlong;
+           $enumname_prefix =~ s/_$enumshort$//;
+       } elsif (!$symprefix && !$idprefix) {
+           # 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);
+
+           $enumname_prefix = $enumname;
+           $enumname_prefix =~ s/^([A-Z][a-z]*).*$/$1/;
+           $enumname_prefix = uc($enumname_prefix);
+
+           $enumlong = uc($enspace) . "_" . $enumshort;
+           $enumsym = lc($enspace) . "_" . lc($enumshort);
+
+           if (defined($option_lowercase_name)) {
+               $enumsym = $option_lowercase_name;
+           }
+       } else {
+           $enumshort = $enumname;
+           if ($idprefix) {
+               $enumshort =~ s/^${idprefix}//;
+           } else {
+               $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);
+           $enumname_prefix = $symprefix && uc($symprefix) || uc($idprefix);
+
+           $enumlong = $enumname_prefix . "_" . $enumshort;
+           $enumsym = lc($enumlong);
+       }
 
        if ($firstenum) {
            $firstenum = 0;
            
            if (length($fprod)) {
                my $prod = $fprod;
+               my $base = basename ($ARGV);
 
                $prod =~ s/\@filename\@/$ARGV/g;
+               $prod =~ s/\@basename\@/$base/g;
                $prod =~ s/\\a/\a/g; $prod =~ s/\\b/\b/g; $prod =~ s/\\t/\t/g; $prod =~ s/\\n/\n/g;
                $prod =~ s/\\f/\f/g; $prod =~ s/\\r/\r/g;
+               chomp ($prod);
                
                print "$prod\n";
            }
@@ -321,11 +454,13 @@ while (<>) {
            $prod =~ s/\@EnumName\@/$enumname/g;
            $prod =~ s/\@ENUMSHORT\@/$enumshort/g;
            $prod =~ s/\@ENUMNAME\@/$enumlong/g;
+           $prod =~ s/\@ENUMPREFIX\@/$enumname_prefix/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/\\f/\f/g; $prod =~ s/\\r/\r/g;
+            chomp ($prod);
 
            print "$prod\n";
        }
@@ -337,29 +472,53 @@ while (<>) {
             $prod =~ s/\@EnumName\@/$enumname/g;
             $prod =~ s/\@ENUMSHORT\@/$enumshort/g;
             $prod =~ s/\@ENUMNAME\@/$enumlong/g;
+           $prod =~ s/\@ENUMPREFIX\@/$enumname_prefix/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/\\f/\f/g; $prod =~ s/\\r/\r/g;
+            chomp ($prod);
            
             print "$prod\n";
        }
 
        if (length($vprod)) {
            my $prod = $vprod;
+            my $next_num = 0;
            
            $prod =~ s/\\a/\a/g; $prod =~ s/\\b/\b/g; $prod =~ s/\\t/\t/g; $prod =~ s/\\n/\n/g;
            $prod =~ s/\\f/\f/g; $prod =~ s/\\r/\r/g;
            for (@entries) {
-               my ($name,$nick) = @{$_};
-               my $tmp_prod = $vprod;
+               my ($name,$num,$nick) = @{$_};
+               my $tmp_prod = $prod;
+
+                if ($prod =~ /\@valuenum\@/) {
+                    # only attempt to eval the value if it is requested
+                    # this prevents us from throwing errors otherwise
+                    if (defined $num) {
+                        # use sandboxed perl evaluation as a reasonable
+                        # approximation to C constant folding
+                        $num = $sandbox->reval ($num);
+
+                        # make sure it parsed to an integer
+                        if (!defined $num or $num !~ /^-?\d+$/) {
+                            die "Unable to parse enum value '$num'";
+                        }
+                    } else {
+                        $num = $next_num;
+                    }
+
+                    $tmp_prod =~ s/\@valuenum\@/$num/g;
+                    $next_num = $num + 1;
+                }
 
                $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; }
+               chomp ($tmp_prod);
 
                print "$tmp_prod\n";
            }
@@ -372,11 +531,13 @@ while (<>) {
             $prod =~ s/\@EnumName\@/$enumname/g;
             $prod =~ s/\@ENUMSHORT\@/$enumshort/g;
             $prod =~ s/\@ENUMNAME\@/$enumlong/g;
+           $prod =~ s/\@ENUMPREFIX\@/$enumname_prefix/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/\\f/\f/g; $prod =~ s/\\r/\r/g;
+            chomp ($prod);
            
             print "$prod\n";
        }
@@ -385,10 +546,13 @@ while (<>) {
 
 if (length($ftail)) {
     my $prod = $ftail;
+    my $base = basename ($ARGV);
 
     $prod =~ s/\@filename\@/$ARGV/g;
+    $prod =~ s/\@basename\@/$base/g;
     $prod =~ s/\\a/\a/g; $prod =~ s/\\b/\b/g; $prod =~ s/\\t/\t/g; $prod =~ s/\\n/\n/g;
     $prod =~ s/\\f/\f/g; $prod =~ s/\\r/\r/g;
+    chomp ($prod);
                
     print "$prod\n";
 }