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