generate_interface.pl 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. #!/usr/bin/perl -w
  2. #
  3. # Copyright (c) 2007, Cameron Rich
  4. #
  5. # All rights reserved.
  6. #
  7. # Redistribution and use in source and binary forms, with or without
  8. # modification, are permitted provided that the following conditions are met:
  9. #
  10. # * Redistributions of source code must retain the above copyright notice,
  11. # this list of conditions and the following disclaimer.
  12. # * Redistributions in binary form must reproduce the above copyright
  13. # notice, this list of conditions and the following disclaimer in the
  14. # documentation and/or other materials provided with the distribution.
  15. # * Neither the name of the axTLS project nor the names of its
  16. # contributors may be used to endorse or promote products derived
  17. # from this software without specific prior written permission.
  18. #
  19. # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  20. # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  21. # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  22. # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  23. # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  24. # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
  25. # TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  26. # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  27. # OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  28. # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  29. # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30. #
  31. #===============================================================
  32. # This application transforms ssl.h into interfaces that can be used by
  33. # other language bindings. It is "SWIG"-like in nature in that various
  34. # files are generated based on the axTLS API.
  35. #
  36. # The file produced is axInterface.? (depending on the file extension).
  37. #
  38. #===============================================================
  39. use strict;
  40. my $CSHARP = 0;
  41. my $VBNET = 1;
  42. my $binding;
  43. my $skip = 0;
  44. my $signature_ret_type;
  45. # Transforms function signature into an Interface format
  46. sub transformSignature
  47. {
  48. my $item;
  49. my ($line) = @_;
  50. foreach $item ($line)
  51. {
  52. # our very basic preprocessor
  53. if ($binding == $CSHARP)
  54. {
  55. $line =~ s/STDCALL //;
  56. $line =~ s/EXP_FUNC/ [DllImport ("axtls")]\n public static extern/;
  57. $line =~ s/uint32_t/uint/g;
  58. $line =~ s/uint8_t \*\*/ref IntPtr /g;
  59. $line =~ s/const uint8_t \* /IntPtr /g;
  60. $line =~ s/const uint8_t \*/byte[] /g; # note: subtle diff
  61. $line =~ s/uint8_t \* ?/byte[] /g;
  62. $line =~ s/uint8_t ?/byte /g;
  63. $line =~ s/const char \* ?/string /g;
  64. $line =~ s/const SSL_CTX \* ?/IntPtr /g;
  65. $line =~ s/SSL_CTX \* ?/IntPtr /g;
  66. $line =~ s/SSLObjLoader \* ?/IntPtr /g;
  67. $line =~ s/const SSL \* ?/IntPtr /g;
  68. $line =~ s/SSL \* ?/IntPtr /g;
  69. $line =~ s/\(void\)/()/g;
  70. }
  71. elsif ($binding == $VBNET)
  72. {
  73. if ($line =~ /EXP_FUNC/)
  74. {
  75. # Procedure or function?
  76. my $invariant = $line =~ /void /;
  77. my $proc = $invariant ? "Sub" : "Function";
  78. ($signature_ret_type) = $line =~ /EXP_FUNC (.*) STDCALL/;
  79. $line =~ s/EXP_FUNC .* STDCALL / <DllImport("axtls")> Public Shared $proc _\n /;
  80. $signature_ret_type =~ s/const uint8_t \*/As IntPtr/;
  81. $signature_ret_type =~ s/const char \*/As String/;
  82. $signature_ret_type =~ s/SSL_CTX \*/As IntPtr/;
  83. $signature_ret_type =~ s/SSLObjLoader \*/As IntPtr/;
  84. $signature_ret_type =~ s/SSL \*/As IntPtr/;
  85. $signature_ret_type =~ s/uint8_t/As Byte/;
  86. $signature_ret_type =~ s/int/As Integer/;
  87. $signature_ret_type =~ s/void//;
  88. $signature_ret_type .= "\n End $proc\n\n";
  89. }
  90. $line =~ s/uint32_t (\w+)/ByVal $1 As Integer/g;
  91. $line =~ s/int (\w+)/ByVal $1 As Integer/g;
  92. $line =~ s/uint8_t \*\* ?(\w+)/ByRef $1 As IntPtr/g;
  93. $line =~ s/const uint8_t \* ?(\w+)/ByVal $1() As Byte/g;
  94. $line =~ s/uint8_t \* ?(\w+)/ByVal $1() As Byte/g;
  95. $line =~ s/uint8_t ?(\w+)/ByVal $1 As Byte/g;
  96. $line =~ s/const char \* ?(\w+)/ByVal $1 As String/g;
  97. $line =~ s/const SSL_CTX \* ?(\w+)/ByVal $1 As IntPtr/g;
  98. $line =~ s/SSL_CTX \* ?(\w+)/ByVal $1 As IntPtr/g;
  99. $line =~ s/SSLObjLoader \* ?(\w+)/ByVal $1 As IntPtr/g;
  100. $line =~ s/const SSL \* ?(\w+)/ByVal $1 As IntPtr/g;
  101. $line =~ s/SSL \* ?(\w+)/ByVal $1 As IntPtr/g;
  102. $line =~ s/void \* ?(\w+)/Byval $1 As IntPtr/g;
  103. $line =~ s/\(void\)/()/g;
  104. $line =~ s/void//g;
  105. $line =~ s/;\n/ $signature_ret_type;/;
  106. }
  107. }
  108. return $line;
  109. }
  110. # Parse input file
  111. sub parseFile
  112. {
  113. my (@file) = @_;
  114. my $line;
  115. my $splitDefine = 0;
  116. my $splitFunctionDeclaration;
  117. my $vb_hack = " ";
  118. my $vb_line_hack = 0;
  119. $skip = 0;
  120. foreach $line (@file)
  121. {
  122. next if $line =~ /sl_x509_create/; # ignore for now
  123. # test for a #define
  124. if (!$skip && $line =~ m/^#define/)
  125. {
  126. $splitDefine = 1 if $line =~ m/\\$/;
  127. if ($binding == $VBNET)
  128. {
  129. $line =~ s/\|/Or/g;
  130. $line =~ s/ 0x/ &H/;
  131. }
  132. my ($name, $value) = $line =~ /#define (\w+) +([^\\]*)[\\]?\n/;
  133. if (defined $name && defined $value)
  134. {
  135. # C# constant translation
  136. if ($binding == $CSHARP)
  137. {
  138. $line = " public const int $name = $value";
  139. }
  140. # VB.NET constant translation
  141. elsif ($binding == $VBNET)
  142. {
  143. $line = " Public Const $name As Integer = $value";
  144. }
  145. }
  146. next if $line =~ /#define/; # ignore any other defines
  147. print DATA_OUT $line;
  148. # check line is not split
  149. next if $splitDefine == 1;
  150. print DATA_OUT ";" if $binding == $CSHARP;
  151. print DATA_OUT "\n";
  152. }
  153. # pick up second line of #define statement
  154. if ($splitDefine)
  155. {
  156. if ($line !~ /\\$/)
  157. {
  158. $line =~ s/$/;/ if $binding == $CSHARP; # add the ";"
  159. }
  160. $line =~ s/ ?\| ?/ Or /g
  161. if ($binding == $VBNET);
  162. # check line is not split
  163. $splitDefine = ($line =~ m/\\$/);
  164. # ignore trailing "\"
  165. $line =~ s/\\$// if $binding == $CSHARP;
  166. $line =~ s/\\$/_/ if $binding == $VBNET;
  167. print DATA_OUT $line;
  168. next;
  169. }
  170. # test for function declaration
  171. if (!$skip && $line =~ /EXP_FUNC/ && $line !~ /\/\*/)
  172. {
  173. $line = transformSignature($line);
  174. $splitFunctionDeclaration = $line !~ /;/;
  175. $line =~ s/;// if ($binding == $VBNET);
  176. $line =~ s/\n$/ _\n/ if ($binding == $VBNET) &&
  177. $splitFunctionDeclaration;
  178. print DATA_OUT $line;
  179. next;
  180. }
  181. if ($splitFunctionDeclaration)
  182. {
  183. $line = transformSignature($line);
  184. $splitFunctionDeclaration = $line !~ /;/;
  185. $line =~ s/;// if ($binding == $VBNET);
  186. $line =~ s/\n/ _\n/ if ($binding == $VBNET) &&
  187. $splitFunctionDeclaration == 1;
  188. print DATA_OUT $line;
  189. next;
  190. }
  191. }
  192. }
  193. #===============================================================
  194. # Determine which module to build from command-line options
  195. use strict;
  196. use Getopt::Std;
  197. my $binding_prefix;
  198. my $binding_suffix;
  199. my $data_file;
  200. my @raw_data;
  201. if (not defined $ARGV[0])
  202. {
  203. goto ouch;
  204. }
  205. if ($ARGV[0] eq "-csharp")
  206. {
  207. print "Generating C# interface file\n";
  208. $binding_prefix = "csharp";
  209. $binding_suffix = "cs";
  210. $binding = $CSHARP;
  211. }
  212. elsif ($ARGV[0] eq "-vbnet")
  213. {
  214. print "Generating VB.NET interface file\n";
  215. $binding_prefix = "vbnet";
  216. $binding_suffix = "vb";
  217. $binding = $VBNET;
  218. }
  219. else
  220. {
  221. ouch:
  222. die "Usage: $0 [-csharp | -vbnet]\n";
  223. }
  224. my $interfaceFile = "$binding_prefix/axInterface.$binding_suffix";
  225. # Input file required to generate interface file.
  226. $data_file = "../ssl/ssl.h";
  227. # Open input files
  228. open(DATA_IN, $data_file) || die("Could not open file ($data_file)!");
  229. @raw_data = <DATA_IN>;
  230. # Open output file
  231. if ($binding == $CSHARP || $binding == $VBNET)
  232. {
  233. open(DATA_OUT, ">$interfaceFile") || die("Cannot Open File");
  234. }
  235. # SPEC interface file header
  236. if ($binding == $CSHARP)
  237. {
  238. # generate the C#/C interface file
  239. print DATA_OUT << "END";
  240. // The C# to C interface definition file for the axTLS project
  241. // Do not modify - this file is generated
  242. using System;
  243. using System.Runtime.InteropServices;
  244. namespace axTLS
  245. {
  246. public class axtls
  247. {
  248. END
  249. }
  250. elsif ($binding == $VBNET)
  251. {
  252. # generate the VB.NET/C interface file
  253. print DATA_OUT << "END";
  254. ' The VB.NET to C interface definition file for the axTLS project
  255. ' Do not modify - this file is generated
  256. Imports System
  257. Imports System.Runtime.InteropServices
  258. Namespace axTLSvb
  259. Public Class axtls
  260. END
  261. }
  262. parseFile(@raw_data);
  263. # finish up
  264. if ($binding == $CSHARP)
  265. {
  266. print DATA_OUT " };\n";
  267. print DATA_OUT "};\n";
  268. }
  269. elsif ($binding == $VBNET)
  270. {
  271. print DATA_OUT " End Class\nEnd Namespace\n";
  272. }
  273. close(DATA_IN);
  274. close(DATA_OUT);
  275. #===============================================================