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