]>
git.saurik.com Git - apple/security.git/blob - cdsa/cdsa_pluginlib/generator.pl
3 # generator.pl - auto-generate code for the CSSM plugin interfaces
6 # perl generator.pl input-directory h-output-dir c-output-dir
8 # Perry The Cynic, Fall 1999.
11 %SPI_H=("AC" => "cssmaci.h", "CSP" => "cssmcspi.h", "DL" => "cssmdli.h",
12 "CL" => "cssmcli.h", "TP" => "cssmtpi.h");
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
18 (${D
}) = $HTARGETDIR =~ m
@([/:])@; # guess directory delimiter
19 sub macintosh
() { return ${D
} eq ':'; }
21 # XXX The configuration file should be passed in as a command line argument
23 $APICFG=":::cdsa:cdsa_pluginlib:generator.cfg"; # configuration file
26 $APICFG="generator.cfg"; # configuration file
29 $tabs = "\t\t\t"; # argument indentation (noncritical)
30 $warning = "This file was automatically generated. Do not edit on penalty of futility!";
34 # Open and read the configuration file
37 open(APICFG
, $APICFG) or die "Cannot open $APICFG: $^E";
40 tr/\012/\015/ if macintosh
;
41 %optionals = /^\s*optional\s+(\w+)\s+(.*)$/gm;
45 # Pre-arranged arrays for processing below
47 %noDataReturnError = ( CL
=> "CSSMERR_CL_NO_FIELD_VALUES",
48 DL
=> "CSSMERR_DL_ENDOFDATA" );
52 # process one SPI at a time
54 while (($type, $header) = each %SPI_H) {
55 my(%functions, %methods, %actuals);
56 ($typelower = $type) =~ tr/A-Z/a-z/; # lowercase version of type
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...
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}";
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;
73 $MOREHEADERS .= "#include <Security/context.h>\n" if /CSSM_CONTEXT
/;
74 $MOREHEADERS .= "#include <Security/cssmacl.h>\n" if /CSSM_
(ACL
|ACCESS
)/;
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...
82 while (($function, $_) = each %functions) {
84 # Turn CSSM SPI formal into method formal
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
94 $returntype{$function} = "CSSM_HANDLE";
95 $prefix{$function} = "if ((Required(ResultsHandle) = ";
96 $postfix{$function} = ") == CSSM_INVALID_HANDLE)\n return $noDataReturnError{$type};";
98 if ($function =~ /GetNext/) { # *GetNext* returns a bool
99 $returntype{$function} = "bool";
100 $prefix{$function} = "if (!";
101 $postfix{$function} = ")\n return $noDataReturnError{$type};";
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} = $_;
121 # Now turn the method formal into the transition invocation actuals
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
133 $actuals{$function} = $_;
136 # Fix optional arguments
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
147 # Prepare to write header and source files
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";
157 // $type plugin transition layer.
160 #ifndef _H_${type}ABSTRACTSESSION
161 #define _H_${type}ABSTRACTSESSION
163 #include <Security/pluginsession.h>
165 #if defined(_CPP_${type}ABSTRACTSESSION)
173 // A pure abstract class to define the ${type} module interface
175 class ${type}AbstractPluginSession {
180 while (($function, $arglist) = each %methods) {
181 # generate method declaration
182 print H
" virtual $returntype{$function} $function($arglist) = 0;\n";
188 } // end namespace Security
190 #if defined(_CPP_${type}ABSTRACTSESSION)
194 #endif //_H_${type}ABSTRACTSESSION
202 // $type plugin transition layer.
205 #if defined(__MWERKS__)
206 # define _CPP_${type}ABSTRACTSESSION
207 # define _CPP_${type}SESSION
209 #include <Security/${type}session.h>
210 #include <Security/cssmplugin.h>
211 #include <Security/cssm${typelower}i.h>
215 # write transition layer functions
216 while (($function, $arglist) = each %functions) {
217 $lookupHandle = "${type}Handle";
218 $lookupHandle = "DLDBHandle.DLHandle" if $arglist =~ /DL_DB_HANDLE/;
220 static CSSM_RETURN CSSM${type}I cssm_$function($arglist)
223 ${prefix{$function}}findSession<${type}PluginSession>($lookupHandle).$function($actuals{$function})${postfix{$function}}
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
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
245 CSSM_MODULE_FUNCS_PTR ${type}PluginSession::construct()
247 return &${type}FunctionTable;
252 # Done with this type
257 print "$nFunctions functions generated for $type SPI transition layer.\n";