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