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 28open(APICFG, $APICFG) or die "Cannot open $APICFG: $^E"; 29$_=<APICFG>; 30close(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# 44while (($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 160namespace Security { 161 162 163// 164// A pure abstract class to define the ${type} module interface 165// 166class ${type}AbstractPluginSession { 167public: 168 virtual ~${type}AbstractPluginSession(); 169HDRHEAD 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 183HDREND 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 202BODY 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; 209static 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 216SHIM 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; 228static 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 234CSSM_MODULE_FUNCS_PTR ${type}PluginSession::construct() 235{ 236 return &${type}FunctionTable; 237} 238END 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}; 248