#extractdefs.pl
#Klaas Hartmann, July 2007
#
#This script extracts constants from wxWidgets include/defs.h. It stores the first and last wxWidgets
#version in which the constant was found and investigates whether a constant is implemented in wxPerl.
#
#Descriptions for constants can be added andconstants/groups of constants that we don't want added to 
#wxPerl can be specified.
# 
#Output is a csv.
#
#NB: this is very rough, to determine if a constant is in wxPerl I simply grep for it - figuring that 
#any reference means inclusion -- of course this is not very accurate.
#


#Location of wxWidgets sources, including the part of the directory name without the version number.
#Eg. if your sources are in /home/klaas/wxGTK-2.x.x/ use $widgets_prefix = '/home/klaas/wxGTK-';
my $widgets_prefix = '/home/klaas/wxGTK-';
my $wxperl_path = "/home/klaas/wxPerl/";


#Versions of wxWidgets installed (list in ascending order)
my @versions = ( '2.2.9', '2.3.4', '2.4.0', '2.4.1', '2.4.2', '2.5.1', '2.5.2', '2.5.3', '2.5.4', '2.5.5', '2.6.1', '2.6.2', '2.6.3', '2.7.0', '2.7.1', '2.7.2', '2.8.0', '2.8.2', '2.8.3', '2.8.4' );

#Descriptions to add to constants
my $description = {
    'wxALWAYS_SHOW_SB' => 'always show scroll bars for a window',
    'wxDEFAULT_CONTROL_BORDER' => 'borders for pocket pc & phone?',
    'wxFORWARD' => 'used to get sizer\'s controls',
    'wxHELP' => 'wxDialog style',
    'wxICON_ASTERISK' => 'duplicate definition of wxICON_INFORMATION',
    'wxICON_STOP' => 'duplicate definition of wxICON_HAND',
    'wxMB_DOCKABLE' => 'wxMenuBar style for detachable/dockable menu (GTK only)',
    'wxID_CLOSE_ALL' => 'event identifier',
    'wxID_CLOSE_FRAME' => 'event identifier',
    'wxID_DEFAULT' => 'event identifier',
    'wxID_DELETE' => 'event identifier and stock item (wx_stockitems.html)',
    'wxID_EDIT' => 'event identifier and stock item (wx_stockitems.html)',
    'wxID_FILE' => 'event identifier and stock item (wx_stockitems.html)',
    'wxID_FILEDLGG' => 'event identifier',
    'wxID_ICONIZE_FRAME' => 'event identifier',
    'wxID_MAXIMIZE_FRAME' => 'event identifier',
    'wxID_MORE' => 'event identifier and used in CreateButtonSizer (not implemented in wxPerl)',
    'wxID_MOVE_FRAME' => 'event identifier',
    'wxID_REPLACE' => 'event identifier and stock item (wx_stockitems.html)',
    'wxID_REPLACE_ALL' => 'event identifier',
    'wxID_RESET' => 'event identifier',
'wxID_RESIZE_FRAME' => 'event identifier',
'wxID_RESTORE_FRAME' => 'event identifier',
'wxID_SETUP' => 'event identifier and used in CreateButtonSizer (not implemented in wxPerl)',
'wxID_VIEW_DETAILS' => 'event identifier',
'wxID_VIEW_LARGEICONS' => 'event identifier',
'wxID_VIEW_LIST' => 'event identifier',
'wxID_VIEW_SMALLICONS' => 'event identifier',
'wxID_VIEW_SORTDATE' => 'event identifier',
'wxID_VIEW_SORTNAME' => 'event identifier',
'wxID_VIEW_SORTSIZE' => 'event identifier',
'wxID_VIEW_SORTTYPE' => 'event identifier',
    'wxBORDER' => 'undocumented duplicate of wx*_BORDER -- has been some suggestion that this should be the future standard',

};    

#Constants we don't want to add to wxPerl
my $omit = {
    'wxALIGN_MASK' => 'internal',
    'wxALIGN_NOT' => 'undocumented',
    'wxFIRST_HATCH' => 'internal',
    'wxLAST_HATCH' => 'internal',
    'wxVARIABLE' => 'not yet used',
    'wxFIXED' => 'not yet used',
    'wxSHRINK' => 'undocumented',
    'wxSTRETCH_NOT' => 'undocumented',
    'wxTILE' => 'undocumented',
    'WX_CC_MANIFEST' => 'internal?',
    'wx_const_case' => 'internal',
    'wx_static_case' => 'internal',
    'wx_reinterpret_cast' => 'internal',
    'wx_const_cast' => 'internal',
    'wx_static_cast' => 'internal',
    'wx_truncate_cast' => 'internal',
    'WX_OPAQUE_TYPE' => 'internal',
    'wxBACKWARD' => => 'used in CreateButtonSizer (not implemented in wxPerl)',
    'wxBI_EXPAND' => 'internal',
    'wxBIG_ENDIAN' => 'internal',
    'wxBYTE_ORDER' => 'internal',
    'wxC_CALLING_CONV' => 'internal',
    'wxCENTER_FRAME' => 'obsolete',
    'wxCMPFUNC_CONV' => 'internal',
    'CMPFUNC_CONV' => 'internal/obsolete',
    'wxColoured' => 'undocumented',
    'wxConstCast' => 'internal',
    'wxDELETE' => 'internal',
    'wxDELETEA' => 'internal',
    'wxDEPRECATED' => 'internal',
    'wxDLG_UNIT' => 'internal',
    'wxBACKINGSTORE' => 'internal',
    'wxCOLOURED' => 'internal',
    'wxEXPLICIT' => 'internal',
    'wxFIXED_LENGTH' => 'internal',
    'wxFRAME_DRAWER' => 'internal',
    'wxHAS_INT64' => 'internal',
    'wxICON_MASK' => 'internal', 
    'wxITEM_MAX' => 'internal?',
    'wxLB_INT_HEIGHT' => 'undocumented style for showing entire lines of list box only',
    'wxLITTLE_ENDIAN' => 'internal',
    'WXLPARAM' => 'internal',
    'WXWPARAM' => 'internal',
    'wxMORE' => 'used in CreateButtonSizer (not implemented in wxPerl)',
    'wxPASSWORD' => 'obsolete',
    'wxPROCESS_ENTER' => 'obsolete',
    'wxPDP_ENDIAN' => 'internal',
    'wxPOPUP_WINDOW' => 'undocumented?',
    'wxSIZE_NO_ADJUSTMENTS' => 'internal/undocumented',
    'wxSIZE_T_IS_UINT' => 'internal',
    'wxSTDCALL' => 'internal',
    'wxSTIPPLE_MASK' => 'unimplemented',
    'wxULongLong_t' => 'internal',
    'wxUSE_BASE' => 'internal',
    'wxUSE_NESTED_CLASSES' => 'internal',
    'wxUSE_PANGO' => 'internal',
    'wxVaCopy' => 'internal',
    'wxWINDOW_STYLE_MASK' => 'internal',
    'wxWS_EX_THEMED_BACKGROUND' => 'unimplemented',
    'wxRESET' => 'internal/undocumented',
    'wxSETUP' => 'internal/undocumented',

};

#Groups of constants we don't want added to wxPerl (if a constant name contains one of these it is flagged as undesirable to add
my $omitpartial = {
    'wxDF' => 'internal?',
    'wxHT' => 'internal?',
    'wxMM' => 'internal?',
    'wxMOD' => 'internal - used by wxkey_events',
    'wxTOOL' => 'internal?/undocumented',
    'wxINT16' => 'internal',
    'wxINT32' => 'internal',
    'wxINT64' => 'internal',
    'wxInt64' => 'internal',
    'wxUINT16' => 'internal',
    'wxUINT32' => 'internal',
    'wxUINT64' => 'internal',
    'wxUint64' => 'internal',
    'wxLong' => 'internal',
    'wxRA_' => 'internal/undocumented radio box options',
    'wxRB_' => 'internal/undocumented radio button options',
    'wxST_DOTS' => 'internal/undocumented static text options',
    'wxTC_' => 'internal/undocumented static text options',
    'WXUNUSED' => 'internal',
    'wxUNKNOWN_PLATFORM' => 'test',
    'wxBLIT_' => 'internal? for blit drawing (eg wxDC)',
    'wxPAPER_' => 'internal/undocument paper sizes',
    'wxPRINT_MODE_' => 'internal/undocumented print modes',
    'wxROP_' => 'internal? for blit drawing (eg wxDC)',
};


#The version we are checking
my $version;
#All info about the constants is stored in this hash
my %defs;

#For each version
foreach $version (@versions) {

    #Load defs.h into $in
    open (IN, "+<$widgets_prefix$version/include/wx/defs.h");
    @file = <IN>;
    seek IN,0,0;
    $in = ""; 

    foreach $file (@file){
        $in = $in.$file;
    }

    close IN;
    
    
    #Get enum blocks
    foreach ($in =~ /enum[^\{]*\{([^\}]*)\}/g) {
        #Remove comments
        $_ =~ s/\/\*[^\n]*?\*\// /g;
        #Get any enumerated constants
        while ($_ =~ /[\s,\n](wx[^\s\n,=()]*)[\s,\n=]/g) { add_entry($1,$version); }
        while ($_ =~ /[\s,\n](WX[^\s\n,=()]*)[\s,\n=]/g) { add_entry($1,$version); }
        while ($_ =~ /[\s,\n](Wx[^\s\n,=()]*)[\s,\n=]/g) { add_entry($1,$version); }
    }
    #Get #define constants
    while ($in =~ /#define[\s]+(wx[^\s\n,=()]*)[\s,\n=]/g) { add_entry($1,$version); }
    while ($in =~ /#define[\s]+(WX[^\s\n,=()]*)[\s,\n=]/g) { add_entry($1,$version); }
    while ($in =~ /#define[\s]+(Wx[^\s\n,=()]*)[\s,\n=]/g) { add_entry($1,$version); }
}

#Sorted list so we get sorted output
my @definitions = sort keys %defs;

#Output the details
print 'constant, first version, last version, want it in wxPerl, implemented in wxPerl, comments'."\n";
foreach (@definitions) {
    unless ($defs{$_}->{status} eq $versions[-1]) {
        $defs{$_}->{wantInWxPerl} = 0;
    }
    print $_.','.$defs{$_}->{introduced}.','.$defs{$_}->{status}.','.$defs{$_}->{wantInWxPerl}.','.$defs{$_}->{inWxPerl}.','.$defs{$_}->{comments}."\n";
}


#Add a constant
sub add_entry {
    my $wxLabel = shift;
    my $version = shift;
    #print $wxLabel;
    #New constant
    unless (defined $defs{$wxLabel}) {
        $defs{$wxLabel}->{introduced} = $version;
        #Check whether it is in wxperl
        $output = `grep $wxLabel $wxperl_path -wR`;
        if ($output) { 
            $defs{$wxLabel}->{inWxPerl} = 1; 
        } else { 
            $defs{$wxLabel}->{inWxPerl} = 0; 
        }
        $defs{$wxLabel}->{wantInWxPerl} = 1;
        $defs{$wxLabel}->{comments} = '';
        #Check whether we want to see this in wxPerl
        if (defined $omit->{$wxLabel}) {
            $defs{$wxLabel}->{wantInWxPerl} = 0;
            $defs{$wxLabel}->{comments} = $defs{$wxLabel}->{comments}.$omit->{$wxLabel};
        }
        #Check partial matches
        foreach (keys %{$omitpartial}) {
            if ($wxLabel =~ /$_/) {
                $defs{$wxLabel}->{wantInWxPerl} = 0;
                $defs{$wxLabel}->{comments} = $defs{$wxLabel}->{comments}.$omitpartial->{$_};
            } 
        }
        #Add any other descriptions
        if (defined $description->{$wxLabel}) {
            $defs{$wxLabel}->{comments} = $defs{$wxLabel}->{comments}.$description->{$wxLabel};
        } 

    }
    #Update the last wxWidgets version where we've seen this constant
    $defs{$wxLabel}->{status} = $version;
}
