e1f2ca99a10571bb911b830e5a0a4c8fd3c59c43
[openssl.git] / util / mkdef.pl
1 #!/usr/local/bin/perl
2 #
3 # generate a .def file
4 #
5 # It does this by parsing the header files and looking for the
6 # non-prototyped functions.
7 #
8
9 $crypto_num="util/libeay.num";
10 $ssl_num=   "util/ssleay.num";
11
12 $NT=1;
13 foreach (@ARGV)
14         {
15         $NT=1 if $_ eq "32";
16         $NT=0 if $_ eq "16";
17         $do_ssl=1 if $_ eq "ssleay";
18         $do_ssl=1 if $_ eq "ssl";
19         $do_crypto=1 if $_ eq "libeay";
20         $do_crypto=1 if $_ eq "crypto";
21         $do_update=1 if $_ eq "update";
22         }
23
24 if (!$do_ssl && !$do_crypto)
25         {
26         print STDERR "usage: $0 ( ssl | crypto ) [ 16 | 32 ]\n";
27         exit(1);
28         }
29
30 %ssl_list=&load_numbers($ssl_num);
31 $max_ssl = $max_num;
32 %crypto_list=&load_numbers($crypto_num);
33 $max_crypto = $max_num;
34
35 $ssl="ssl/ssl.h";
36
37 $crypto ="crypto/crypto.h";
38 $crypto.=" crypto/des/des.h";
39 $crypto.=" crypto/idea/idea.h";
40 $crypto.=" crypto/rc4/rc4.h";
41 $crypto.=" crypto/rc5/rc5.h";
42 $crypto.=" crypto/rc2/rc2.h";
43 $crypto.=" crypto/bf/blowfish.h";
44 $crypto.=" crypto/cast/cast.h";
45 $crypto.=" crypto/md2/md2.h";
46 $crypto.=" crypto/md5/md5.h";
47 $crypto.=" crypto/mdc2/mdc2.h";
48 $crypto.=" crypto/sha/sha.h";
49 $crypto.=" crypto/ripemd/ripemd.h";
50
51 $crypto.=" crypto/bn/bn.h";
52 $crypto.=" crypto/rsa/rsa.h";
53 $crypto.=" crypto/dsa/dsa.h";
54 $crypto.=" crypto/dh/dh.h";
55
56 $crypto.=" crypto/stack/stack.h";
57 $crypto.=" crypto/buffer/buffer.h";
58 $crypto.=" crypto/bio/bio.h";
59 $crypto.=" crypto/lhash/lhash.h";
60 $crypto.=" crypto/conf/conf.h";
61 $crypto.=" crypto/txt_db/txt_db.h";
62
63 $crypto.=" crypto/evp/evp.h";
64 $crypto.=" crypto/objects/objects.h";
65 $crypto.=" crypto/pem/pem.h";
66 #$crypto.=" crypto/meth/meth.h";
67 $crypto.=" crypto/asn1/asn1.h";
68 $crypto.=" crypto/asn1/asn1_mac.h";
69 $crypto.=" crypto/err/err.h";
70 $crypto.=" crypto/pkcs7/pkcs7.h";
71 $crypto.=" crypto/x509/x509.h";
72 $crypto.=" crypto/x509/x509_vfy.h";
73 $crypto.=" crypto/x509v3/x509v3.h";
74 $crypto.=" crypto/rand/rand.h";
75 $crypto.=" crypto/hmac/hmac.h";
76 $crypto.=" crypto/comp/comp.h";
77 $crypto.=" crypto/tmdiff.h";
78
79 $match{'NOPROTO'}=1;
80 $match2{'PERL5'}=1;
81
82 @ssl_func = &do_defs("SSLEAY", $ssl);
83 @crypto_func = &do_defs("LIBEAY", $crypto);
84
85 if ($do_update) {
86
87 if ($do_ssl == 1) {
88         open(OUT, ">>$ssl_num");
89         &update_numbers(*OUT,"SSLEAY",*ssl_list,$max_ssl, @ssl_func);
90         close OUT;
91 }
92
93 if($do_crypto == 1) {
94         open(OUT, ">>$crypto_num");
95         &update_numbers(*OUT,"LIBEAY",*crypto_list,$max_crypto, @crypto_func);
96         close OUT;
97 }
98
99 } else {
100
101         &print_def_file(*STDOUT,"SSLEAY",*ssl_list,@ssl_func)
102                 if $do_ssl == 1;
103
104         &print_def_file(*STDOUT,"LIBEAY",*crypto_list,@crypto_func)
105                 if $do_crypto == 1;
106
107 }
108
109
110 sub do_defs
111         {
112         local($name,$files)=@_;
113         local(@ret);
114
115         $off=-1;
116         foreach $file (split(/\s+/,$files))
117                 {
118 #               print STDERR "reading $file\n";
119                 open(IN,"<$file") || die "unable to open $file:$!\n";
120                 $depth=0;
121                 $pr=-1;
122                 @np="";
123                 $/=undef;
124                 $a=<IN>;
125                 while (($i=index($a,"/*")) >= 0)
126                         {
127                         $j=index($a,"*/");
128                         last unless ($j >= 0);
129                         $a=substr($a,0,$i).substr($a,$j+2);
130                 #       print "$i $j\n";
131                         }
132                 foreach (split("\n",$a))
133                         {
134                         if (/^\#\s*ifndef (.*)/)
135                                 {
136                                 push(@tag,$1);
137                                 $tag{$1}=-1;
138                                 next;
139                                 }
140                         elsif (/^\#\s*if !defined\(([^\)]+)\)/)
141                                 {
142                                 push(@tag,$1);
143                                 $tag{$1}=-1;
144                                 next;
145                                 }
146                         elsif (/^\#\s*ifdef (.*)/)
147                                 {
148                                 push(@tag,$1);
149                                 $tag{$1}=1;
150                                 next;
151                                 }
152                         elsif (/^\#\s*if defined(.*)/)
153                                 {
154                                 push(@tag,$1);
155                                 $tag{$1}=1;
156                                 next;
157                                 }
158                         elsif (/^\#\s*endif/)
159                                 {
160                                 $tag{$tag[$#tag]}=0;
161                                 pop(@tag);
162                                 next;
163                                 }
164                         elsif (/^\#\s*else/)
165                                 {
166                                 $t=$tag[$#tag];
167                                 $tag{$t}= -$tag{$t};
168                                 next;
169                                 }
170 #printf STDERR "$_\n%2d %2d %2d %2d %2d $NT\n",
171 #$tag{'NOPROTO'},$tag{'FreeBSD'},$tag{'WIN16'},$tag{'PERL5'},$tag{'NO_FP_API'};
172
173                         $t=undef;
174                         if (/^extern .*;$/)
175                                 { $t=&do_extern($name,$_); }
176                         elsif ( ($tag{'NOPROTO'} == 1) &&
177                                 ($tag{'FreeBSD'} != 1) &&
178                                 (($NT && ($tag{'WIN16'} != 1)) ||
179                                  (!$NT && ($tag{'WIN16'} != -1))) &&
180                                 ($tag{'PERL5'} != 1) &&
181 #                               ($tag{'_WINDLL'} != -1) &&
182                                 ((!$NT && $tag{'_WINDLL'} != -1) ||
183                                  ($NT && $tag{'_WINDLL'} != 1)) &&
184                                 ((($tag{'NO_FP_API'} != 1) && $NT) ||
185                                  (($tag{'NO_FP_API'} != -1) && !$NT)))
186                                 { $t=&do_line($name,$_); }
187                         else
188                                 { $t=undef; }
189                         if (($t ne undef) && (!$done{$name,$t}))
190                                 {
191                                 $done{$name,$t}++;
192                                 push(@ret,$t);
193 #printf STDERR "one:$t\n" if $t =~ /BIO_/;
194                                 }
195                         }
196                 close(IN);
197                 }
198         return(@ret);
199         }
200
201 sub do_line
202         {
203         local($file,$_)=@_;
204         local($n);
205
206         return(undef) if /^$/;
207         return(undef) if /^\s/;
208 #printf STDERR "two:$_\n" if $_ =~ /BIO_/;
209         if (/(CRYPTO_get_locking_callback)/)
210                 { return($1); }
211         elsif (/(CRYPTO_get_id_callback)/)
212                 { return($1); }
213         elsif (/(CRYPTO_get_add_lock_callback)/)
214                 { return($1); }
215         elsif (/(SSL_CTX_get_verify_callback)/)
216                 { return($1); }
217         elsif (/(SSL_get_info_callback)/)
218                 { return($1); }
219         elsif ((!$NT) && /(ERR_load_CRYPTO_strings)/)
220                 { return("ERR_load_CRYPTOlib_strings"); }
221         elsif (!$NT && /BIO_s_file/)
222                 { return(undef); }
223         elsif (!$NT && /BIO_new_file/)
224                 { return(undef); }
225         elsif (!$NT && /BIO_new_fp/)
226                 { return(undef); }
227         elsif ($NT && /BIO_s_file_internal/)
228                 { return(undef); }
229         elsif ($NT && /BIO_new_file_internal/)
230                 { return(undef); }
231         elsif ($NT && /BIO_new_fp_internal/)
232                 { return(undef); }
233         else
234                 {
235                 /\s\**(\S+)\s*\(/;
236                 return($1);
237                 }
238         }
239
240 sub do_extern
241         {
242         local($file,$_)=@_;
243         local($n);
244
245         /\s\**(\S+);$/;
246         return($1);
247         }
248
249 sub print_def_file
250         {
251         local(*OUT,$name,*nums,@functions)=@_;
252         local($n)=1;
253
254         if ($NT)
255                 { $name.="32"; }
256         else
257                 { $name.="16"; }
258
259         print OUT <<"EOF";
260 ;
261 ; Definition file for the DLL version of the $name library from OpenSSL
262 ;
263
264 LIBRARY         $name
265
266 DESCRIPTION     'OpenSSL $name - http://www.openssl.org/'
267
268 EOF
269
270         if (!$NT)
271                 {
272                 print <<"EOF";
273 CODE            PRELOAD MOVEABLE
274 DATA            PRELOAD MOVEABLE SINGLE
275
276 EXETYPE         WINDOWS
277
278 HEAPSIZE        4096
279 STACKSIZE       8192
280
281 EOF
282                 }
283
284         print "EXPORTS\n";
285
286
287         (@e)=grep(/^SSLeay/,@functions);
288         (@r)=grep(!/^SSLeay/,@functions);
289         @functions=((sort @e),(sort @r));
290
291         foreach $func (@functions)
292                 {
293                 if (!defined($nums{$func}))
294                         {
295                         printf STDERR "$func does not have a number assigned\n"
296                                         if(!$do_update);
297                         }
298                 else
299                         {
300                         $n=$nums{$func};
301                         printf OUT "    %s%-40s@%d\n",($NT)?"":"_",$func,$n;
302                         }
303                 }
304         printf OUT "\n";
305         }
306
307 sub load_numbers
308         {
309         local($name)=@_;
310         local($j,@a,%ret);
311
312         $max_num = 0;
313
314         open(IN,"<$name") || die "unable to open $name:$!\n";
315         while (<IN>)
316                 {
317                 chop;
318                 s/#.*$//;
319                 next if /^\s*$/;
320                 @a=split;
321                 $ret{$a[0]}=$a[1];
322                 $max_num = $a[1] if $a[1] > $max_num;
323                 }
324         close(IN);
325         return(%ret);
326         }
327
328 sub update_numbers
329         {
330         local(*OUT,$name,*nums,$start_num, @functions)=@_;
331         my $new_funcs = 0;
332         print STDERR "Updating $name\n";
333         foreach $func (@functions)
334                 {
335                 if (!defined($nums{$func}))
336                         {
337                         $new_funcs++;
338                         printf OUT "%s%-40s%d\n","",$func, ++$start_num;
339                         }
340                 }
341         if($new_funcs) {
342                 print STDERR "$new_funcs New Functions added\n";
343         } else {
344                 print STDERR "No New Functions Added\n";
345         }
346         }