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