#!/usr/bin/perl use warnings; use strict; our $fn = $ARGV[0] || "Scintilla.iface"; our %cat; our $cat; our $enu; our $pre; our $lex; open FH, $fn or die "Failed to open iface file: $fn: $!\n"; our $last_comment = ''; ## cat -> start a category ## fun -> a function ## get -> a property get function ## set -> a property set function ## val -> definition of a constant ## evt -> an event ## enu -> associate an enumeration with a set of vals with a prefix ## lex -> associate a lexer with the lexical classes it produces open ENU, ">enums.h" or die "Failed to open enums.h file: $!\n"; for () { chomp;chomp;chomp; s/[\r\n]+//g; next if /^##/; if(/^cat\s+(.*)\s*$/) { last if $1 eq 'Deprecated'; } if(/^$/) { $last_comment = ''; next; } if(/^\s*#\s*(.*)\s*$/) { $last_comment .= $1; next; } if(/^(\w{3})\s+(.*)\s*$/) { my $cmd = $1; my $text = $2; if($cmd eq 'cat') { if(!defined $cat) { $cat{$text} = { 'val' => {}, 'pre' => {}, 'enu' => {}, 'fun' => {}, 'evt' => {} }; } $cat = $cat{$text}; $pre = $cat{$text}{'pre'}; next; } elsif($cmd eq 'lex') { # lex Python=SCLEX_PYTHON SCE_P_ # val SCE_P_DEFAULT=0 my ($lang, $macro, $prefix) = split(/[\s=]+/, $text); $enu = exists $cat->{'enu'}{$macro} ? $cat->{'enu'}{$macro} : $cat->{'enu'}{$macro}={}; $enu->{'name'} = $lang; $enu->{'prefix'} = $prefix; my $p = ((exists $pre->{$prefix}) ? $pre->{$prefix} : ($pre->{$prefix}=[])); push @$p, $macro; } elsif($cmd eq 'val') { # this is all wrong, need to compare the val name against the prefix lists my ($enam,$eval) = split(/=/, $text); $cat{'Basics'}{'val'}{$enam} = $eval; =pod for my $key (keys %$pre) { if($enam =~ /^$key/) { push @{$pre->{$key}[1]}, [$enam,$eval]; print "Adding $enam to $key\n"; } } =cut } elsif($cmd eq 'fun' || $cmd eq 'get' || $cmd eq 'set') { ## get bool GetMarginSensitiveN=2247(int margin,) # kill $lex and $enu here my ($type, $name, $id, $arg1, $arg2) = ($text =~ /(\w+)\s+(\w+)\s*=\s*(\d+)\(([^,]*),([^\)]*)\)/); #print "$cmd $type $name=$id($arg1, $arg2)\n"; #push @{}, { name = } elsif($cmd eq 'evt') { $lex = $enu = undef; # evt void StyleNeeded=2000(int position) my ($ret, $nam, $id, $args) = ($text =~ /(\w+)\s+(\w+)\s*=(\d+)\s*\(([^\)]+)\)/); #printf "evt %s %s=%i(%s)\n", $ret, $nam, $id, $args; } elsif($cmd eq 'enu') { my ($enam,@eval) = split(/[=\s]+/, $text); for my $eval (@eval) { # print "enu $enam=$eval\n"; if(exists $cat->{'enu'}{$enam}) { $enu = $cat->{'enu'}{$enam}; push @{$enu->{'prefix'}}, $eval; } else { $enu = $cat->{'enu'}{$enam} = {}; $enu->{'name'} = $enam; $enu->{'prefix'} = [ $eval ]; } my $p = ((exists $pre->{$eval}) ? $pre->{$eval} : ($pre->{$eval}=[])); push @$p, $enam; } # print "enu $enam=$eval\n"; } else { print "$cmd: $text\n"; } } } close FH; #use Data::Dumper; #print Dumper(\%cat); sub cat($) : lvalue { $cat{'Basics'}{shift()} } my @sclex; my %chomp = ( 'CHARSET' => '', 'MARKNUM' => '', 'WRAPVISUALFLAGLOC' => '', 'EOL' => '', ); my %hmapping = ( 'NULL' => 'NONE', ); for my $enu (sort keys %{cat 'enu'}) { my $te = cat('enu'); if($enu =~ /^SCLEX_/) { push @sclex, $te->{$enu}; next; } print ENU "\tstruct $te->{$enu}{'name'}\n\t{\n\t\tenum \n\t\t{\n"; if(defined $te && defined $te->{$enu}) { for my $prefix (@{$te->{$enu}{'prefix'}}) { my %tmp; for my $val (keys %{cat 'val'}) { #print "\t$val = " . cat('val')->{$val} . ",\n" if $val =~ /^$prefix/; $tmp{cat('val')->{$val}} = $val if $val =~ /^$prefix/; } for my $val (sort { if($a !~ /0x/) { $a <=> $b } else { $a cmp $b } } keys %tmp) { my @items = split '_', $tmp{$val}; shift @items; shift @items if scalar @items > 1; if(uc($items[0]) =~ /\U$te->{$enu}->{'name'}\E/) { if(scalar @items > 1) { shift @items; } else { $items[0] =~ s/\U$te->{$enu}->{'name'}\E//; } } elsif(uc($te->{$enu}->{'name'}) =~ /\U$items[0]\E/) { if(scalar @items > 1) { shift @items; } else { $items[0] =~ s/\U$te->{$enu}->{'name'}\E//; } } $items[0] =~ s/^(\d+)$/_$1/; $items[0] = $hmapping{uc($items[0])} if exists $hmapping{uc($items[0])}; shift @items if exists $chomp{uc $items[0]}; $tmp{$val} = join '_', @items; print ENU "\t\t\t$tmp{$val} = $val,\n"; } } } print ENU "\t\t};\n\t};\n\n"; } %hmapping = ( 'HJ' => 'JavaScript', 'HJA' => 'AspJavaScript', 'HB' => 'VBScript', 'HBA' => 'AspVBScript', 'HP' => 'Python', 'P' => 'Python', 'HPA' => 'AspPython', 'HPHP' => 'PHP', 'HA' => 'Haskel', # 'PL' => 'Perl', 'FS' => 'FlagShip', 'PROPS' => 'PROP', # 'H' => 'HTML', 'BAT' => 'Batch', 'AVE' => 'Avenue', 'ERR' => 'ErrorList', 'L' => 'Latex', 'MAKE' => 'Makefile', 'V' => 'Verilog', ); %chomp = ( 'CLW' => '', 'MATLAB' => '', 'SH' => '', 'PL' => '', 'SCRIPTOL' => '', 'SN' => '', 'HASKEL' => '', 'RB' => '', 'C' => '', 'ST' => '', 'T3' => '', 'B' => '', 'PROP' => '', 'FLAGSHIP' => '', 'F' => '', ); my $valr = cat 'val'; my %tmp; my $sh = ''; my %enut; my %tenu; if(open(ENUT, "enums_desc.txt")) { for () { chomp; next if /^\s*$/; /^([^\s]+)\s+(.*)$/; $enut{$1} = $2; } close ENUT; } for my $val (sort keys %{$valr}) { my @items = split '_', $val; #print "val: $val\n"; next if $items[0] ne 'SCE'; $sh = '1' . shift @items; my $nam = join '_', @items; my $enu = cat 'enu'; for my $c (sort keys %{$enu}) { next if $c !~ /^SCLEX_/; my $cat = $enu->{$c}; #next if ref $cat->{'prefix'}; #my $pre = $cat->{'prefix'}; if(ref $cat->{'prefix'}) { for my $pre (sort @{$cat->{'prefix'}}) { if(uc($val) =~ /^\U$pre\b\E/) { shift @items; my $t = ((exists $tmp{$cat->{'name'}}) ? $tmp{$cat->{'name'}} : ($tmp{$cat->{'name'}}={})); $t->{$valr->{$val}} = join('_',@items); # uc($cat->{'name'}) . "_" . # print "Add enu $cat->{'name'}\n"; # last; } } } else { my $pre = $cat->{'prefix'}; if(uc($val) =~ /^\U$pre\E/) { if(defined $items[0] && $items[0] eq 'H') { # print "H!!!!!!!!!!!!!!!!!!!\n"; $items[0] = 'HTML'; } if($items[0] eq 'HTML' && $items[1] eq 'SGML') { shift @items; } elsif($items[0] eq 'HTML') { # print "HTML: $items[1]\n"; } if(exists $chomp{uc($items[0])}) { # chomp removable items my $tmp = shift @items ; print "chomped: $tmp\n"; } if(exists $hmapping{uc($items[0])}) { my $tmp = $items[0]; $items[0] = uc($hmapping{uc($items[0])}); print "map: $tmp -> $items[0]\n"; } # shift @items if uc($cat->{'name'}) =~ /^\U$items[0]\E/ && scalar @items > 1 && uc($items[0]) ne 'HTML' && uc($items[0]) ne 'H'; if(uc($cat->{'name'}) =~ /^$items[0]\b/i && uc($items[0]) ne 'HTML' && uc($items[0]) ne 'H' && uc($items[0]) ne 'PHP') { my $pv = shift @items; print "shifted: '$pv' pre:'$pre' cname:'" . $cat->{'name'} . "' i0:'" . $items[0] . "'\n"; } shift @items if exists $chomp{uc($items[0])}; my $t = ((exists $tmp{$cat->{'name'}}) ? $tmp{$cat->{'name'}} : ($tmp{$cat->{'name'}}={})); my $name = join('_',@items); $t->{$valr->{$val}} = $name; # uc($cat->{'name'}) . "_" . # shift @items if(defined $items[0] && $items[0] =~ /^ASP/); $name = join('_',@items); $enut{$name} = '' if !exists $enut{$name}; # print "shift: '$sh'\n"; #last; } } } } =pod use Data::Dumper; print Dumper(\%tmp); exit 0; =cut #exit; print ENU "\tstruct Lex\n\t{\n"; for my $val (sort keys %tmp) { # print ENU "\t\tstruct " . ucfirst(lc($val)) . " {\n\t\t\tenum \n\t\t\t{\n"; for my $item (sort { if($a !~ /0x/) { $a <=> $b } } keys %{$tmp{$val}}) { print ENU "\t\t\t\t$tmp{$val}{$item} = " . $item . ",\n"; } print ENU "\t\t\t};\n\t\t};\n"; } print ENU "\t};\n"; close ENU; my @enutwarn; open ENUT, ">enums_desc.txt" or die "Failed to open enums_desc.txt: $!\n"; for (sort keys %enut) { push @enutwarn, $_ if($enut{$_} eq ''); my @items = split '_', $_; for my $item (@items) { for my $hm (keys %hmapping) { if(uc($item) eq uc($hmapping{$hm})) { shift @items; } } } my $name = join '_', @items; print ENUT $name . " " . $enut{$name} . "\n"; } close ENUT; =pod if(scalar @enutwarn) { print "The following ENUM elements need a short description:\n"; for (sort @enutwarn) { print "\t" . $_ . "\n"; } print "\nPlease edit enums_desc.txt to add a short blurb for each item.\n"; } =cut