mkdef.pl revision 72613
1261991Sdim#!/usr/local/bin/perl -w
2218885Sdim#
3218885Sdim# generate a .def file
4218885Sdim#
5218885Sdim# It does this by parsing the header files and looking for the
6218885Sdim# prototyped functions: it then prunes the output.
7218885Sdim#
8218885Sdim# Intermediary files are created, call libeay.num and ssleay.num,...
9218885Sdim# Previously, they had the following format:
10261991Sdim#
11218885Sdim#	routine-name	nnnn
12218885Sdim#
13218885Sdim# But that isn't enough for a number of reasons, the first on being that
14218885Sdim# this format is (needlessly) very Win32-centric, and even then...
15261991Sdim# One of the biggest problems is that there's no information about what
16261991Sdim# routines should actually be used, which varies with what crypto algorithms
17218885Sdim# are disabled.  Also, some operating systems (for example VMS with VAX C)
18218885Sdim# need to keep track of the global variables as well as the functions.
19261991Sdim#
20276479Sdim# So, a remake of this script is done so as to include information on the
21261991Sdim# kind of symbol it is (function or variable) and what algorithms they're
22261991Sdim# part of.  This will allow easy translating to .def files or the corresponding
23261991Sdim# file in other operating systems (a .opt file for VMS, possibly with a .mar
24261991Sdim# file).
25218885Sdim#
26276479Sdim# The format now becomes:
27276479Sdim#
28276479Sdim#	routine-name	nnnn	info
29276479Sdim#
30276479Sdim# and the "info" part is actually a colon-separated string of fields with
31261991Sdim# the following meaning:
32218885Sdim#
33261991Sdim#	existence:platform:kind:algorithms
34261991Sdim#
35261991Sdim# - "existence" can be "EXIST" or "NOEXIST" depending on if the symbol is
36261991Sdim#   found somewhere in the source,
37261991Sdim# - "platforms" is empty if it exists on all platforms, otherwise it contains
38218885Sdim#   comma-separated list of the platform, just as they are if the symbol exists
39261991Sdim#   for those platforms, or prepended with a "!" if not.  This helps resolve
40261991Sdim#   symbol name replacements for platforms where the names are too long for the
41296417Sdim#   compiler or linker, or if the systems is case insensitive and there is a
42261991Sdim#   clash.  This script assumes those redefinitions are place in the file
43218885Sdim#   crypto/symhacks.h.
44261991Sdim#   The semantics for the platforms list is a bit complicated.  The rule of
45218885Sdim#   thumb is that the list is exclusive, but it seems to mean different things.
46261991Sdim#   So, if the list is all negatives (like "!VMS,!WIN16"), the symbol exists
47261991Sdim#   on all platforms except those listed.  If the list is all positives (like
48280031Sdim#   "VMS,WIN16"), the symbol exists only on those platforms and nowhere else.
49218885Sdim#   The combination of positives and negatives will act as if the positives
50276479Sdim#   weren't there.
51276479Sdim# - "kind" is "FUNCTION" or "VARIABLE".  The meaning of that is obvious.
52276479Sdim# - "algorithms" is a comma-separated list of algorithm names.  This helps
53276479Sdim#   exclude symbols that are part of an algorithm that some user wants to
54276479Sdim#   exclude.
55276479Sdim#
56276479Sdim
57218885Sdimmy $crypto_num= "util/libeay.num";
58218885Sdimmy $ssl_num=    "util/ssleay.num";
59218885Sdim
60261991Sdimmy $do_update = 0;
61261991Sdimmy $do_rewrite = 0;
62280031Sdimmy $do_crypto = 0;
63280031Sdimmy $do_ssl = 0;
64280031Sdimmy $do_ctest = 0;
65280031Sdimmy $do_ctestall = 0;
66280031Sdimmy $rsaref = 0;
67280031Sdim
68280031Sdimmy $VMS=0;
69280031Sdimmy $W32=0;
70280031Sdimmy $W16=0;
71280031Sdimmy $NT=0;
72280031Sdim# Set this to make typesafe STACK definitions appear in DEF
73280031Sdimmy $safe_stack_def = 0;
74280031Sdim
75280031Sdimmy @known_platforms = ( "__FreeBSD__", "VMS", "WIN16", "WIN32",
76280031Sdim			"WINNT", "PERL5", "NeXT" );
77280031Sdimmy @known_algorithms = ( "RC2", "RC4", "RC5", "IDEA", "DES", "BF",
78280031Sdim			 "CAST", "MD2", "MD4", "MD5", "SHA", "RIPEMD",
79280031Sdim			 "MDC2", "RSA", "DSA", "DH", "HMAC", "FP_API" );
80280031Sdim
81280031Sdimmy $options="";
82280031Sdimopen(IN,"<Makefile.ssl") || die "unable to open Makefile.ssl!\n";
83288943Sdimwhile(<IN>) {
84280031Sdim    $options=$1 if (/^OPTIONS=(.*)$/);
85280031Sdim}
86280031Sdimclose(IN);
87280031Sdim
88280031Sdim# The following ciphers may be excluded (by Configure). This means functions
89280031Sdim# defined with ifndef(NO_XXX) are not included in the .def file, and everything
90280031Sdim# in directory xxx is ignored.
91280031Sdimmy $no_rc2; my $no_rc4; my $no_rc5; my $no_idea; my $no_des; my $no_bf;
92280031Sdimmy $no_cast;
93280031Sdimmy $no_md2; my $no_md4; my $no_md5; my $no_sha; my $no_ripemd; my $no_mdc2;
94280031Sdimmy $no_rsa; my $no_dsa; my $no_dh; my $no_hmac=0;
95280031Sdimmy $no_fp_api;
96280031Sdim
97280031Sdimforeach (@ARGV, split(/ /, $options))
98280031Sdim	{
99280031Sdim	$W32=1 if $_ eq "32";
100280031Sdim	$W16=1 if $_ eq "16";
101280031Sdim	if($_ eq "NT") {
102280031Sdim		$W32 = 1;
103280031Sdim		$NT = 1;
104280031Sdim	}
105280031Sdim	$VMS=1 if $_ eq "VMS";
106280031Sdim	$rsaref=1 if $_ eq "rsaref";
107280031Sdim
108280031Sdim	$do_ssl=1 if $_ eq "ssleay";
109280031Sdim	$do_ssl=1 if $_ eq "ssl";
110280031Sdim	$do_crypto=1 if $_ eq "libeay";
111280031Sdim	$do_crypto=1 if $_ eq "crypto";
112280031Sdim	$do_update=1 if $_ eq "update";
113280031Sdim	$do_rewrite=1 if $_ eq "rewrite";
114280031Sdim	$do_ctest=1 if $_ eq "ctest";
115280031Sdim	$do_ctestall=1 if $_ eq "ctestall";
116280031Sdim	#$safe_stack_def=1 if $_ eq "-DDEBUG_SAFESTACK";
117280031Sdim
118261991Sdim	if    (/^no-rc2$/)      { $no_rc2=1; }
119218885Sdim	elsif (/^no-rc4$/)      { $no_rc4=1; }
120261991Sdim	elsif (/^no-rc5$/)      { $no_rc5=1; }
121261991Sdim	elsif (/^no-idea$/)     { $no_idea=1; }
122261991Sdim	elsif (/^no-des$/)      { $no_des=1; $no_mdc2=1; }
123218885Sdim	elsif (/^no-bf$/)       { $no_bf=1; }
124261991Sdim	elsif (/^no-cast$/)     { $no_cast=1; }
125261991Sdim	elsif (/^no-md2$/)      { $no_md2=1; }
126261991Sdim	elsif (/^no-md4$/)      { $no_md4=1; }
127218885Sdim	elsif (/^no-md5$/)      { $no_md5=1; }
128261991Sdim	elsif (/^no-sha$/)      { $no_sha=1; }
129261991Sdim	elsif (/^no-ripemd$/)   { $no_ripemd=1; }
130261991Sdim	elsif (/^no-mdc2$/)     { $no_mdc2=1; }
131261991Sdim	elsif (/^no-rsa$/)      { $no_rsa=1; }
132218885Sdim	elsif (/^no-dsa$/)      { $no_dsa=1; }
133261991Sdim	elsif (/^no-dh$/)       { $no_dh=1; }
134261991Sdim	elsif (/^no-hmac$/)	{ $no_hmac=1; }
135261991Sdim	}
136218885Sdim
137261991Sdim
138261991Sdim# If no platform is given, assume WIN32
139261991Sdimif ($W32 + $W16 + $VMS == 0) {
140261991Sdim	$W32 = 1;
141218885Sdim}
142261991Sdim
143218885Sdim# Add extra knowledge
144218885Sdimif ($W16) {
145261991Sdim	$no_fp_api=1;
146261991Sdim}
147261991Sdim
148261991Sdimif (!$do_ssl && !$do_crypto)
149261991Sdim	{
150261991Sdim	print STDERR "usage: $0 ( ssl | crypto ) [ 16 | 32 | NT ] [rsaref]\n";
151261991Sdim	exit(1);
152218885Sdim	}
153218885Sdim
154309124Sdim%ssl_list=&load_numbers($ssl_num);
155309124Sdim$max_ssl = $max_num;
156309124Sdim%crypto_list=&load_numbers($crypto_num);
157309124Sdim$max_crypto = $max_num;
158309124Sdim
159309124Sdimmy $ssl="ssl/ssl.h";
160309124Sdim
161309124Sdimmy $crypto ="crypto/crypto.h";
162309124Sdim$crypto.=" crypto/des/des.h" unless $no_des;
163309124Sdim$crypto.=" crypto/idea/idea.h" unless $no_idea;
164309124Sdim$crypto.=" crypto/rc4/rc4.h" unless $no_rc4;
165309124Sdim$crypto.=" crypto/rc5/rc5.h" unless $no_rc5;
166309124Sdim$crypto.=" crypto/rc2/rc2.h" unless $no_rc2;
167314564Sdim$crypto.=" crypto/bf/blowfish.h" unless $no_bf;
168314564Sdim$crypto.=" crypto/cast/cast.h" unless $no_cast;
169314564Sdim$crypto.=" crypto/md2/md2.h" unless $no_md2;
170314564Sdim$crypto.=" crypto/md4/md4.h" unless $no_md4;
171314564Sdim$crypto.=" crypto/md5/md5.h" unless $no_md5;
172309124Sdim$crypto.=" crypto/mdc2/mdc2.h" unless $no_mdc2;
173309124Sdim$crypto.=" crypto/sha/sha.h" unless $no_sha;
174314564Sdim$crypto.=" crypto/ripemd/ripemd.h" unless $no_ripemd;
175314564Sdim
176314564Sdim$crypto.=" crypto/bn/bn.h";
177314564Sdim$crypto.=" crypto/rsa/rsa.h" unless $no_rsa;
178314564Sdim$crypto.=" crypto/dsa/dsa.h" unless $no_dsa;
179218885Sdim$crypto.=" crypto/dh/dh.h" unless $no_dh;
180218885Sdim$crypto.=" crypto/hmac/hmac.h" unless $no_hmac;
181276479Sdim
182261991Sdim$crypto.=" crypto/stack/stack.h";
183261991Sdim$crypto.=" crypto/buffer/buffer.h";
184218885Sdim$crypto.=" crypto/bio/bio.h";
185261991Sdim$crypto.=" crypto/dso/dso.h";
186261991Sdim$crypto.=" crypto/lhash/lhash.h";
187261991Sdim$crypto.=" crypto/conf/conf.h";
188218885Sdim$crypto.=" crypto/txt_db/txt_db.h";
189261991Sdim
190261991Sdim$crypto.=" crypto/evp/evp.h";
191288943Sdim$crypto.=" crypto/objects/objects.h";
192218885Sdim$crypto.=" crypto/pem/pem.h";
193261991Sdim#$crypto.=" crypto/meth/meth.h";
194261991Sdim$crypto.=" crypto/asn1/asn1.h";
195261991Sdim$crypto.=" crypto/asn1/asn1_mac.h";
196261991Sdim$crypto.=" crypto/err/err.h";
197261991Sdim$crypto.=" crypto/pkcs7/pkcs7.h";
198261991Sdim$crypto.=" crypto/pkcs12/pkcs12.h";
199261991Sdim$crypto.=" crypto/x509/x509.h";
200261991Sdim$crypto.=" crypto/x509/x509_vfy.h";
201218885Sdim$crypto.=" crypto/x509v3/x509v3.h";
202218885Sdim$crypto.=" crypto/rand/rand.h";
203296417Sdim$crypto.=" crypto/comp/comp.h";
204296417Sdim$crypto.=" crypto/tmdiff.h";
205261991Sdim
206218885Sdimmy $symhacks="crypto/symhacks.h";
207280031Sdim
208261991Sdimmy @ssl_symbols = &do_defs("SSLEAY", $ssl, $symhacks);
209218885Sdimmy @crypto_symbols = &do_defs("LIBEAY", $crypto, $symhacks);
210261991Sdim
211276479Sdimif ($do_update) {
212276479Sdim
213288943Sdimif ($do_ssl == 1) {
214276479Sdim
215218885Sdim	&maybe_add_info("SSLEAY",*ssl_list,@ssl_symbols);
216276479Sdim	if ($do_rewrite == 1) {
217218885Sdim		open(OUT, ">$ssl_num");
218218885Sdim		&rewrite_numbers(*OUT,"SSLEAY",*ssl_list,@ssl_symbols);
219276479Sdim		close OUT;
220276479Sdim	} else {
221261991Sdim		open(OUT, ">>$ssl_num");
222261991Sdim	}
223261991Sdim	&update_numbers(*OUT,"SSLEAY",*ssl_list,$max_ssl,@ssl_symbols);
224280031Sdim	close OUT;
225276479Sdim}
226280031Sdim
227276479Sdimif($do_crypto == 1) {
228218885Sdim
229276479Sdim	&maybe_add_info("LIBEAY",*crypto_list,@crypto_symbols);
230288943Sdim	if ($do_rewrite == 1) {
231218885Sdim		open(OUT, ">$crypto_num");
232276479Sdim		&rewrite_numbers(*OUT,"LIBEAY",*crypto_list,@crypto_symbols);
233218885Sdim	} else {
234218885Sdim		open(OUT, ">>$crypto_num");
235314564Sdim	}
236314564Sdim	&update_numbers(*OUT,"LIBEAY",*crypto_list,$max_crypto,@crypto_symbols);
237314564Sdim	close OUT;
238314564Sdim}
239276479Sdim
240261991Sdim} elsif ($do_ctest || $do_ctestall) {
241218885Sdim
242276479Sdim	print <<"EOF";
243276479Sdim
244276479Sdim/* Test file to check all DEF file symbols are present by trying
245276479Sdim * to link to all of them. This is *not* intended to be run!
246276479Sdim */
247261991Sdim
248261991Sdimint main()
249280031Sdim{
250261991SdimEOF
251261991Sdim	&print_test_file(*STDOUT,"SSLEAY",*ssl_list,$do_ctestall,@ssl_symbols)
252276479Sdim		if $do_ssl == 1;
253261991Sdim
254288943Sdim	&print_test_file(*STDOUT,"LIBEAY",*crypto_list,$do_ctestall,@crypto_symbols)
255276479Sdim		if $do_crypto == 1;
256276479Sdim
257276479Sdim	print "}\n";
258276479Sdim
259261991Sdim} else {
260276479Sdim
261288943Sdim	&print_def_file(*STDOUT,"SSLEAY",*ssl_list,@ssl_symbols)
262276479Sdim		if $do_ssl == 1;
263276479Sdim
264276479Sdim	&print_def_file(*STDOUT,"LIBEAY",*crypto_list,@crypto_symbols)
265276479Sdim		if $do_crypto == 1;
266218885Sdim
267218885Sdim}
268276479Sdim
269261991Sdim
270261991Sdimsub do_defs
271261991Sdim{
272280031Sdim	my($name,$files,$symhacksfile)=@_;
273276479Sdim	my $file;
274280031Sdim	my @ret;
275276479Sdim	my %syms;
276261991Sdim	my %platform;		# For anything undefined, we assume ""
277276479Sdim	my %kind;		# For anything undefined, we assume "FUNCTION"
278296417Sdim	my %algorithm;		# For anything undefined, we assume ""
279309124Sdim	my %rename;
280296417Sdim	my $cpp;
281296417Sdim
282296417Sdim	foreach $file (split(/\s+/,$symhacksfile." ".$files))
283309124Sdim		{
284309124Sdim		open(IN,"<$file") || die "unable to open $file:$!\n";
285261991Sdim		my $line = "", my $def= "";
286309124Sdim		my %tag = (
287309124Sdim			(map { $_ => 0 } @known_platforms),
288296417Sdim			(map { "NO_".$_ => 0 } @known_algorithms),
289309124Sdim			NOPROTO		=> 0,
290309124Sdim			PERL5		=> 0,
291309124Sdim			_WINDLL		=> 0,
292309124Sdim			CONST_STRICT	=> 0,
293309124Sdim			TRUE		=> 1,
294296417Sdim		);
295309124Sdim		my $symhacking = $file eq $symhacksfile;
296309124Sdim		while(<IN>) {
297309124Sdim			last if (/BEGIN ERROR CODES/);
298309124Sdim			if ($line ne '') {
299309124Sdim				$_ = $line . $_;
300309124Sdim				$line = '';
301309124Sdim			}
302309124Sdim
303309124Sdim			if (/\\$/) {
304309124Sdim				$line = $_;
305309124Sdim				next;
306309124Sdim			}
307309124Sdim
308309124Sdim	    		$cpp = 1 if /^\#.*ifdef.*cplusplus/;
309309124Sdim			if ($cpp) {
310309124Sdim				$cpp = 0 if /^\#.*endif/;
311309124Sdim				next;
312309124Sdim	    		}
313309124Sdim
314309124Sdim			s/\/\*.*?\*\///gs;                   # ignore comments
315309124Sdim			s/{[^{}]*}//gs;                      # ignore {} blocks
316309124Sdim			if (/^\#\s*ifndef (.*)/) {
317261991Sdim				push(@tag,$1);
318261991Sdim				$tag{$1}=-1;
319276479Sdim			} elsif (/^\#\s*if !defined\(([^\)]+)\)/) {
320296417Sdim				push(@tag,$1);
321296417Sdim				$tag{$1}=-1;
322296417Sdim			} elsif (/^\#\s*ifdef (.*)/) {
323296417Sdim				push(@tag,$1);
324261991Sdim				$tag{$1}=1;
325261991Sdim			} elsif (/^\#\s*if defined\(([^\)]+)\)/) {
326261991Sdim				push(@tag,$1);
327218885Sdim				$tag{$1}=1;
328218885Sdim			} elsif (/^\#\s*error\s+(\w+) is disabled\./) {
329280031Sdim				if ($tag[$#tag] eq "NO_".$1) {
330261991Sdim					$tag{$tag[$#tag]}=2;
331280031Sdim				}
332261991Sdim			} elsif (/^\#\s*endif/) {
333280031Sdim				if ($tag{$tag[$#tag]}==2) {
334261991Sdim					$tag{$tag[$#tag]}=-1;
335276479Sdim				} else {
336218885Sdim					$tag{$tag[$#tag]}=0;
337218885Sdim				}
338280031Sdim				pop(@tag);
339280031Sdim			} elsif (/^\#\s*else/) {
340218885Sdim				my $t=$tag[$#tag];
341280031Sdim				$tag{$t}= -$tag{$t};
342280031Sdim			} elsif (/^\#\s*if\s+1/) {
343218885Sdim				# Dummy tag
344280031Sdim				push(@tag,"TRUE");
345218885Sdim				$tag{"TRUE"}=1;
346280031Sdim			} elsif (/^\#\s*if\s+0/) {
347261991Sdim				# Dummy tag
348276479Sdim				push(@tag,"TRUE");
349276479Sdim				$tag{"TRUE"}=-1;
350276479Sdim			} elsif (/^\#\s*define\s+(\w+)\s+(\w+)/
351288943Sdim				 && $symhacking) {
352280031Sdim				my $s = $1;
353280031Sdim				my $a =
354218885Sdim				    $2.":".join(",", grep(!/^$/,
355280031Sdim							  map { $tag{$_} == 1 ?
356280031Sdim								    $_ : "" }
357218885Sdim							  @known_platforms));
358280031Sdim				$rename{$s} = $a;
359261991Sdim			}
360218885Sdim			if (/^\#/) {
361296417Sdim				my @p = grep(!/^$/,
362296417Sdim					     map { $tag{$_} == 1 ? $_ :
363296417Sdim						       $tag{$_} == -1 ? "!".$_  : "" }
364296417Sdim					     @known_platforms);
365296417Sdim				my @a = grep(!/^$/,
366261991Sdim					     map { $tag{"NO_".$_} == -1 ? $_ : "" }
367261991Sdim					     @known_algorithms);
368309124Sdim				$def .= "#INFO:".join(',',@p).":".join(',',@a).";";
369309124Sdim				next;
370309124Sdim			}
371309124Sdim			if (/^\s*DECLARE_STACK_OF\s*\(\s*(\w*)\s*\)/) {
372309124Sdim				next;
373309124Sdim			} elsif (/^\s*DECLARE_PKCS12_STACK_OF\s*\(\s*(\w*)\s*\)/) {
374309124Sdim				next;
375309124Sdim			} elsif (/^\s*DECLARE_ASN1_SET_OF\s*\(\s*(\w*)\s*\)/) {
376309124Sdim				next;
377218885Sdim			} elsif (/^DECLARE_PEM_rw\s*\(\s*(\w*)\s*,/ ||
378218885Sdim				 /^DECLARE_PEM_rw_cb\s*\(\s*(\w*)\s*,/ ) {
379276479Sdim				# Things not in Win16
380261991Sdim				$syms{"PEM_read_${1}"} = 1;
381276479Sdim				$platform{"PEM_read_${1}"} = "!WIN16";
382276479Sdim				$syms{"PEM_write_${1}"} = 1;
383276479Sdim				$platform{"PEM_write_${1}"} = "!WIN16";
384276479Sdim				# Things that are everywhere
385261991Sdim				$syms{"PEM_read_bio_${1}"} = 1;
386276479Sdim				$syms{"PEM_write_bio_${1}"} = 1;
387261991Sdim				if ($1 eq "RSAPrivateKey" ||
388218885Sdim				    $1 eq "RSAPublicKey" ||
389261991Sdim				    $1 eq "RSA_PUBKEY") {
390261991Sdim					$algorithm{"PEM_read_${1}"} = "RSA";
391261991Sdim					$algorithm{"PEM_write_${1}"} = "RSA";
392296417Sdim					$algorithm{"PEM_read_bio_${1}"} = "RSA";
393296417Sdim					$algorithm{"PEM_write_bio_${1}"} = "RSA";
394296417Sdim				}
395296417Sdim				elsif ($1 eq "DSAPrivateKey" ||
396296417Sdim				       $1 eq "DSAparams" ||
397296417Sdim				       $1 eq "RSA_PUBKEY") {
398218885Sdim					$algorithm{"PEM_read_${1}"} = "DSA";
399261991Sdim					$algorithm{"PEM_write_${1}"} = "DSA";
400261991Sdim					$algorithm{"PEM_read_bio_${1}"} = "DSA";
401261991Sdim					$algorithm{"PEM_write_bio_${1}"} = "DSA";
402261991Sdim				}
403261991Sdim				elsif ($1 eq "DHparams") {
404309124Sdim					$algorithm{"PEM_read_${1}"} = "DH";
405261991Sdim					$algorithm{"PEM_write_${1}"} = "DH";
406261991Sdim					$algorithm{"PEM_read_bio_${1}"} = "DH";
407218885Sdim					$algorithm{"PEM_write_bio_${1}"} = "DH";
408218885Sdim				}
409218885Sdim			} elsif (/^DECLARE_PEM_write\s*\(\s*(\w*)\s*,/ ||
410261991Sdim				     /^DECLARE_PEM_write_cb\s*\(\s*(\w*)\s*,/ ) {
411218885Sdim				# Things not in Win16
412218885Sdim				$syms{"PEM_write_${1}"} = 1;
413218885Sdim				$platform{"PEM_write_${1}"} .= ",!WIN16";
414276479Sdim				# Things that are everywhere
415261991Sdim				$syms{"PEM_write_bio_${1}"} = 1;
416261991Sdim				if ($1 eq "RSAPrivateKey" ||
417261991Sdim				    $1 eq "RSAPublicKey" ||
418261991Sdim				    $1 eq "RSA_PUBKEY") {
419261991Sdim					$algorithm{"PEM_write_${1}"} = "RSA";
420261991Sdim					$algorithm{"PEM_write_bio_${1}"} = "RSA";
421261991Sdim				}
422261991Sdim				elsif ($1 eq "DSAPrivateKey" ||
423261991Sdim				       $1 eq "DSAparams" ||
424288943Sdim				       $1 eq "RSA_PUBKEY") {
425261991Sdim					$algorithm{"PEM_write_${1}"} = "DSA";
426276479Sdim					$algorithm{"PEM_write_bio_${1}"} = "DSA";
427218885Sdim				}
428261991Sdim				elsif ($1 eq "DHparams") {
429261991Sdim					$algorithm{"PEM_write_${1}"} = "DH";
430261991Sdim					$algorithm{"PEM_write_bio_${1}"} = "DH";
431261991Sdim				}
432276479Sdim			} elsif (/^DECLARE_PEM_read\s*\(\s*(\w*)\s*,/ ||
433261991Sdim				     /^DECLARE_PEM_read_cb\s*\(\s*(\w*)\s*,/ ) {
434261991Sdim				# Things not in Win16
435276479Sdim				$syms{"PEM_read_${1}"} = 1;
436261991Sdim				$platform{"PEM_read_${1}"} .= ",!WIN16";
437218885Sdim				# Things that are everywhere
438261991Sdim				$syms{"PEM_read_bio_${1}"} = 1;
439261991Sdim			} elsif (
440261991Sdim				($tag{'TRUE'} != -1)
441261991Sdim				&& ($tag{'CONST_STRICT'} != 1)
442261991Sdim				 )
443261991Sdim				{
444261991Sdim					if (/\{|\/\*|\([^\)]*$/) {
445261991Sdim						$line = $_;
446261991Sdim					} else {
447309124Sdim						$def .= $_;
448309124Sdim					}
449309124Sdim				}
450261991Sdim			}
451261991Sdim		close(IN);
452261991Sdim
453276479Sdim		my $algs;
454218885Sdim		my $plays;
455218885Sdim
456261991Sdim		foreach (split /;/, $def) {
457276479Sdim			my $s; my $k = "FUNCTION"; my $p; my $a;
458276479Sdim			s/^[\n\s]*//g;
459276479Sdim			s/[\n\s]*$//g;
460261991Sdim			next if(/\#undef/);
461276479Sdim			next if(/typedef\W/);
462261991Sdim			next if(/\#define/);
463218885Sdim
464261991Sdim			if (/^\#INFO:([^:]*):(.*)$/) {
465288943Sdim				$plats = $1;
466261991Sdim				$algs = $2;
467218885Sdim				next;
468276479Sdim			} elsif (/^\s*OPENSSL_EXTERN\s.*?(\w+)(\[[0-9]*\])*\s*$/) {
469261991Sdim				$s = $1;
470261991Sdim				$k = "VARIABLE";
471261991Sdim			} elsif (/\(\*(\w*)\([^\)]+/) {
472261991Sdim				$s = $1;
473261991Sdim			} elsif (/\w+\W+(\w+)\W*\(\s*\)$/s) {
474261991Sdim				# K&R C
475276479Sdim				next;
476218885Sdim			} elsif (/\w+\W+\w+\W*\(.*\)$/s) {
477218885Sdim				while (not /\(\)$/s) {
478280031Sdim					s/[^\(\)]*\)$/\)/s;
479261991Sdim					s/\([^\(\)]*\)\)$/\)/s;
480218885Sdim				}
481261991Sdim				s/\(void\)//;
482261991Sdim				/(\w+)\W*\(\)/s;
483261991Sdim				$s = $1;
484261991Sdim			} elsif (/\(/ and not (/=/)) {
485261991Sdim				print STDERR "File $file: cannot parse: $_;\n";
486261991Sdim				next;
487261991Sdim			} else {
488261991Sdim				next;
489261991Sdim			}
490261991Sdim
491261991Sdim			$syms{$s} = 1;
492261991Sdim			$kind{$s} = $k;
493261991Sdim
494261991Sdim			$p = $plats;
495261991Sdim			$a = $algs;
496261991Sdim			$a .= ",BF" if($s =~ /EVP_bf/);
497218885Sdim			$a .= ",CAST" if($s =~ /EVP_cast/);
498261991Sdim			$a .= ",DES" if($s =~ /EVP_des/);
499261991Sdim			$a .= ",DSA" if($s =~ /EVP_dss/);
500261991Sdim			$a .= ",IDEA" if($s =~ /EVP_idea/);
501261991Sdim			$a .= ",MD2" if($s =~ /EVP_md2/);
502261991Sdim			$a .= ",MD4" if($s =~ /EVP_md4/);
503261991Sdim			$a .= ",MD5" if($s =~ /EVP_md5/);
504261991Sdim			$a .= ",RC2" if($s =~ /EVP_rc2/);
505261991Sdim			$a .= ",RC4" if($s =~ /EVP_rc4/);
506261991Sdim			$a .= ",RC5" if($s =~ /EVP_rc5/);
507218885Sdim			$a .= ",RIPEMD" if($s =~ /EVP_ripemd/);
508218885Sdim			$a .= ",SHA" if($s =~ /EVP_sha/);
509276479Sdim			$a .= ",RSA" if($s =~ /EVP_(Open|Seal)(Final|Init)/);
510261991Sdim			$a .= ",RSA" if($s =~ /PEM_Seal(Final|Init|Update)/);
511261991Sdim			$a .= ",RSA" if($s =~ /RSAPrivateKey/);
512261991Sdim			$a .= ",RSA" if($s =~ /SSLv23?_((client|server)_)?method/);
513261991Sdim
514314564Sdim			$platform{$s} .= ','.$p;
515314564Sdim			$algorithm{$s} .= ','.$a;
516261991Sdim
517261991Sdim			if (defined($rename{$s})) {
518288943Sdim				(my $r, my $p) = split(/:/,$rename{$s});
519276479Sdim				my @ip = map { /^!(.*)$/ ? $1 : "!".$_ } split /,/, $p;
520261991Sdim				$syms{$r} = 1;
521261991Sdim				$kind{$r} = $kind{$s}."(".$s.")";
522280031Sdim				$algorithm{$r} = $algorithm{$s};
523280031Sdim				$platform{$r} = $platform{$s}.",".$p;
524261991Sdim				$platform{$s} .= ','.join(',', @ip).','.join(',', @ip);
525280031Sdim			}
526261991Sdim		}
527261991Sdim	}
528280031Sdim
529280031Sdim	# Prune the returned symbols
530280031Sdim
531280031Sdim	$platform{"crypt"} .= ",!PERL5,!__FreeBSD__,!NeXT";
532261991Sdim
533261991Sdim        delete $syms{"SSL_add_dir_cert_subjects_to_stack"};
534261991Sdim        delete $syms{"bn_dump1"};
535261991Sdim
536261991Sdim	$platform{"BIO_s_file_internal"} .= ",WIN16";
537218885Sdim	$platform{"BIO_new_file_internal"} .= ",WIN16";
538218885Sdim	$platform{"BIO_new_fp_internal"} .= ",WIN16";
539280031Sdim
540261991Sdim	$platform{"BIO_s_file"} .= ",!WIN16";
541261991Sdim	$platform{"BIO_new_file"} .= ",!WIN16";
542261991Sdim	$platform{"BIO_new_fp"} .= ",!WIN16";
543261991Sdim
544261991Sdim	$platform{"BIO_s_log"} .= ",!WIN32,!WIN16,!macintosh";
545288943Sdim
546261991Sdim	if(exists $syms{"ERR_load_CRYPTO_strings"}) {
547218885Sdim		$platform{"ERR_load_CRYPTO_strings"} .= ",!VMS,!WIN16";
548218885Sdim		$syms{"ERR_load_CRYPTOlib_strings"} = 1;
549261991Sdim		$platform{"ERR_load_CRYPTOlib_strings"} .= ",VMS,WIN16";
550261991Sdim	}
551261991Sdim
552261991Sdim	# Info we know about
553261991Sdim
554261991Sdim	$platform{"RSA_PKCS1_RSAref"} = "RSAREF";
555261991Sdim	$algorithm{"RSA_PKCS1_RSAref"} = "RSA";
556261991Sdim
557261991Sdim	push @ret, map { $_."\\".&info_string($_,"EXIST",
558261991Sdim					      $platform{$_},
559261991Sdim					      $kind{$_},
560261991Sdim					      $algorithm{$_}) } keys %syms;
561288943Sdim
562261991Sdim	return(@ret);
563261991Sdim}
564261991Sdim
565261991Sdimsub info_string {
566261991Sdim	(my $symbol, my $exist, my $platforms, my $kind, my $algorithms) = @_;
567261991Sdim
568261991Sdim	my %a = defined($algorithms) ?
569261991Sdim	    map { $_ => 1 } split /,/, $algorithms : ();
570288943Sdim	my $pl = defined($platforms) ? $platforms : "";
571261991Sdim	my %p = map { $_ => 0 } split /,/, $pl;
572261991Sdim	my $k = defined($kind) ? $kind : "FUNCTION";
573261991Sdim	my $ret;
574218885Sdim
575261991Sdim	# We do this, because if there's code like the following, it really
576218885Sdim	# means the function exists in all cases and should therefore be
577218885Sdim	# everywhere.  By increasing and decreasing, we may attain 0:
578261991Sdim	#
579261991Sdim	# ifndef WIN16
580261991Sdim	#    int foo();
581276479Sdim	# else
582218885Sdim	#    int _fat foo();
583218885Sdim	# endif
584280031Sdim	foreach $platform (split /,/, $pl) {
585280031Sdim		if ($platform =~ /^!(.*)$/) {
586280031Sdim			$p{$1}--;
587280031Sdim		} else {
588280031Sdim			$p{$platform}++;
589280031Sdim		}
590261991Sdim	}
591218885Sdim	foreach $platform (keys %p) {
592261991Sdim		if ($p{$platform} == 0) { delete $p{$platform}; }
593261991Sdim	}
594261991Sdim
595261991Sdim	delete $p{""};
596218885Sdim	delete $a{""};
597261991Sdim
598261991Sdim	$ret = $exist;
599261991Sdim	$ret .= ":".join(',',map { $p{$_} < 0 ? "!".$_ : $_ } keys %p);
600261991Sdim	$ret .= ":".$k;
601218885Sdim	$ret .= ":".join(',',keys %a);
602261991Sdim	return $ret;
603261991Sdim}
604261991Sdim
605261991Sdimsub maybe_add_info {
606218885Sdim	(my $name, *nums, my @symbols) = @_;
607261991Sdim	my $sym;
608261991Sdim	my $new_info = 0;
609261991Sdim
610261991Sdim	print STDERR "Updating $name info\n";
611218885Sdim	foreach $sym (@symbols) {
612261991Sdim		(my $s, my $i) = split /\\/, $sym;
613261991Sdim		$i =~ s/^(.*?:.*?:\w+)(\(\w+\))?/$1/;
614261991Sdim		if (defined($nums{$s})) {
615261991Sdim			(my $n, my $dummy) = split /\\/, $nums{$s};
616261991Sdim			if (!defined($dummy) || $i ne $dummy) {
617218885Sdim				$nums{$s} = $n."\\".$i;
618276479Sdim				$new_info++;
619261991Sdim				#print STDERR "DEBUG: maybe_add_info for $s: \"$dummy\" => \"$i\"\n";
620261991Sdim			}
621218885Sdim		}
622280031Sdim	}
623261991Sdim	if ($new_info) {
624218885Sdim		print STDERR "$new_info old symbols got an info update\n";
625261991Sdim		if (!$do_rewrite) {
626261991Sdim			print STDERR "You should do a rewrite to fix this.\n";
627261991Sdim		}
628261991Sdim	} else {
629261991Sdim		print STDERR "No old symbols needed info update\n";
630261991Sdim	}
631261991Sdim}
632261991Sdim
633261991Sdimsub print_test_file
634218885Sdim{
635261991Sdim	(*OUT,my $name,*nums,my @symbols)=@_;
636261991Sdim	my $n = 1; my @e; my @r;
637261991Sdim	my $sym; my $prev = ""; my $prefSSLeay;
638261991Sdim
639288943Sdim	(@e)=grep(/^SSLeay\\.*?:.*?:FUNCTION/,@symbols);
640218885Sdim	(@r)=grep(/^\w+\\.*?:.*?:FUNCTION/ && !/^SSLeay\\.*?:.*?:FUNCTION/,@symbols);
641261991Sdim	@symbols=((sort @e),(sort @r));
642261991Sdim
643261991Sdim	foreach $sym (@symbols) {
644261991Sdim		(my $s, my $i) = $sym =~ /^(.*?)\\(.*)$/;
645261991Sdim		if ($s ne $prev) {
646276479Sdim			if (!defined($nums{$sym})) {
647261991Sdim				printf STDERR "Warning: $sym does not have a number assigned\n"
648276479Sdim						if(!$do_update);
649261991Sdim			} else {
650288943Sdim				$n=$nums{$s};
651261991Sdim				print OUT "\t$s();\n";
652261991Sdim			}
653218885Sdim		}
654261991Sdim		$prev = $s;	# To avoid duplicates...
655261991Sdim	}
656276479Sdim}
657276479Sdim
658276479Sdimsub print_def_file
659261991Sdim{
660218885Sdim	(*OUT,my $name,*nums,my @symbols)=@_;
661261991Sdim	my $n = 1; my @e; my @r;
662261991Sdim
663288943Sdim	if ($W32)
664288943Sdim		{ $name.="32"; }
665218885Sdim	else
666276479Sdim		{ $name.="16"; }
667218885Sdim
668218885Sdim	print OUT <<"EOF";
669276479Sdim;
670261991Sdim; Definition file for the DLL version of the $name library from OpenSSL
671261991Sdim;
672261991Sdim
673261991SdimLIBRARY         $name
674261991Sdim
675276479SdimDESCRIPTION     'OpenSSL $name - http://www.openssl.org/'
676261991Sdim
677218885SdimEOF
678276479Sdim
679261991Sdim	if (!$W32) {
680261991Sdim		print <<"EOF";
681276479SdimCODE            PRELOAD MOVEABLE
682261991SdimDATA            PRELOAD MOVEABLE SINGLE
683276479Sdim
684261991SdimEXETYPE		WINDOWS
685288943Sdim
686261991SdimHEAPSIZE	4096
687218885SdimSTACKSIZE	8192
688261991Sdim
689261991SdimEOF
690261991Sdim	}
691261991Sdim
692261991Sdim	print "EXPORTS\n";
693218885Sdim
694261991Sdim	(@e)=grep(/^SSLeay\\.*?:.*?:FUNCTION/,@symbols);
695276479Sdim	(@r)=grep(/^\w+\\.*?:.*?:FUNCTION/ && !/^SSLeay\\.*?:.*?:FUNCTION/,@symbols);
696276479Sdim	@symbols=((sort @e),(sort @r));
697276479Sdim
698261991Sdim
699218885Sdim	foreach $sym (@symbols) {
700261991Sdim		(my $s, my $i) = $sym =~ /^(.*?)\\(.*)$/;
701276479Sdim		if (!defined($nums{$s})) {
702218885Sdim			printf STDERR "Warning: $s does not have a number assigned\n"
703218885Sdim					if(!$do_update);
704309124Sdim		} else {
705309124Sdim			(my $n, my $i) = split /\\/, $nums{$s};
706261991Sdim			my %pf = ();
707218885Sdim			my @p = split(/,/, ($i =~ /^[^:]*:([^:]*):/,$1));
708280031Sdim			my @a = split(/,/, ($i =~ /^[^:]*:[^:]*:[^:]*:([^:]*)/,$1));
709261991Sdim			# @p_purged must contain hardware platforms only
710218885Sdim			my @p_purged = ();
711296417Sdim			foreach $ptmp (@p) {
712296417Sdim				next if $ptmp =~ /^!?RSAREF$/;
713296417Sdim				push @p_purged, $ptmp;
714296417Sdim			}
715261991Sdim			my $negatives = !!grep(/^!/,@p);
716276479Sdim			# It is very important to check NT before W32
717288943Sdim			if ((($NT && (!@p_purged
718261991Sdim				      || (!$negatives && grep(/^WINNT$/,@p))
719261991Sdim				      || ($negatives && !grep(/^!WINNT$/,@p))))
720261991Sdim			     || ($W32 && (!@p_purged
721276479Sdim					  || (!$negatives && grep(/^WIN32$/,@p))
722261991Sdim					  || ($negatives && !grep(/^!WIN32$/,@p))))
723261991Sdim			     || ($W16 && (!@p_purged
724276479Sdim					  || (!$negatives && grep(/^WIN16$/,@p))
725261991Sdim					  || ($negatives && !grep(/^!WIN16$/,@p)))))
726218885Sdim			    && (!@p
727218885Sdim				|| (!$negatives
728261991Sdim				    && ($rsaref || !grep(/^RSAREF$/,@p)))
729261991Sdim				|| ($negatives
730261991Sdim				    && (!$rsaref || !grep(/^!RSAREF$/,@p))))
731288943Sdim			    && (!@a || (!$no_rc2 || !grep(/^RC2$/,@a)))
732218885Sdim			    && (!@a || (!$no_rc4 || !grep(/^RC4$/,@a)))
733218885Sdim			    && (!@a || (!$no_rc5 || !grep(/^RC5$/,@a)))
734309124Sdim			    && (!@a || (!$no_idea || !grep(/^IDEA$/,@a)))
735309124Sdim			    && (!@a || (!$no_des || !grep(/^DES$/,@a)))
736309124Sdim			    && (!@a || (!$no_bf || !grep(/^BF$/,@a)))
737309124Sdim			    && (!@a || (!$no_cast || !grep(/^CAST$/,@a)))
738309124Sdim			    && (!@a || (!$no_md2 || !grep(/^MD2$/,@a)))
739309124Sdim			    && (!@a || (!$no_md4 || !grep(/^MD4$/,@a)))
740309124Sdim			    && (!@a || (!$no_md5 || !grep(/^MD5$/,@a)))
741309124Sdim			    && (!@a || (!$no_sha || !grep(/^SHA$/,@a)))
742309124Sdim			    && (!@a || (!$no_ripemd || !grep(/^RIPEMD$/,@a)))
743309124Sdim			    && (!@a || (!$no_mdc2 || !grep(/^MDC2$/,@a)))
744309124Sdim			    && (!@a || (!$no_rsa || !grep(/^RSA$/,@a)))
745309124Sdim			    && (!@a || (!$no_dsa || !grep(/^DSA$/,@a)))
746309124Sdim			    && (!@a || (!$no_dh || !grep(/^DH$/,@a)))
747309124Sdim			    && (!@a || (!$no_hmac || !grep(/^HMAC$/,@a)))
748309124Sdim			    && (!@a || (!$no_fp_api || !grep(/^FP_API$/,@a)))
749309124Sdim			    ) {
750261991Sdim				printf OUT "    %s%-40s@%d\n",($W32)?"":"_",$s,$n;
751276479Sdim#			} else {
752218885Sdim#				print STDERR "DEBUG: \"$sym\" (@p):",
753218885Sdim#				" rsaref:", !!(!@p
754276479Sdim#					       || (!$negatives
755261991Sdim#						   && ($rsaref || !grep(/^RSAREF$/,@p)))
756261991Sdim#					       || ($negatives
757261991Sdim#						   && (!$rsaref || !grep(/^!RSAREF$/,@p))))?1:0,
758261991Sdim#				" 16:", !!($W16 && (!@p_purged
759218885Sdim#						    || (!$negatives && grep(/^WIN16$/,@p))
760261991Sdim#						    || ($negatives && !grep(/^!WIN16$/,@p)))),
761218885Sdim#				" 32:", !!($W32 && (!@p_purged
762280031Sdim#						    || (!$negatives && grep(/^WIN32$/,@p))
763261991Sdim#						    || ($negatives && !grep(/^!WIN32$/,@p)))),
764218885Sdim#				" NT:", !!($NT && (!@p_purged
765261991Sdim#						   || (!$negatives && grep(/^WINNT$/,@p))
766261991Sdim#						   || ($negatives && !grep(/^!WINNT$/,@p)))),
767261991Sdim#				"\n";
768261991Sdim			}
769261991Sdim		}
770261991Sdim	}
771261991Sdim	printf OUT "\n";
772261991Sdim}
773276479Sdim
774276479Sdimsub load_numbers
775276479Sdim{
776276479Sdim	my($name)=@_;
777276479Sdim	my(@a,%ret);
778261991Sdim
779261991Sdim	$max_num = 0;
780261991Sdim	$num_noinfo = 0;
781261991Sdim	$prev = "";
782276479Sdim
783288943Sdim	open(IN,"<$name") || die "unable to open $name:$!\n";
784261991Sdim	while (<IN>) {
785261991Sdim		chop;
786261991Sdim		s/#.*$//;
787276479Sdim		next if /^\s*$/;
788261991Sdim		@a=split;
789261991Sdim		if (defined $ret{$a[0]}) {
790276479Sdim			print STDERR "Warning: Symbol '",$a[0],"' redefined. old=",$ret{$a[0]},", new=",$a[1],"\n";
791261991Sdim		}
792221345Sdim		if ($max_num > $a[1]) {
793218885Sdim			print STDERR "Warning: Number decreased from ",$max_num," to ",$a[1],"\n";
794261991Sdim		}
795261991Sdim		if ($max_num == $a[1]) {
796261991Sdim			# This is actually perfectly OK
797218885Sdim			#print STDERR "Warning: Symbol ",$a[0]," has same number as previous ",$prev,": ",$a[1],"\n";
798276479Sdim		}
799261991Sdim		if ($#a < 2) {
800218885Sdim			# Existence will be proven later, in do_defs
801261991Sdim			$ret{$a[0]}=$a[1];
802261991Sdim			$num_noinfo++;
803261991Sdim		} else {
804288943Sdim			$ret{$a[0]}=$a[1]."\\".$a[2]; # \\ is a special marker
805261991Sdim		}
806218885Sdim		$max_num = $a[1] if $a[1] > $max_num;
807261991Sdim		$prev=$a[0];
808276479Sdim	}
809218885Sdim	if ($num_noinfo) {
810309124Sdim		print STDERR "Warning: $num_noinfo symbols were without info.";
811309124Sdim		if ($do_rewrite) {
812309124Sdim			printf STDERR "  The rewrite will fix this.\n";
813309124Sdim		} else {
814309124Sdim			printf STDERR "  You should do a rewrite to fix this.\n";
815309124Sdim		}
816309124Sdim	}
817309124Sdim	close(IN);
818309124Sdim	return(%ret);
819309124Sdim}
820309124Sdim
821309124Sdimsub parse_number
822309124Sdim{
823309124Sdim	(my $str, my $what) = @_;
824309124Sdim	(my $n, my $i) = split(/\\/,$str);
825309124Sdim	if ($what eq "n") {
826309124Sdim		return $n;
827309124Sdim	} else {
828309124Sdim		return $i;
829309124Sdim	}
830309124Sdim}
831309124Sdim
832309124Sdimsub rewrite_numbers
833309124Sdim{
834309124Sdim	(*OUT,$name,*nums,@symbols)=@_;
835309124Sdim	my $thing;
836309124Sdim
837309124Sdim	print STDERR "Rewriting $name\n";
838309124Sdim
839309124Sdim	my @r = grep(/^\w+\\.*?:.*?:\w+\(\w+\)/,@symbols);
840309124Sdim	my $r; my %r; my %rsyms;
841309124Sdim	foreach $r (@r) {
842309124Sdim		(my $s, my $i) = split /\\/, $r;
843309124Sdim		my $a = $1 if $i =~ /^.*?:.*?:\w+\((\w+)\)/;
844309124Sdim		$i =~ s/^(.*?:.*?:\w+)\(\w+\)/$1/;
845309124Sdim		$r{$a} = $s."\\".$i;
846261991Sdim		$rsyms{$s} = 1;
847218885Sdim	}
848276479Sdim
849296417Sdim	my @s=sort { &parse_number($nums{$a},"n") <=> &parse_number($nums{$b},"n") } keys %nums;
850296417Sdim	foreach $sym (@s) {
851296417Sdim		(my $n, my $i) = split /\\/, $nums{$sym};
852296417Sdim		next if defined($i) && $i =~ /^.*?:.*?:\w+\(\w+\)/;
853276479Sdim		next if defined($rsyms{$sym});
854276479Sdim		$i="NOEXIST::FUNCTION:" if !defined($i) || $i eq "";
855296417Sdim		printf OUT "%s%-40s%d\t%s\n","",$sym,$n,$i;
856296417Sdim		if (exists $r{$sym}) {
857296417Sdim			(my $s, $i) = split /\\/,$r{$sym};
858296417Sdim			printf OUT "%s%-40s%d\t%s\n","",$s,$n,$i;
859276479Sdim		}
860296417Sdim	}
861296417Sdim}
862276479Sdim
863276479Sdimsub update_numbers
864296417Sdim{
865296417Sdim	(*OUT,$name,*nums,my $start_num, my @symbols)=@_;
866296417Sdim	my $new_syms = 0;
867280031Sdim
868296417Sdim	print STDERR "Updating $name numbers\n";
869280031Sdim
870280031Sdim	my @r = grep(/^\w+\\.*?:.*?:\w+\(\w+\)/,@symbols);
871280031Sdim	my $r; my %r; my %rsyms;
872280031Sdim	foreach $r (@r) {
873296417Sdim		(my $s, my $i) = split /\\/, $r;
874280031Sdim		my $a = $1 if $i =~ /^.*?:.*?:\w+\((\w+)\)/;
875280031Sdim		$i =~ s/^(.*?:.*?:\w+)\(\w+\)/$1/;
876280031Sdim		$r{$a} = $s."\\".$i;
877280031Sdim		$rsyms{$s} = 1;
878280031Sdim	}
879280031Sdim
880280031Sdim	foreach $sym (@symbols) {
881296417Sdim		(my $s, my $i) = $sym =~ /^(.*?)\\(.*)$/;
882280031Sdim		next if $i =~ /^.*?:.*?:\w+\(\w+\)/;
883280031Sdim		next if defined($rsyms{$sym});
884280031Sdim		die "ERROR: Symbol $sym had no info attached to it."
885296417Sdim		    if $i eq "";
886296417Sdim		if (!exists $nums{$s}) {
887280031Sdim			$new_syms++;
888280031Sdim			printf OUT "%s%-40s%d\t%s\n","",$s, ++$start_num,$i;
889280031Sdim			if (exists $r{$s}) {
890280031Sdim				($s, $i) = split /\\/,$r{$s};
891280031Sdim				printf OUT "%s%-40s%d\t%s\n","",$s, $start_num,$i;
892280031Sdim			}
893280031Sdim		}
894280031Sdim	}
895280031Sdim	if($new_syms) {
896280031Sdim		print STDERR "$new_syms New symbols added\n";
897296417Sdim	} else {
898296417Sdim		print STDERR "No New symbols Added\n";
899296417Sdim	}
900296417Sdim}
901296417Sdim
902296417Sdimsub check_existing
903296417Sdim{
904296417Sdim	(*nums, my @symbols)=@_;
905280031Sdim	my %existing; my @remaining;
906296417Sdim	@remaining=();
907280031Sdim	foreach $sym (@symbols) {
908280031Sdim		(my $s, my $i) = $sym =~ /^(.*?)\\(.*)$/;
909296417Sdim		$existing{$s}=1;
910280031Sdim	}
911280031Sdim	foreach $sym (keys %nums) {
912276479Sdim		if (!exists $existing{$sym}) {
913276479Sdim			push @remaining, $sym;
914261991Sdim		}
915276479Sdim	}
916276479Sdim	if(@remaining) {
917276479Sdim		print STDERR "The following symbols do not seem to exist:\n";
918276479Sdim		foreach $sym (@remaining) {
919276479Sdim			print STDERR "\t",$sym,"\n";
920261991Sdim		}
921276479Sdim	}
922288943Sdim}
923261991Sdim
924276479Sdim