Blame gdk/makeenums.pl

Packit Service fb6fa5
#!/usr/bin/perl -w
Packit Service fb6fa5
Packit Service fb6fa5
# Information about the current enumeration
Packit Service fb6fa5
Packit Service fb6fa5
my $flags;			# Is enumeration a bitmask
Packit Service fb6fa5
my $seenbitshift;			# Have we seen bitshift operators?
Packit Service fb6fa5
my $prefix;			# Prefix for this enumeration
Packit Service fb6fa5
my $enumname;			# Name for this enumeration
Packit Service fb6fa5
my $firstenum = 1;		# Is this the first enumeration in file?
Packit Service fb6fa5
my @entries;			# [ $name, $val ] for each entry
Packit Service fb6fa5
Packit Service fb6fa5
sub parse_options {
Packit Service fb6fa5
    my $opts = shift;
Packit Service fb6fa5
    my @opts;
Packit Service fb6fa5
Packit Service fb6fa5
    for $opt (split /\s*,\s*/, $opts) {
Packit Service fb6fa5
	my ($key,$val) = $opt =~ /\s*(\w+)(?:=(\S+))?/;
Packit Service fb6fa5
	defined $val or $val = 1;
Packit Service fb6fa5
	push @opts, $key, $val;
Packit Service fb6fa5
    }
Packit Service fb6fa5
    @opts;
Packit Service fb6fa5
}
Packit Service fb6fa5
sub parse_entries {
Packit Service fb6fa5
    my $file = shift;
Packit Service fb6fa5
Packit Service fb6fa5
    while (<$file>) {
Packit Service fb6fa5
	# Read lines until we have no open comments
Packit Service fb6fa5
	while (m@/\*
Packit Service fb6fa5
	       ([^*]|\*(?!/))*$
Packit Service fb6fa5
	       @x) {
Packit Service fb6fa5
	    my $new;
Packit Service fb6fa5
	    defined ($new = <$file>) || die "Unmatched comment";
Packit Service fb6fa5
	    $_ .= $new;
Packit Service fb6fa5
	}
Packit Service fb6fa5
	# Now strip comments
Packit Service fb6fa5
	s@/\*(?!<)
Packit Service fb6fa5
	    ([^*]+|\*(?!/))*
Packit Service fb6fa5
	   \*/@@gx;
Packit Service fb6fa5
	
Packit Service fb6fa5
	s@\n@ @;
Packit Service fb6fa5
	
Packit Service fb6fa5
	next if m@^\s*$@;
Packit Service fb6fa5
Packit Service fb6fa5
	# Handle include files
Packit Service fb6fa5
	if (/^\#include\s*<([^>]*)>/ ) {
Packit Service fb6fa5
            my $file= "../$1";
Packit Service fb6fa5
	    open NEWFILE, $file or die "Cannot open include file $file: $!\n";
Packit Service fb6fa5
	    
Packit Service fb6fa5
	    if (parse_entries (\*NEWFILE)) {
Packit Service fb6fa5
		return 1;
Packit Service fb6fa5
	    } else {
Packit Service fb6fa5
		next;
Packit Service fb6fa5
	    }
Packit Service fb6fa5
	}
Packit Service fb6fa5
	
Packit Service fb6fa5
	if (/^\s*\}\s*(\w+)/) {
Packit Service fb6fa5
	    $enumname = $1;
Packit Service fb6fa5
	    return 1;
Packit Service fb6fa5
	}
Packit Service fb6fa5
Packit Service fb6fa5
	if (m@^\s*
Packit Service fb6fa5
              (\w+)\s*		         # name
Packit Service fb6fa5
              (?:=(                      # value
Packit Service fb6fa5
                   (?:[^,/]|/(?!\*))*
Packit Service fb6fa5
                  ))?,?\s*
Packit Service fb6fa5
              (?:/\*<		         # options 
Packit Service fb6fa5
                (([^*]|\*(?!/))*)
Packit Service fb6fa5
               >\*/)?
Packit Service fb6fa5
              \s*$
Packit Service fb6fa5
             @x) {
Packit Service fb6fa5
	    my ($name, $value, $options) = ($1,$2,$3);
Packit Service fb6fa5
Packit Service fb6fa5
	    if (!defined $flags && defined $value && $value =~ /<</) {
Packit Service fb6fa5
		$seenbitshift = 1;
Packit Service fb6fa5
	    }
Packit Service fb6fa5
	    if (defined $options) {
Packit Service fb6fa5
		my %options = parse_options($options);
Packit Service fb6fa5
		if (!defined $options{skip}) {
Packit Service fb6fa5
		    push @entries, [ $name, $options{nick} ];
Packit Service fb6fa5
		}
Packit Service fb6fa5
	    } else {
Packit Service fb6fa5
		push @entries, [ $name ];
Packit Service fb6fa5
	    }
Packit Service fb6fa5
	} else {
Packit Service fb6fa5
	    print STDERR "Can't understand: $_\n";
Packit Service fb6fa5
	}
Packit Service fb6fa5
    }
Packit Service fb6fa5
    return 0;
Packit Service fb6fa5
}
Packit Service fb6fa5
Packit Service fb6fa5
Packit Service fb6fa5
my $gen_arrays = 0;
Packit Service fb6fa5
my $gen_defs = 0;
Packit Service fb6fa5
my $gen_includes = 0;
Packit Service fb6fa5
my $gen_cfile = 0;
Packit Service fb6fa5
Packit Service fb6fa5
# Parse arguments
Packit Service fb6fa5
Packit Service fb6fa5
if (@ARGV) {
Packit Service fb6fa5
    if ($ARGV[0] eq "arrays") {
Packit Service fb6fa5
	shift @ARGV;
Packit Service fb6fa5
	$gen_arrays = 1;
Packit Service fb6fa5
    } elsif ($ARGV[0] eq "defs") {
Packit Service fb6fa5
	shift @ARGV;
Packit Service fb6fa5
	$gen_defs = 1;
Packit Service fb6fa5
    } elsif ($ARGV[0] eq "include") {
Packit Service fb6fa5
	shift @ARGV;
Packit Service fb6fa5
	$gen_includes = 1;
Packit Service fb6fa5
    } elsif ($ARGV[0] eq "cfile") {
Packit Service fb6fa5
	shift @ARGV;
Packit Service fb6fa5
	$gen_cfile = 1;
Packit Service fb6fa5
    }
Packit Service fb6fa5
}
Packit Service fb6fa5
Packit Service fb6fa5
if ($gen_defs) {
Packit Service fb6fa5
    print ";; generated by makeenums.pl  ; -*- scheme -*-\n\n";
Packit Service fb6fa5
} else {
Packit Service fb6fa5
    print "/* Generated by makeenums.pl */\n\n";
Packit Service fb6fa5
}
Packit Service fb6fa5
Packit Service fb6fa5
if ($gen_includes) {
Packit Service fb6fa5
  print "#ifndef __GDK_ENUM_TYPES_H__\n";
Packit Service fb6fa5
  print "#define __GDK_ENUM_TYPES_H__\n";
Packit Service fb6fa5
}
Packit Service fb6fa5
Packit Service fb6fa5
if ($gen_cfile) {
Packit Service fb6fa5
  print "#include \"gdk.h\"\n";
Packit Service fb6fa5
}
Packit Service fb6fa5
Packit Service fb6fa5
ENUMERATION:
Packit Service fb6fa5
while (<>) {
Packit Service fb6fa5
    if (eof) {
Packit Service fb6fa5
	close (ARGV);		# reset line numbering
Packit Service fb6fa5
	$firstenum = 1;		# Flag to print filename at next enum
Packit Service fb6fa5
    }
Packit Service fb6fa5
Packit Service fb6fa5
    if (m@^\s*typedef\s+enum\s*
Packit Service fb6fa5
           ({)?\s*
Packit Service fb6fa5
           (?:/\*<
Packit Service fb6fa5
             (([^*]|\*(?!/))*)
Packit Service fb6fa5
            >\*/)?
Packit Service fb6fa5
         @x) {
Packit Service fb6fa5
      print "\n";
Packit Service fb6fa5
	if (defined $2) {
Packit Service fb6fa5
	    my %options = parse_options($2);
Packit Service fb6fa5
	    $prefix = $options{prefix};
Packit Service fb6fa5
	    $flags = $options{flags};
Packit Service fb6fa5
	} else {
Packit Service fb6fa5
	    $prefix = undef;
Packit Service fb6fa5
	    $flags = undef;
Packit Service fb6fa5
	}
Packit Service fb6fa5
	# Didn't have trailing '{' look on next lines
Packit Service fb6fa5
	if (!defined $1) {
Packit Service fb6fa5
	    while (<>) {
Packit Service fb6fa5
		if (s/^\s*\{//) {
Packit Service fb6fa5
		    last;
Packit Service fb6fa5
		}
Packit Service fb6fa5
	    }
Packit Service fb6fa5
	}
Packit Service fb6fa5
Packit Service fb6fa5
	$seenbitshift = 0;
Packit Service fb6fa5
	@entries = ();
Packit Service fb6fa5
Packit Service fb6fa5
	# Now parse the entries
Packit Service fb6fa5
	parse_entries (\*ARGV);
Packit Service fb6fa5
Packit Service fb6fa5
	# figure out if this was a flags or enums enumeration
Packit Service fb6fa5
Packit Service fb6fa5
	if (!defined $flags) {
Packit Service fb6fa5
	    $flags = $seenbitshift;
Packit Service fb6fa5
	}
Packit Service fb6fa5
Packit Service fb6fa5
	# Autogenerate a prefix
Packit Service fb6fa5
Packit Service fb6fa5
	if (!defined $prefix) {
Packit Service fb6fa5
	    for (@entries) {
Packit Service fb6fa5
		my $name = $_->[0];
Packit Service fb6fa5
		if (defined $prefix) {
Packit Service fb6fa5
		    my $tmp = ~ ($name ^ $prefix);
Packit Service fb6fa5
		    ($tmp) = $tmp =~ /(^\xff*)/;
Packit Service fb6fa5
		    $prefix = $prefix & $tmp;
Packit Service fb6fa5
		} else {
Packit Service fb6fa5
		    $prefix = $name;
Packit Service fb6fa5
		}
Packit Service fb6fa5
	    }
Packit Service fb6fa5
	    # Trim so that it ends in an underscore
Packit Service fb6fa5
	    $prefix =~ s/_[^_]*$/_/;
Packit Service fb6fa5
	}
Packit Service fb6fa5
	
Packit Service fb6fa5
	for $entry (@entries) {
Packit Service fb6fa5
	    my ($name,$nick) = @{$entry};
Packit Service fb6fa5
            if (!defined $nick) {
Packit Service fb6fa5
 	        ($nick = $name) =~ s/^$prefix//;
Packit Service fb6fa5
	        $nick =~ tr/_/-/;
Packit Service fb6fa5
	        $nick = lc($nick);
Packit Service fb6fa5
	        @{$entry} = ($name, $nick);
Packit Service fb6fa5
            }
Packit Service fb6fa5
	}
Packit Service fb6fa5
Packit Service fb6fa5
	# Spit out the output
Packit Service fb6fa5
Packit Service fb6fa5
        my $valuename = $enumname;
Packit Service fb6fa5
        $valuename =~ s/([^A-Z])([A-Z])/$1_$2/g;
Packit Service fb6fa5
        $valuename =~ s/([A-Z][A-Z])([A-Z][0-9a-z])/$1_$2/g;
Packit Service fb6fa5
        $valuename = lc($valuename);
Packit Service fb6fa5
Packit Service fb6fa5
        my $typemacro = $enumname;
Packit Service fb6fa5
        $typemacro =~ s/([^A-Z])([A-Z])/$1_$2/g;
Packit Service fb6fa5
        $typemacro =~ s/([A-Z][A-Z])([A-Z][0-9a-z])/$1_$2/g;
Packit Service fb6fa5
        $typemacro = uc($valuename);
Packit Service fb6fa5
        $typemacro =~ s/GDK_/GDK_TYPE_/g;
Packit Service fb6fa5
Packit Service fb6fa5
	if ($gen_defs) {
Packit Service fb6fa5
	    if ($firstenum) {
Packit Service fb6fa5
		print qq(\n; enumerations from "$ARGV"\n);
Packit Service fb6fa5
		$firstenum = 0;
Packit Service fb6fa5
	    }
Packit Service fb6fa5
Packit Service fb6fa5
	    print "\n(define-".($flags ? "flags" : "enum")." $enumname";
Packit Service fb6fa5
Packit Service fb6fa5
	    for (@entries) {
Packit Service fb6fa5
		my ($name,$nick) = @{$_};
Packit Service fb6fa5
		print "\n   ($nick $name)";
Packit Service fb6fa5
	    }
Packit Service fb6fa5
	    print ")\n";
Packit Service fb6fa5
Packit Service fb6fa5
	} elsif ($gen_arrays) {
Packit Service fb6fa5
Packit Service fb6fa5
	    print "static const GtkEnumValue _${valuename}_values[] = {\n";
Packit Service fb6fa5
	    for (@entries) {
Packit Service fb6fa5
		my ($name,$nick) = @{$_};
Packit Service fb6fa5
		print qq(  { $name, "$name", "$nick" },\n);
Packit Service fb6fa5
	    }
Packit Service fb6fa5
	    print "  { 0, NULL, NULL }\n";
Packit Service fb6fa5
	    print "};\n";
Packit Service fb6fa5
	} elsif ($gen_includes) {
Packit Service fb6fa5
            print "GType ${valuename}_get_type (void);\n";
Packit Service fb6fa5
            print "#define ${typemacro} ${valuename}_get_type ()\n";
Packit Service fb6fa5
          } elsif ($gen_cfile) {
Packit Service fb6fa5
            print (<
Packit Service fb6fa5
GType
Packit Service fb6fa5
${valuename}_get_type (void)
Packit Service fb6fa5
{
Packit Service fb6fa5
  static GType etype = 0;
Packit Service fb6fa5
  if (etype == 0)
Packit Service fb6fa5
    {
Packit Service fb6fa5
EOF
Packit Service fb6fa5
            if ($flags) {
Packit Service fb6fa5
              print "      static const GFlagsValue values[] = {\n";
Packit Service fb6fa5
            } else {
Packit Service fb6fa5
              print "      static const GEnumValue values[] = {\n";
Packit Service fb6fa5
            }
Packit Service fb6fa5
            for (@entries) {
Packit Service fb6fa5
              my ($name,$nick) = @{$_};
Packit Service fb6fa5
              print qq(        { $name, "$name", "$nick" },\n);
Packit Service fb6fa5
            }
Packit Service fb6fa5
	    print "        { 0, NULL, NULL }\n";
Packit Service fb6fa5
	    print "      };\n";
Packit Service fb6fa5
Packit Service fb6fa5
            if ($flags) {
Packit Service fb6fa5
              print "      etype = g_flags_register_static (\"$enumname\", values);\n";
Packit Service fb6fa5
            } else {
Packit Service fb6fa5
              print "      etype = g_enum_register_static (\"$enumname\", values);\n";
Packit Service fb6fa5
            }
Packit Service fb6fa5
Packit Service fb6fa5
            print (<
Packit Service fb6fa5
    }
Packit Service fb6fa5
  return etype;
Packit Service fb6fa5
}
Packit Service fb6fa5
EOF
Packit Service fb6fa5
          }
Packit Service fb6fa5
        print "\n";
Packit Service fb6fa5
      }
Packit Service fb6fa5
  }
Packit Service fb6fa5
Packit Service fb6fa5
Packit Service fb6fa5
if ($gen_includes) {
Packit Service fb6fa5
  print "#endif /* __GDK_ENUMS_H__ */\n";
Packit Service fb6fa5
}