/ OSX / libsecurity_cssm / lib / generator.pl
generator.pl
  1  #!/usr/bin/perl
  2  #
  3  # Copyright (c) 2001-2004,2011-2012,2014 Apple Inc. All Rights Reserved.
  4  #
  5  # @APPLE_LICENSE_HEADER_START@
  6  # 
  7  # This file contains Original Code and/or Modifications of Original Code
  8  # as defined in and that are subject to the Apple Public Source License
  9  # Version 2.0 (the 'License'). You may not use this file except in
 10  # compliance with the License. Please obtain a copy of the License at
 11  # http://www.opensource.apple.com/apsl/ and read it before using this
 12  # file.
 13  # 
 14  # The Original Code and all software distributed under the License are
 15  # distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
 16  # EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
 17  # INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
 18  # FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
 19  # Please see the License for the specific language governing rights and
 20  # limitations under the License.
 21  # 
 22  # @APPLE_LICENSE_HEADER_END@
 23  #
 24  # generator.pl - derive various and sundry C++ code from the CDSA header files
 25  #
 26  # Usage:
 27  #	perl generator.pl input-directory config-file output-directory
 28  #
 29  # Perry The Cynic, Fall 1999.
 30  #
 31  @API_H=("cssmapi.h");
 32  %SPI_H=("AC" => "cssmaci.h", "CSP" => "cssmcspi.h", "DL" => "cssmdli.h",
 33          "CL" => "cssmcli.h", "TP"  => "cssmtpi.h");
 34  @OIDS_H=("oidscert.h", "oidscrl.h");
 35  @OIDS_H2=("oidsattr.h", "oidsalg.h");
 36  
 37  $SOURCEDIR=$ARGV[0];			# directory with inputs
 38  $APICFG=$ARGV[1];				# configuration file
 39  $TARGETDIR=$ARGV[2];			# directory for outputs
 40  
 41  
 42  $TRANSITION="$TARGETDIR/transition.gen"; # C++ code for transition layer
 43  $TABLES="$TARGETDIR/funcnames.gen";		# function name tables
 44  $REPORT="$TARGETDIR/generator.rpt";		# report file
 45  $EXPORTS="$TARGETDIR/cssmexports.gen";	# Exports file
 46  
 47  $tabs = "\t\t\t";	# argument indentation (noncritical)
 48  $warning = "This file was automatically generated. Do not edit on penalty of futility!";
 49  
 50  
 51  #
 52  # Parse API headers and extract function names and argument lists
 53  #
 54  # Jim Muprhy I added [^;]* to the end of the %formals variable to
 55  # allow for deprecation macros.
 56  #
 57  $/=undef;	# big gulp mode
 58  foreach $_ (@API_H) {
 59    open(API_H, "$SOURCEDIR/$_") or die "Cannot open $SOURCEDIR/$_: $^E";
 60    $_ = <API_H>;		# glglgl... aaaaah
 61    %formals = /CSSM_RETURN CSSMAPI\s*([A-Za-z_]+)\s+\(([^)]*)\)[^;]*;/gs;
 62    while (($name, $args) = each %formals) {
 63      $args =~ s/^.*[ *]([A-Za-z_]+,?)$/$tabs$1/gm;	# remove type declarators
 64      $args =~ s/^$tabs//o;	# chop intial tabs		# so now we have...
 65      $actuals{$name} = $args;						# ...an actual argument list
 66    };
 67  };
 68  close(API_H);
 69  
 70  
 71  #
 72  # Slurp SPI headers into memory for future use
 73  #
 74  $/=undef;	# slurp files
 75  while (($key, $file) = each %SPI_H) {
 76    open(SPI_H, "$SOURCEDIR/$file") or die "Cannot open $SOURCEDIR/$file: $^E";
 77    $spi{$key} = <SPI_H>;
 78  };
 79  close(SPI_H);
 80  
 81  
 82  #
 83  # Open and read the configuration file
 84  #
 85  $/=undef;	# gulp yet again
 86  open(APICFG, $APICFG) or die "Cannot open $APICFG: $^E";
 87  $_=<APICFG>;
 88  close(APICFG);
 89  %config = /^\s*(\w+)\s+(.*)$/gm;
 90  
 91  
 92  #
 93  # Now we will generate the API transition layer.
 94  # The idea here is that for each function in the API, we try to
 95  # figure out what type of plugin it belongs to, and then look up
 96  # its evil twin in that type's header. If that works, we generate
 97  # a function for the transition, taking care of various oddities
 98  # and endities in the process.
 99  #
100  open(OUT, ">$TRANSITION") or die "Cannot write $TRANSITION: $^E";
101  select OUT;
102  open(REPORT, ">$REPORT") or die "Cannot write $REPORT: $^E";
103  
104  sub ignored {
105    my ($reason) = @_;
106    $ignored++;
107    print REPORT "$name $reason\n";
108  };
109  
110  print "//
111  // $warning
112  //";
113  
114  for $name (sort keys %formals) {
115    $config = $config{$name};
116    do { ignored "has custom implementation"; next; } if $config =~ /custom/;
117  
118    ($barename) = $name =~ /^CSSM.*_([A-Za-z]+$)/;
119    die "Can't fathom SPI name for $name" unless $barename;
120    $actuals = $actuals{$name};
121  
122    # key off the type code in the first argument: CSSM_type_HANDLE
123    ($type, $handle) = $formals{$name} =~ /CSSM_([A-Z_]+)_HANDLE\s+([A-Za-z0-9_]+)/;
124    $type = "CSP" if $type eq "CC";	# CSP methods may have CC (context) handles
125    $type = "DL" if $type eq "DL_DB";	# DL methods may have DL_DB handles
126    $type = "KR" if $type eq "KRSP";	# KR methods have KRSP handles
127    $Type = $type . "Attachment";
128    do { ignored "has no module type"; next; } unless defined $SPI_H{$type};
129  
130    # $prefix will hold code to be generated before the actual call
131    $prefix = "";
132  
133    # match the SPI; take care of the Privilege variants of some calls
134    ($args) = $spi{$type} =~ /CSSM_RETURN \(CSSM${type}I \*$barename\)\s+\(([^)]*)\)[^;]*;/s
135      or $barename =~ s/P$// &&	# second chance for FooBarP() API functions
136        (($args) = $spi{$type} =~ /CSSM_RETURN \(CSSM${type}I \*$barename\)\s+\(([^)]*)\)[^;]*;/s)
137      or do { ignored "not in $SPI_H{$type}"; next; };
138  
139    # take care of CSP calls taking context handles
140    $handletype = $type;
141    $type eq "CSP" && $actuals =~ /CCHandle/ && do {
142      $actuals =~ s/CCHandle/context.CSPHandle, CCHandle/;
143      $args =~ /CSSM_CONTEXT/ &&
144        $actuals =~ s/CCHandle/CCHandle, &context/;
145      $handletype = "CC";
146    };
147  
148    # add the default privilege argument to non-P functions taking privileges
149    $args =~ /CSSM_PRIVILEGE/ && ! ($name =~ /P$/) &&			# add privilege argument (last)
150      ($actuals .= ",\n${tabs}attachment.module.cssm.getPrivilege()");
151  
152    # finally translate DLDBHandles into their DL component
153    $handle =~ s/DLDBHandle/DLDBHandle.DLHandle/;
154  
155    # payoff time
156    print "
157  CSSM_RETURN CSSMAPI
158  $name ($formals{$name})
159  {
160    BEGIN_API";
161    if ($handletype eq "CC") {
162      print "
163    HandleContext &context = enterContext($handle);
164    CSPAttachment &attachment = context.attachment;";
165    } else {
166      print "
167    $Type &attachment = enterAttachment<$Type>($handle);";
168    };
169    print "
170    TransitLock _(attachment);
171    ${prefix}return attachment.downcalls.$barename($actuals);
172    END_API($type)
173  }
174  ";
175    $written++;
176  };
177  close(OUT);
178  select(STDOUT);
179  
180  
181  #
182  # Now peruse the SPI headers for a list of function names
183  # and build in-memory translation tables for runtime.
184  #
185  open(OUT, ">$TABLES") or die "Cannot write $TABLES: $^E";
186  select OUT;
187  
188  print "//
189  // Standard plugin name tables
190  // $warning
191  //
192  ";
193  while (($name, $_) = each %spi) {
194    print "extern const char *const ${name}NameTable[] = {";
195      s/^.*struct(?: DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER)? cssm_spi.*{(.*)} CSSM_SPI.*$/$1/s
196      or die "bad format in $SPI_H{$name}";
197    s/CSSM_RETURN \(CSSM[A-Z]*I \*([A-Za-z_]+)\)\s+\([^)]+\)[^;]*;/\t"$1",/g;
198    print;
199    print "};\n\n";
200  };
201  close(OUT);
202  select(STDOUT);
203  
204  #
205  # Finally, generate linker export file to avoid leaking internal symbols
206  #
207  open(OUT, ">$EXPORTS") or die "Cannot write $EXPORTS: $^E";
208  select(OUT);
209  
210  # entry point names (functions)
211  for $name (keys %formals) {
212    $symbols{$name} = 1;
213  };
214  
215  # OID-related data symbols
216  $/=undef;
217  foreach $_ (@OIDS_H) {
218    open(OIDS_H, "$SOURCEDIR/$_") or die "Cannot open $SOURCEDIR/$_: $^E";
219    $_ = <OIDS_H>;		# glglgl... aaaaah
220    s/\/\*.*\*\///gm;	# remove comments
221    
222    foreach $name (/\s+(CSSMOID_[A-Za-z0-9_]+)/gs) {
223      $symbols{$name} = 1;
224    };
225  };
226  close(OIDS_H);
227  
228  foreach $_ (@OIDS_H2) {
229      open(OIDS_H2, "$SOURCEDIR/../../libsecurity_asn1/lib/$_") or die "Cannot open $SOURCEDIR/$_: $^E";
230      $_ = <OIDS_H2>;		# glglgl... aaaaah
231      s/\/\*.*\*\///gm;	# remove comments
232      
233      foreach $name (/\s+(CSSMOID_[A-Za-z0-9_]+)/gs) {
234          $symbols{$name} = 1;
235      };
236  };
237  close(OIDS_H2);
238  
239  foreach $name (keys %symbols) {
240    print "_$name\n";
241  };
242  
243  close(OUT);
244  select(STDOUT);
245  
246  
247  close(EXPORTS);
248  close(REPORT);
249  print "$written API functions generated; $ignored ignored (see $REPORT)\n";