]> git.saurik.com Git - apple/security.git/blob - libsecurity_cssm/lib/generator.pl
Security-55163.44.tar.gz
[apple/security.git] / libsecurity_cssm / lib / generator.pl
1 #!/usr/bin/perl
2 #
3 # Copyright (c) 2001-2004 Apple Computer, Inc. All Rights Reserved.
4 #
5 # @APPLE_LICENSE_HEADER_START@
6 #
7 # This file contains Original Code and/or Modifications of Original Code
8 # as defined in and that are subject to the Apple Public Source License
9 # Version 2.0 (the 'License'). You may not use this file except in
10 # compliance with the License. Please obtain a copy of the License at
11 # http://www.opensource.apple.com/apsl/ and read it before using this
12 # file.
13 #
14 # The Original Code and all software distributed under the License are
15 # distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 # EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 # INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 # FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
19 # Please see the License for the specific language governing rights and
20 # limitations under the License.
21 #
22 # @APPLE_LICENSE_HEADER_END@
23 #
24 # generator.pl - derive various and sundry C++ code from the CDSA header files
25 #
26 # Usage:
27 # perl generator.pl input-directory config-file output-directory
28 #
29 # Perry The Cynic, Fall 1999.
30 #
31 @API_H=("cssmapi.h");
32 %SPI_H=("AC" => "cssmaci.h", "CSP" => "cssmcspi.h", "DL" => "cssmdli.h",
33 "CL" => "cssmcli.h", "TP" => "cssmtpi.h");
34 @OIDS_H=("oidscert.h", "oidscrl.h");
35 @OIDS_H2=("oidsattr.h", "oidsalg.h");
36
37 $SOURCEDIR=$ARGV[0]; # directory with inputs
38 $APICFG=$ARGV[1]; # configuration file
39 $TARGETDIR=$ARGV[2]; # directory for outputs
40
41
42 $TRANSITION="$TARGETDIR/transition.gen"; # C++ code for transition layer
43 $TABLES="$TARGETDIR/funcnames.gen"; # function name tables
44 $REPORT="$TARGETDIR/generator.rpt"; # report file
45 $EXPORTS="$TARGETDIR/cssmexports.gen"; # Exports file
46
47 $tabs = "\t\t\t"; # argument indentation (noncritical)
48 $warning = "This file was automatically generated. Do not edit on penalty of futility!";
49
50
51 #
52 # Parse API headers and extract function names and argument lists
53 #
54 # Jim Muprhy I added [^;]* to the end of the %formals variable to
55 # allow for deprecation macros.
56 #
57 $/=undef; # big gulp mode
58 foreach $_ (@API_H) {
59 open(API_H, "$SOURCEDIR/$_") or die "Cannot open $SOURCEDIR/$_: $^E";
60 $_ = <API_H>; # glglgl... aaaaah
61 %formals = /CSSM_RETURN CSSMAPI\s*([A-Za-z_]+)\s+\(([^)]*)\)[^;]*;/gs;
62 while (($name, $args) = each %formals) {
63 $args =~ s/^.*[ *]([A-Za-z_]+,?)$/$tabs$1/gm; # remove type declarators
64 $args =~ s/^$tabs//o; # chop intial tabs # so now we have...
65 $actuals{$name} = $args; # ...an actual argument list
66 };
67 };
68 close(API_H);
69
70
71 #
72 # Slurp SPI headers into memory for future use
73 #
74 $/=undef; # slurp files
75 while (($key, $file) = each %SPI_H) {
76 open(SPI_H, "$SOURCEDIR/$file") or die "Cannot open $SOURCEDIR/$file: $^E";
77 $spi{$key} = <SPI_H>;
78 };
79 close(SPI_H);
80
81
82 #
83 # Open and read the configuration file
84 #
85 $/=undef; # gulp yet again
86 open(APICFG, $APICFG) or die "Cannot open $APICFG: $^E";
87 $_=<APICFG>;
88 close(APICFG);
89 %config = /^\s*(\w+)\s+(.*)$/gm;
90
91
92 #
93 # Now we will generate the API transition layer.
94 # The idea here is that for each function in the API, we try to
95 # figure out what type of plugin it belongs to, and then look up
96 # its evil twin in that type's header. If that works, we generate
97 # a function for the transition, taking care of various oddities
98 # and endities in the process.
99 #
100 open(OUT, ">$TRANSITION") or die "Cannot write $TRANSITION: $^E";
101 select OUT;
102 open(REPORT, ">$REPORT") or die "Cannot write $REPORT: $^E";
103
104 sub ignored {
105 my ($reason) = @_;
106 $ignored++;
107 print REPORT "$name $reason\n";
108 };
109
110 print "//
111 // $warning
112 //";
113
114 for $name (sort keys %formals) {
115 $config = $config{$name};
116 do { ignored "has custom implementation"; next; } if $config =~ /custom/;
117
118 ($barename) = $name =~ /^CSSM.*_([A-Za-z]+$)/;
119 die "Can't fathom SPI name for $name" unless $barename;
120 $actuals = $actuals{$name};
121
122 # key off the type code in the first argument: CSSM_type_HANDLE
123 ($type, $handle) = $formals{$name} =~ /CSSM_([A-Z_]+)_HANDLE\s+([A-Za-z0-9_]+)/;
124 $type = "CSP" if $type eq "CC"; # CSP methods may have CC (context) handles
125 $type = "DL" if $type eq "DL_DB"; # DL methods may have DL_DB handles
126 $type = "KR" if $type eq "KRSP"; # KR methods have KRSP handles
127 $Type = $type . "Attachment";
128 do { ignored "has no module type"; next; } unless defined $SPI_H{$type};
129
130 # $prefix will hold code to be generated before the actual call
131 $prefix = "";
132
133 # match the SPI; take care of the Privilege variants of some calls
134 # Jim Murphy Added [^;]* before the ; to allow for deprecation macros
135 ($args) = $spi{$type} =~ /CSSM_RETURN \(CSSM${type}I \*$barename\)\s+\(([^)]*)\)[^;]*;/s
136 or $barename =~ s/P$// && # second chance for FooBarP() API functions
137 (($args) = $spi{$type} =~ /CSSM_RETURN \(CSSM${type}I \*$barename\)\s+\(([^)]*)\)[^;]*;/s)
138 or do { ignored "not in $SPI_H{$type}"; next; };
139
140 # take care of CSP calls taking context handles
141 $handletype = $type;
142 $type eq "CSP" && $actuals =~ /CCHandle/ && do {
143 $actuals =~ s/CCHandle/context.CSPHandle, CCHandle/;
144 $args =~ /CSSM_CONTEXT/ &&
145 $actuals =~ s/CCHandle/CCHandle, &context/;
146 $handletype = "CC";
147 };
148
149 # add the default privilege argument to non-P functions taking privileges
150 $args =~ /CSSM_PRIVILEGE/ && ! ($name =~ /P$/) && # add privilege argument (last)
151 ($actuals .= ",\n${tabs}attachment.module.cssm.getPrivilege()");
152
153 # finally translate DLDBHandles into their DL component
154 $handle =~ s/DLDBHandle/DLDBHandle.DLHandle/;
155
156 # payoff time
157 print "
158 CSSM_RETURN CSSMAPI
159 $name ($formals{$name})
160 {
161 BEGIN_API";
162 if ($handletype eq "CC") {
163 print "
164 HandleContext &context = enterContext($handle);
165 CSPAttachment &attachment = context.attachment;";
166 } else {
167 print "
168 $Type &attachment = enterAttachment<$Type>($handle);";
169 };
170 print "
171 TransitLock _(attachment);
172 ${prefix}return attachment.downcalls.$barename($actuals);
173 END_API($type)
174 }
175 ";
176 $written++;
177 };
178 close(OUT);
179 select(STDOUT);
180
181
182 #
183 # Now peruse the SPI headers for a list of function names
184 # and build in-memory translation tables for runtime.
185 #
186 open(OUT, ">$TABLES") or die "Cannot write $TABLES: $^E";
187 select OUT;
188
189 print "//
190 // Standard plugin name tables
191 // $warning
192 //
193 ";
194 while (($name, $_) = each %spi) {
195 print "extern const char *const ${name}NameTable[] = {";
196 s/^.*struct cssm_spi.*{(.*)} CSSM_SPI.*$/$1/s
197 or die "bad format in $SPI_H{$name}";
198 s/CSSM_RETURN \(CSSM[A-Z]*I \*([A-Za-z_]+)\)\s+\([^)]+\)[^;]*;/\t"$1",/g;
199 print;
200 print "};\n\n";
201 };
202 close(OUT);
203 select(STDOUT);
204
205 #
206 # Finally, generate linker export file to avoid leaking internal symbols
207 #
208 open(OUT, ">$EXPORTS") or die "Cannot write $EXPORTS: $^E";
209 select(OUT);
210
211 # entry point names (functions)
212 for $name (keys %formals) {
213 $symbols{$name} = 1;
214 };
215
216 # OID-related data symbols
217 $/=undef;
218 foreach $_ (@OIDS_H) {
219 open(OIDS_H, "$SOURCEDIR/$_") or die "Cannot open $SOURCEDIR/$_: $^E";
220 $_ = <OIDS_H>; # glglgl... aaaaah
221 s/\/\*.*\*\///gm; # remove comments
222
223 foreach $name (/\s+(CSSMOID_[A-Za-z0-9_]+)/gs) {
224 $symbols{$name} = 1;
225 };
226 };
227 close(OIDS_H);
228
229 foreach $_ (@OIDS_H2) {
230 open(OIDS_H2, "$SOURCEDIR/../../libsecurity_asn1/lib/$_") or die "Cannot open $SOURCEDIR/$_: $^E";
231 $_ = <OIDS_H2>; # glglgl... aaaaah
232 s/\/\*.*\*\///gm; # remove comments
233
234 foreach $name (/\s+(CSSMOID_[A-Za-z0-9_]+)/gs) {
235 $symbols{$name} = 1;
236 };
237 };
238 close(OIDS_H2);
239
240 foreach $name (keys %symbols) {
241 print "_$name\n";
242 };
243
244 close(OUT);
245 select(STDOUT);
246
247
248 close(EXPORTS);
249 close(REPORT);
250 print "$written API functions generated; $ignored ignored (see $REPORT)\n";