]> git.saurik.com Git - apple/security.git/blob - cdsa/cdsa_pluginlib/generator.pl
Security-28.tar.gz
[apple/security.git] / cdsa / cdsa_pluginlib / generator.pl
1 #!/usr/bin/perl
2 #
3 # generator.pl - auto-generate code for the CSSM plugin interfaces
4 #
5 # Usage:
6 # perl generator.pl input-directory h-output-dir c-output-dir
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
14 $SOURCEDIR=$ARGV[0]; # where all the input files are
15 $HTARGETDIR=$ARGV[1]; # where the generated headers go
16 $CTARGETDIR=$ARGV[2]; # where the generated sources go
17
18 (${D}) = $HTARGETDIR =~ m@([/:])@; # guess directory delimiter
19 sub macintosh() { return ${D} eq ':'; }
20
21 # XXX The configuration file should be passed in as a command line argument
22 if( macintosh() ) {
23 $APICFG=":::cdsa:cdsa_pluginlib:generator.cfg"; # configuration file
24 }
25 else{
26 $APICFG="generator.cfg"; # configuration file
27 }
28
29 $tabs = "\t\t\t"; # argument indentation (noncritical)
30 $warning = "This file was automatically generated. Do not edit on penalty of futility!";
31
32
33 #
34 # Open and read the configuration file
35 #
36 $/=undef; # gulp file
37 open(APICFG, $APICFG) or die "Cannot open $APICFG: $^E";
38 $_=<APICFG>;
39 close(APICFG);
40 tr/\012/\015/ if macintosh;
41 %optionals = /^\s*optional\s+(\w+)\s+(.*)$/gm;
42
43
44 #
45 # Pre-arranged arrays for processing below
46 #
47 %noDataReturnError = ( CL => "CSSMERR_CL_NO_FIELD_VALUES",
48 DL => "CSSMERR_DL_ENDOFDATA" );
49
50
51 #
52 # process one SPI at a time
53 #
54 while (($type, $header) = each %SPI_H) {
55 my(%functions, %methods, %actuals);
56 ($typelower = $type) =~ tr/A-Z/a-z/; # lowercase version of type
57
58 # start in on the $type header file
59 open(SPI, "$SOURCEDIR${D}$header") or die "cannot open $SOURCEDIR${D}$header: $^E";
60 $/=undef; # big gulp mode
61 $_ = <SPI>; # aaaaah...
62 close(SPI); # done
63 tr/\012/\015/ if macintosh;
64 # throw away leading and trailing crud (only interested in SPI structure)
65 s/^.*struct cssm_spi.*{(.*)} CSSM_SPI.*$/$1/s
66 or die "bad format in $SPI_H{$name}";
67
68 # break up into functions (you'd do that HOW in YOUR language? :-)
69 @functions = /CSSM_RETURN \(CSSM${type}I \*([A-Za-z_]+)\)\s+\(([^)]+)\);/g;
70 %functions = @functions;
71
72 $MOREHEADERS="";
73 $MOREHEADERS .= "#include <Security/context.h>\n" if /CSSM_CONTEXT/;
74 $MOREHEADERS .= "#include <Security/cssmacl.h>\n" if /CSSM_(ACL|ACCESS)/;
75
76 # break function arguments into many forms:
77 # functions => formal SPI arguments
78 # methods => formal C++ method arguments
79 # actuals => actual expression forms for transition layer use
80 # and (by the way) massage them into a more palatable form...
81 $nFunctions = 0;
82 while (($function, $_) = each %functions) {
83 #
84 # Turn CSSM SPI formal into method formal
85 #
86 $returntype{$function} = "void";
87 $prefix{$function} = "";
88 $postfix{$function} = ";";
89 # reshape initial argument (the module handle, more or less)
90 s/^CSSM_${type}_HANDLE ${type}Handle(,\s*\n\s*|$)//s; # remove own handle (-> this)
91 s/^CSSM_DL_DB_HANDLE DLDBHandle/CSSM_DB_HANDLE DBHandle/s; # DL_DB handle -> DB handle
92 s/CSSM_HANDLE_PTR ResultsHandle(,?)\n//m # turn ptr-to-resultshandle into fn result
93 and do {
94 $returntype{$function} = "CSSM_HANDLE";
95 $prefix{$function} = "if ((Required(ResultsHandle) = ";
96 $postfix{$function} = ") == CSSM_INVALID_HANDLE)\n return $noDataReturnError{$type};";
97 };
98 if ($function =~ /GetNext/) { # *GetNext* returns a bool
99 $returntype{$function} = "bool";
100 $prefix{$function} = "if (!";
101 $postfix{$function} = ")\n return $noDataReturnError{$type};";
102 }
103 # reshape subsequent arguments
104 s/([su]int32) \*(\w+,?)/$1 \&$2/gm; # int * -> int & (output integer)
105 s/(CSSM_\w+_PTR) \*(\w+,?)/$1 \&$2/gm; # _PTR * -> _PTR &
106 s/(CSSM_\w+)_PTR (\w+)/$1 \*$2/gm; # XYZ_PTR -> XYZ * (explicit)
107 s/(const )?CSSM_DATA \*(\w+)Bufs/$1CssmData $2Bufs\[\]/gm; # c DATA *Bufs (plural)
108 s/(const )?CSSM_(DATA|OID) \*/$1CssmData \&/gm; # c DATA * -> c Data &
109 s/(const )?CSSM_FIELD \*(\w+)Fields/$1CSSM_FIELD $2Fields\[\]/gm; # c FIELD *Fields (plural)
110 s/(const )?CSSM_FIELD \*CrlTemplate/$1CSSM_FIELD CrlTemplate\[\]/gm; # c FIELD *CrlTemplate
111 s/const CSSM_CONTEXT \*/const Context \&/gm; # c CSSM_CONTEXT * -> c Context &
112 s/(const )?CSSM_ACCESS_CREDENTIALS \*/$1AccessCredentials \&/gm; # ditto
113 s/(const )?CSSM_QUERY_SIZE_DATA \*/$1QuerySizeData \&/gm; # ditto
114 s/(const )?CSSM_CSP_OPERATIONAL_STATISTICS \*/$1CSPOperationalStatistics \&/gm; # ditto
115 s/(const )?CSSM_(WRAP_)?KEY \*/$1CssmKey \&/gm; # CSSM[WRAP]KEY * -> CssmKey &
116 s/const CSSM_QUERY \*/const DLQuery \&/gm; # c QUERY * -> c Query &
117 s/(const )?(CSSM_[A-Z_]+) \*/$1$2 \&/gm; # c CSSM_ANY * -> c CSSM_ANY &
118 $methods{$function} = $_;
119
120 #
121 # Now turn the method formal into the transition invocation actuals
122 #
123 s/^CSSM_DB_HANDLE \w+(,?)/DLDBHandle.DBHandle$1/s; # matching change to DL_DB handles
124 s/(const )?([A-Z][a-z]\w+) &(\w+)(,?)/$2::required($3)$4/gm; # BIG_ * -> Small_ &
125 s/(const )?CssmData (\w+)Bufs\[\](,?)/\&\&CssmData::required($2Bufs)$3/gm; # c DATA *DataBufs
126 s/(const )?CSSM_FIELD (\w+)Fields\[\](,?)/$2Fields$3/gm; # c CSSM_FIELD *Fields
127 s/(const )?CSSM_FIELD CrlTemplate\[\](,?)/CrlTemplate$2/gm; # c CSSM_FIELD *CrlTemplate
128 # now remove formal arguments and clean up
129 s/^.* \&\&(\w+,?)/$tabs\&$1/gm; # && escape (to keep real &)
130 s/^.* \&(\w+)(,?)/${tabs}Required($1)$2/gm; # dereference for ref transition
131 s/^.* \**(\w+,?)/$tabs$1/gm; # otherwise, plain actual argument
132 s/^$tabs//;
133 $actuals{$function} = $_;
134
135 #
136 # Fix optional arguments
137 #
138 foreach $opt (split " ", $optionals{$function}) {
139 $methods{$function} =~ s/\&$opt\b/\*$opt/; # turn refs back into pointers
140 $actuals{$function} =~ s/::required\($opt\)/::optional($opt)/; # optional specific
141 $actuals{$function} =~ s/Required\($opt\)/$opt/; # optional generic
142 };
143 $nFunctions++;
144 };
145
146 #
147 # Prepare to write header and source files
148 #
149 open(H, ">$HTARGETDIR${D}${type}abstractsession.h") or die "cannot write ${type}abstractsession.h: $^E";
150 open(C, ">$CTARGETDIR${D}${type}abstractsession.cpp") or die "cannot write ${type}abstractsession.cpp: $^E";
151
152 #
153 # Create header file
154 #
155 print H <<HDRHEAD;
156 //
157 // $type plugin transition layer.
158 // $warning
159 //
160 #ifndef _H_${type}ABSTRACTSESSION
161 #define _H_${type}ABSTRACTSESSION
162
163 #include <Security/pluginsession.h>
164 $MOREHEADERS
165 #if defined(_CPP_${type}ABSTRACTSESSION)
166 # pragma export on
167 #endif
168
169 namespace Security
170 {
171
172 //
173 // A pure abstract class to define the ${type} module interface
174 //
175 class ${type}AbstractPluginSession {
176 public:
177 HDRHEAD
178
179 $functionCount = 0;
180 while (($function, $arglist) = each %methods) {
181 # generate method declaration
182 print H " virtual $returntype{$function} $function($arglist) = 0;\n";
183 $functionCount++;
184 };
185 print H <<HDREND;
186 };
187
188 } // end namespace Security
189
190 #if defined(_CPP_${type}ABSTRACTSESSION)
191 # pragma export off
192 #endif
193
194 #endif //_H_${type}ABSTRACTSESSION
195 HDREND
196
197 #
198 # Create source file
199 #
200 print C <<BODY;
201 //
202 // $type plugin transition layer.
203 // $warning
204 //
205 #if defined(__MWERKS__)
206 # define _CPP_${type}ABSTRACTSESSION
207 # define _CPP_${type}SESSION
208 #endif
209 #include <Security/${type}session.h>
210 #include <Security/cssmplugin.h>
211 #include <Security/cssm${typelower}i.h>
212
213 BODY
214
215 # write transition layer functions
216 while (($function, $arglist) = each %functions) {
217 $lookupHandle = "${type}Handle";
218 $lookupHandle = "DLDBHandle.DLHandle" if $arglist =~ /DL_DB_HANDLE/;
219 print C <<SHIM;
220 static CSSM_RETURN CSSM${type}I cssm_$function($arglist)
221 {
222 BEGIN_API
223 ${prefix{$function}}findSession<${type}PluginSession>($lookupHandle).$function($actuals{$function})${postfix{$function}}
224 END_API($type)
225 }
226
227 SHIM
228 };
229
230 # generate dispatch table - in the right order, please
231 print C "\nstatic const CSSM_SPI_${type}_FUNCS ${type}FunctionStruct = {\n";
232 while ($function = shift @functions) {
233 print C " cssm_$function,\n";
234 shift @functions; # skip over arglist part
235 };
236 print C "};\n\n";
237
238 print C <<END;
239 static CSSM_MODULE_FUNCS ${type}FunctionTable = {
240 CSSM_SERVICE_$type, // service type
241 $functionCount, // number of functions
242 (const CSSM_PROC_ADDR *)&${type}FunctionStruct
243 };
244
245 CSSM_MODULE_FUNCS_PTR ${type}PluginSession::construct()
246 {
247 return &${type}FunctionTable;
248 }
249 END
250
251 #
252 # Done with this type
253 #
254 close(H);
255 close(C);
256
257 print "$nFunctions functions generated for $type SPI transition layer.\n";
258 };