]>
Commit | Line | Data |
---|---|---|
b1ab9ed8 A |
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"; |