Blame gdk/makeenums.pl

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