@API_H=("cssmapi.h");
%SPI_H=("AC" => "cssmaci.h", "CSP" => "cssmcspi.h", "DL" => "cssmdli.h",
"CL" => "cssmcli.h", "TP" => "cssmtpi.h");
$SOURCEDIR=$ARGV[0]; $APICFG=$ARGV[1]; $HTARGETDIR=$ARGV[2]; $CTARGETDIR=$ARGV[3];
$tabs = "\t\t\t"; $warning = "This file was automatically generated. Do not edit on penalty of futility!";
$/=undef; open(APICFG, $APICFG) or die "Cannot open $APICFG: $^E";
$_=<APICFG>;
close(APICFG);
%optionals = /^\s*optional\s+(\w+)\s+(.*)$/gm;
%noDataReturnError = ( CL => "CSSMERR_CL_NO_FIELD_VALUES",
DL => "CSSMERR_DL_ENDOFDATA" );
while (($type, $header) = each %SPI_H) {
my(%functions, %methods, %actuals);
($typelower = $type) =~ tr/A-Z/a-z/;
open(SPI, "$SOURCEDIR/$header") or die "cannot open $SOURCEDIR/$header: $^E";
$/=undef; $_ = <SPI>; close(SPI); s/^.*struct cssm_spi.*{(.*)} CSSM_SPI.*$/$1/s
or die "bad format in $SPI_H{$name}";
@functions = /CSSM_RETURN \(CSSM${type}I \*([A-Za-z_]+)\)\s+\(([^)]+)\);/g;
%functions = @functions;
$MOREHEADERS="";
$MOREHEADERS .= "#include <Security/context.h>\n" if /CSSM_CONTEXT/;
$MOREHEADERS .= "#include <Security/cssmacl.h>\n" if /CSSM_(ACL|ACCESS)/;
$nFunctions = 0;
while (($function, $_) = each %functions) {
$returntype{$function} = "void";
$prefix{$function} = "";
$postfix{$function} = ";";
s/^CSSM_${type}_HANDLE ${type}Handle(,\s*\n\s*|$)//s; # remove own handle (-> this)
s/^CSSM_DL_DB_HANDLE DLDBHandle/CSSM_DB_HANDLE DBHandle/s; s/CSSM_HANDLE_PTR ResultsHandle(,?)\n//m # turn ptr-to-resultshandle into fn result
and do {
$returntype{$function} = "CSSM_HANDLE";
$prefix{$function} = "if ((Required(ResultsHandle) = ";
$postfix{$function} = ") == CSSM_INVALID_HANDLE)\n return $noDataReturnError{$type};";
};
if ($function =~ /GetNext/) { $returntype{$function} = "bool";
$prefix{$function} = "if (!";
$postfix{$function} = ")\n return $noDataReturnError{$type};";
}
s/([su]int32) \*(\w+,?)/$1 \&$2/gm; s/(CSSM_\w+_PTR) \*(\w+,?)/$1 \&$2/gm; s/(CSSM_\w+)_PTR (\w+)/$1 \*$2/gm; s/(const )?CSSM_DATA \*(\w+)Bufs/$1CssmData $2Bufs\[\]/gm; s/(const )?CSSM_(DATA|OID) \*/$1CssmData \&/gm; s/(const )?CSSM_FIELD \*(\w+)Fields/$1CSSM_FIELD $2Fields\[\]/gm; s/(const )?CSSM_FIELD \*CrlTemplate/$1CSSM_FIELD CrlTemplate\[\]/gm; s/const CSSM_CONTEXT \*/const Context \&/gm; s/(const )?CSSM_ACCESS_CREDENTIALS \*/$1AccessCredentials \&/gm; s/(const )?CSSM_QUERY_SIZE_DATA \*/$1QuerySizeData \&/gm; s/(const )?CSSM_CSP_OPERATIONAL_STATISTICS \*/$1CSPOperationalStatistics \&/gm; s/(const )?CSSM_(WRAP_)?KEY \*/$1CssmKey \&/gm; s/const CSSM_QUERY \*/const DLQuery \&/gm; s/(const )?(CSSM_[A-Z_]+) \*/$1$2 \&/gm; $methods{$function} = $_;
s/^CSSM_DB_HANDLE \w+(,?)/DLDBHandle.DBHandle$1/s; s/(const )?([A-Z][a-z]\w+) &(\w+)(,?)/$2::required($3)$4/gm; s/(const )?CssmData (\w+)Bufs\[\](,?)/\&\&CssmData::required($2Bufs)$3/gm; s/(const )?CSSM_FIELD (\w+)Fields\[\](,?)/$2Fields$3/gm; s/(const )?CSSM_FIELD CrlTemplate\[\](,?)/CrlTemplate$2/gm; s/^.* \&\&(\w+,?)/$tabs\&$1/gm; s/^.* \&(\w+)(,?)/${tabs}Required($1)$2/gm; s/^.* \**(\w+,?)/$tabs$1/gm; s/^$tabs//;
$actuals{$function} = $_;
foreach $opt (split " ", $optionals{$function}) {
$methods{$function} =~ s/\&$opt\b/\*$opt/; $actuals{$function} =~ s/::required\($opt\)/::optional($opt)/; $actuals{$function} =~ s/Required\($opt\)/$opt/; };
$nFunctions++;
};
open(H, ">$HTARGETDIR/${type}abstractsession.h") or die "cannot write ${type}abstractsession.h: $^E";
open(C, ">$CTARGETDIR/${type}abstractsession.cpp") or die "cannot write ${type}abstractsession.cpp: $^E";
print H <<HDRHEAD;
//
// $type plugin transition layer.
// $warning
//
$MOREHEADERS
namespace Security
{
//
// A pure abstract class to define the ${type} module interface
//
class ${type}AbstractPluginSession {
public:
HDRHEAD
$functionCount = 0;
while (($function, $arglist) = each %methods) {
print H " virtual $returntype{$function} $function($arglist) = 0;\n";
$functionCount++;
};
print H <<HDREND;
};
} // end namespace Security
HDREND
print C <<BODY;
//
// $type plugin transition layer.
// $warning
//
BODY
while (($function, $arglist) = each %functions) {
$lookupHandle = "${type}Handle";
$lookupHandle = "DLDBHandle.DLHandle" if $arglist =~ /DL_DB_HANDLE/;
print C <<SHIM;
static CSSM_RETURN CSSM${type}I cssm_$function($arglist)
{
BEGIN_API
${prefix{$function}}findSession<${type}PluginSession>($lookupHandle).$function($actuals{$function})${postfix{$function}}
END_API($type)
}
SHIM
};
print C "\nstatic const CSSM_SPI_${type}_FUNCS ${type}FunctionStruct = {\n";
while ($function = shift @functions) {
print C " cssm_$function,\n";
shift @functions; };
print C "};\n\n";
print C <<END;
static CSSM_MODULE_FUNCS ${type}FunctionTable = {
CSSM_SERVICE_$type, // service type
$functionCount, // number of functions
(const CSSM_PROC_ADDR *)&${type}FunctionStruct
};
CSSM_MODULE_FUNCS_PTR ${type}PluginSession::construct()
{
return &${type}FunctionTable;
}
END
close(H);
close(C);
print "$nFunctions functions generated for $type SPI transition layer.\n";
};