1#!/usr/local/bin/perl
2
3my $ignore_re = '^(' . join("|", 
4	qw(
5		_
6		[a-z]
7		DBM
8		DBC
9		DB_AM_
10		DB_BT_
11		DB_RE_
12		DB_HS_
13		DB_FUNC_
14		DB_DBT_
15		DB_DBM
16		DB_TSL
17		MP
18		TXN
19                DB_TXN_GETPGNOS
20	)) . ')' ;
21
22my %ignore_def = map {$_, 1} qw() ;
23
24%ignore_enums = map {$_, 1} qw( ACTION db_status_t db_notices db_lockmode_t ) ;
25
26my %ignore_exact_enum = map { $_ => 1}
27	qw(
28                DB_TXN_GETPGNOS
29                );
30
31my $filler = ' ' x 26 ;
32
33chdir "libraries" || die "Cannot chdir into './libraries': $!\n";
34
35foreach my $name (sort tuple glob "[2-9]*")
36{
37    next if $name =~ /(NC|private)$/;
38
39    my $inc = "$name/include/db.h" ;
40    next unless -f $inc ;
41
42    my $file = readFile($inc) ;
43    StripCommentsAndStrings($file) ;
44    my $result = scan($name, $file) ;
45    print "\n\t#########\n\t# $name\n\t#########\n\n$result" 
46        if $result;
47}
48exit ;
49
50
51sub scan
52{
53    my $version = shift ;
54    my $file = shift ;
55
56    my %seen_define = () ;
57    my $result = "" ;
58
59    if (1) {
60        # Preprocess all tri-graphs 
61        # including things stuck in quoted string constants.
62        $file =~ s/\?\?=/#/g;                         # | ??=|  #|
63        $file =~ s/\?\?\!/|/g;                        # | ??!|  ||
64        $file =~ s/\?\?'/^/g;                         # | ??'|  ^|
65        $file =~ s/\?\?\(/[/g;                        # | ??(|  [|
66        $file =~ s/\?\?\)/]/g;                        # | ??)|  ]|
67        $file =~ s/\?\?\-/~/g;                        # | ??-|  ~|
68        $file =~ s/\?\?\//\\/g;                       # | ??/|  \|
69        $file =~ s/\?\?</{/g;                         # | ??<|  {|
70        $file =~ s/\?\?>/}/g;                         # | ??>|  }|
71    }
72    
73    while ( $file =~ /^\s*#\s*define\s+([\$\w]+)\b(?!\()\s*(.*)/gm ) 
74    {
75        my $def = $1;
76        my $rest = $2;
77        my $ignore = 0 ;
78    
79        $ignore = 1 if $ignore_def{$def} || $def =~ /$ignore_re/o ;
80    
81        # Cannot do: (-1) and ((LHANDLE)3) are OK:
82        #print("Skip non-wordy $def => $rest\n"),
83    
84        $rest =~ s/\s*$//;
85        #next if $rest =~ /[^\w\$]/;
86    
87        #print "Matched $_ ($def)\n" ;
88
89	next if $before{$def} ++ ;
90    
91        if ($ignore)
92          { $seen_define{$def} = 'IGNORE' }
93        elsif ($rest =~ /"/) 
94          { $seen_define{$def} = 'STRING' }
95        else
96          { $seen_define{$def} = 'DEFINE' }
97    }
98    
99    foreach $define (sort keys %seen_define)
100    { 
101        my $out = $filler ;
102	substr($out,0, length $define) = $define;
103	$result .= "\t$out => $seen_define{$define},\n" ;
104    }
105    
106    while ($file =~ /\btypedef\s+enum\s*{(.*?)}\s*(\w+)/gs )
107    {
108        my $enum = $1 ;
109        my $name = $2 ;
110        my $ignore = 0 ;
111    
112        $ignore = 1 if $ignore_enums{$name} ;
113    
114        #$enum =~ s/\s*=\s*\S+\s*(,?)\s*\n/$1/g;
115        $enum =~ s/^\s*//;
116        $enum =~ s/\s*$//;
117    
118        my @tokens = map { s/\s*=.*// ; $_} split /\s*,\s*/, $enum ;
119        my @new =  grep { ! $Enums{$_}++ } @tokens ;
120	if (@new)
121	{
122            my $value ;
123            if ($ignore)
124              { $value = "IGNORE, # $version" }
125            else
126              { $value = "'$version'," }
127
128            $result .= "\n\t# enum $name\n";
129            my $out = $filler ;
130	    foreach $name (@new)
131	    {
132                next if $ignore_exact_enum{$name} ;
133	        $out = $filler ;
134	        substr($out,0, length $name) = $name;
135                $result .= "\t$out => $value\n" ;
136	    }
137	}
138    }
139
140    return $result ;
141}
142
143
144sub StripCommentsAndStrings
145{
146
147  # Strip C & C++ coments
148  # From the perlfaq
149  $_[0] =~
150
151    s{
152       /\*         ##  Start of /* ... */ comment
153       [^*]*\*+    ##  Non-* followed by 1-or-more *'s
154       (
155         [^/*][^*]*\*+
156       )*          ##  0-or-more things which don't start with /
157                   ##    but do end with '*'
158       /           ##  End of /* ... */ comment
159 
160     |         ##     OR  C++ Comment
161       //          ## Start of C++ comment // 
162       [^\n]*      ## followed by 0-or-more non end of line characters
163
164     |         ##     OR  various things which aren't comments:
165 
166       (
167         "           ##  Start of " ... " string
168         (
169           \\.           ##  Escaped char
170         |               ##    OR
171           [^"\\]        ##  Non "\
172         )*
173         "           ##  End of " ... " string
174 
175       |         ##     OR
176 
177         '           ##  Start of ' ... ' string
178         (
179           \\.           ##  Escaped char
180         |               ##    OR
181           [^'\\]        ##  Non '\
182         )*
183         '           ##  End of ' ... ' string
184 
185       |         ##     OR
186 
187         .           ##  Anything other char
188         [^/"'\\]*   ##  Chars which doesn't start a comment, string or escape
189       )
190     }{$2}gxs;
191
192
193
194  # Remove double-quoted strings.
195  #$_[0] =~ s#"(\\.|[^"\\])*"##g;
196
197  # Remove single-quoted strings.
198  #$_[0] =~ s#'(\\.|[^'\\])*'##g;
199
200  # Remove leading whitespace.
201  $_[0] =~ s/\A\s+//m ;
202
203  # Remove trailing whitespace.
204  $_[0] =~ s/\s+\Z//m ;
205
206  # Replace all multiple whitespace by a single space.
207  #$_[0] =~ s/\s+/ /g ;
208}
209
210
211sub readFile
212{
213   my $filename = shift ;
214   open F, "<$filename" || die "Cannot open $filename: $!\n" ;
215   local $/ ;
216   my $x = <F> ;
217   close F ;
218   return $x ;
219}
220
221sub tuple
222{
223    my (@a) = split(/\./, $a) ;
224    my (@b) = split(/\./, $b) ;
225    if (@a != @b) {
226        my $diff = @a - @b ;
227        push @b, (0 x $diff) if $diff > 0 ;
228        push @a, (0 x -$diff) if $diff < 0 ;
229    }
230    foreach $A (@a) {
231        $B = shift @b ;
232        $A == $B or return $A <=> $B ;
233    }
234    return 0;
235}          
236
237__END__
238
239