2001-08-30 Dietmar Maurer <dietmar@ximian.com>
[mono.git] / mono / wrapper / genwrapper.pl
1 #!/usr/bin/perl
2
3 # Author:
4 #       Dietmar Maurer (dietmar@ximian.com)
5 #
6 # (C) 2001 Ximian, Inc.
7
8 use Getopt::Long;
9 init();
10
11 if ($ENV{"OSTYPE"} eq "cygwin") {
12 @includes = ("sys/types.h", "sys/stat.h", "unistd.h", "fcntl.h", "glib.h",
13              "errno.h");
14 } else {
15 @includes = ("sys/types.h", "sys/stat.h", "unistd.h", "fcntl.h", "glib.h",
16              "errno.h");
17 }
18
19 $cflags = `glib-config --cflags glib`;
20 $cflags =~ s/\n//;
21
22 $lib = "monowrapper";
23
24 create_struct ("MonoWrapperStat", "stat",
25                "uint", "st_dev",
26                "uint", "st_mode",
27                "uint", "st_nlink",
28                "uint", "st_uid",
29                "uint", "st_gid",
30                "long", "st_size",
31                "uint", "st_atime",
32                "uint", "st_mtime",
33                "uint", "st_ctime",
34                );
35
36 create_func ($lib, "", "seek", "long", 
37              "IntPtr", "fd",
38              "long", "offset",
39              "int", "whence");
40
41 create_func ($lib, "", "read", "int",
42              "IntPtr", "fd",
43              "void *", "buf",
44              "int", "count");
45
46 create_func ($lib, "", "write", "int",
47              "IntPtr", "fd",
48              "void *", "buf",
49              "int", "count");
50
51 create_func ($lib, "", "fstat", "int",
52              "IntPtr", "fd",
53              "stat *", "buf");
54
55 create_func ($lib, "", "ftruncate", "int",
56              "IntPtr", "fd",
57              "long", "length");
58
59 create_func ($lib, "", "open", "IntPtr",
60              "string", "path",
61              "int", "flags",
62              "int", "mode");
63
64 create_func ($lib, "", "close", "int",
65              "IntPtr", "fd");
66
67 map_const ("int", "%d", "SEEK_SET",
68            "int", "%d", "SEEK_CUR",
69            "int", "%d", "SEEK_END",
70
71            "int", "0x%08x", "O_RDONLY",
72            "int", "0x%08x", "O_WRONLY",
73            "int", "0x%08x", "O_RDWR",
74            "int", "0x%08x", "O_CREAT",
75            "int", "0x%08x", "O_EXCL",
76            "int", "0x%08x", "O_NOCTTY",
77            "int", "0x%08x", "O_TRUNC",
78            "int", "0x%08x", "O_SYNC",
79            "int", "0x%08x", "O_APPEND",
80
81            "int", "0x%08x", "STDIN_FILENO",
82            "int", "0x%08x", "STDOUT_FILENO",
83            "int", "0x%08x", "STDERR_FILENO",
84
85            "int", "0x%08x", "S_IFMT",
86            "int", "0x%08x", "S_IFSOCK",
87            "int", "0x%08x", "S_IFLNK",
88            "int", "0x%08x", "S_IFREG",
89            "int", "0x%08x", "S_IFBLK",
90            "int", "0x%08x", "S_IFDIR",
91            "int", "0x%08x", "S_IFCHR",
92            "int", "0x%08x", "S_IFIFO",
93            "int", "0x%08x", "S_ISUID",
94            "int", "0x%08x", "S_ISGID",
95            "int", "0x%08x", "S_ISVTX",
96            "int", "0x%08x", "S_IRWXU",
97            "int", "0x%08x", "S_IRUSR",
98            "int", "0x%08x", "S_IWUSR",
99            "int", "0x%08x", "S_IXUSR",
100            "int", "0x%08x", "S_IRWXG",
101            "int", "0x%08x", "S_IRGRP",
102            "int", "0x%08x", "S_IWGRP",
103            "int", "0x%08x", "S_IXGRP",
104            "int", "0x%08x", "S_IRWXO",
105            "int", "0x%08x", "S_IROTH",
106            "int", "0x%08x", "S_IWOTH",
107            "int", "0x%08x", "S_IXOTH",
108
109            "int", "%d", "EPERM",
110            "int", "%d", "ENOENT",
111            "int", "%d", "ESRCH",
112            "int", "%d", "EINTR",
113            "int", "%d", "EIO",
114            "int", "%d", "ENXIO",
115            "int", "%d", "E2BIG",
116            "int", "%d", "ENOEXEC",
117            "int", "%d", "EBADF",
118            "int", "%d", "ECHILD",
119            "int", "%d", "EAGAIN",
120            "int", "%d", "ENOMEM",
121            "int", "%d", "EACCES",
122            "int", "%d", "EFAULT",
123            "int", "%d", "ENOTBLK",
124            "int", "%d", "EBUSY",
125            "int", "%d", "EEXIST",
126            "int", "%d", "EXDEV",
127            "int", "%d", "ENODEV",
128            "int", "%d", "EISDIR",
129            "int", "%d", "EINVAL",
130            "int", "%d", "ENFILE",
131            "int", "%d", "EMFILE",
132            "int", "%d", "ENOTTY",
133            "int", "%d", "ETXTBSY",
134            "int", "%d", "EFBIG",
135            "int", "%d", "ENOSPC",
136            "int", "%d", "ESPIPE",
137            "int", "%d", "EROFS",
138            "int", "%d", "EMLINK",
139            "int", "%d", "EPIPE",
140            "int", "%d", "EDOM",
141            "int", "%d", "ERANGE",
142            "int", "%d", "EDEADLK",
143            "int", "%d", "ENAMETOOLONG",
144            "int", "%d", "ENOLCK",
145            "int", "%d", "ENOSYS",
146            "int", "%d", "ENOTEMPTY",
147            "int", "%d", "ELOOP",
148            "int", "%d", "EWOULDBLOCK",
149            "int", "%d", "ENOMSG",
150            "int", "%d", "EIDRM",
151            "int", "%d", "ECHRNG",
152            "int", "%d", "EL2NSYNC",
153            "int", "%d", "EL3HLT",
154            "int", "%d", "EL3RST",
155            "int", "%d", "ELNRNG",
156            "int", "%d", "EUNATCH",
157            "int", "%d", "ENOCSI",
158            "int", "%d", "EL2HLT",
159            "int", "%d", "EBADE",
160            "int", "%d", "EBADR",
161            "int", "%d", "EXFULL",
162            "int", "%d", "ENOANO",
163            "int", "%d", "EBADRQC",
164            "int", "%d", "EBADSLT",
165            "int", "%d", "EDEADLOCK",
166            "int", "%d", "EBFONT",
167            "int", "%d", "ENOSTR",
168            "int", "%d", "ENODATA",
169            "int", "%d", "ETIME",
170            "int", "%d", "ENOSR",
171            "int", "%d", "ENONET",
172            "int", "%d", "ENOPKG",
173            "int", "%d", "EREMOTE",
174            "int", "%d", "ENOLINK",
175            "int", "%d", "EADV",
176            "int", "%d", "ESRMNT",
177            "int", "%d", "ECOMM",
178            "int", "%d", "EPROTO",
179            "int", "%d", "EMULTIHOP",
180            "int", "%d", "EDOTDOT",
181            "int", "%d", "EBADMSG",
182            "int", "%d", "ENOTUNIQ",
183            "int", "%d", "EBADFD",
184            "int", "%d", "EREMCHG",
185            "int", "%d", "ELIBACC",
186            "int", "%d", "ELIBBAD",
187            "int", "%d", "ELIBSCN",
188            "int", "%d", "ELIBMAX",
189            "int", "%d", "ELIBEXEC",
190            "int", "%d", "EUSERS",
191            "int", "%d", "ENOTSOCK",
192            "int", "%d", "EDESTADDRREQ",
193            "int", "%d", "EMSGSIZE",
194            "int", "%d", "EPROTOTYPE",
195            "int", "%d", "ENOPROTOOPT",
196            "int", "%d", "EPROTONOSUPPORT",
197            "int", "%d", "ESOCKTNOSUPPORT",
198            "int", "%d", "EOPNOTSUPP",
199            "int", "%d", "EPFNOSUPPORT",
200            "int", "%d", "EAFNOSUPPORT",
201            "int", "%d", "EADDRINUSE",
202            "int", "%d", "EADDRNOTAVAIL",
203            "int", "%d", "ENETDOWN",
204            "int", "%d", "ENETUNREACH",
205            "int", "%d", "ENETRESET",
206            "int", "%d", "ECONNABORTED",
207            "int", "%d", "ECONNRESET",
208            "int", "%d", "ENOBUFS",
209            "int", "%d", "EISCONN",
210            "int", "%d", "ENOTCONN",
211            "int", "%d", "ESHUTDOWN",
212            "int", "%d", "ETOOMANYREFS",
213            "int", "%d", "ETIMEDOUT",
214            "int", "%d", "ECONNREFUSED",
215            "int", "%d", "EHOSTDOWN",
216            "int", "%d", "EHOSTUNREACH",
217            "int", "%d", "EALREADY",
218            "int", "%d", "EINPROGRESS",
219            "int", "%d", "ESTALE",
220            "int", "%d", "EDQUOT",
221            "int", "%d", "ENOMEDIUM",
222            );
223
224 sub init {
225
226     $csmode = 0;
227     $defmode = 0;
228
229     GetOptions ("c|csharp" => \$csmode,
230                 "d|defmode" => \$defmode) or die "cant parse options";
231
232     $CC = $env{"CC"};
233
234     if (!$CC) {
235         $CC = "gcc";
236     }
237
238
239     %tmap = ("void" => "void",
240              "IntPtr" => "int",
241              "sbyte" => "gint8",
242              "byte" => "guint8",
243              "short" => "gint16",
244              "ushort" => "guint16",
245              "int" => "gint32",
246              "uint" => "guint32",
247              "long" => "gint64",
248              "ulong" => "guint64",
249              "string" => "const char *",
250              );
251 }
252
253 sub t {
254     my ($name) = @_;
255     my ($rname) = $name;
256
257     if ($name =~ m/(.*)\*\s*$/) {
258         $rname = $1;
259         $rname =~ s/\s+$//; # remove trailing spaces
260         $rval = $tmap{$rname} || die "unable to map type \"$name\"";
261         return "$rval*";
262     }
263
264     $rval = $tmap{$name} || die "unable to map type \"$name\"";
265
266 }
267
268 sub create_func {
269     my (@func) = @_;
270     my ($i) = 0;
271     my ($res) = "";
272
273     if ($func[1] eq "") {
274         $func[1] = "mono_wrapper_$func[2]";
275     }
276
277     if ($defmode) {
278         $dlldef .= "\t$func[1]\n";
279     }
280
281     if ($csmode) {
282
283         $res = "\t[DllImport(\"$func[0]\", EntryPoint=\"$func[1]\", CharSet=CharSet.Ansi)]\n";
284         $res .= "\tpublic unsafe static extern $func[3] $func[2] (";
285         $i +=4;
286         while ($i <= $#func) {
287             if ($i>4) {
288                 $res .= ", ";
289             }
290             $res .= "$func[$i] $func[$i+1]";
291             
292             $i+=2;
293         }
294         $res .= ");\n\n";
295
296         $res_func .= $res;
297
298     } else  {
299         
300         $res = t($func[3]) . "\n$func[1] (";
301         
302         $i +=4;
303         while ($i <= $#func) {
304             if ($i>4) {
305                 $res .= ", ";
306             }
307             $res .= t($func[$i]) . " $func[$i+1]";
308             
309             $i+=2;
310         }
311         $res .= ");\n\n";
312
313         $res_func .= $res;
314     }
315 }
316
317 sub create_struct {
318     my (@str) = @_;
319     my ($i) = 0;
320     my ($res) = "";
321
322     if ($csmode) {
323         $res = "public struct $str[1] {\n";
324         $i +=2;
325         while ($i <= $#str) {
326             $res .= "\tpublic $str[$i] $str[$i+1];\n";
327             $i+=2;
328         }
329         $res .= "};\n\n";
330     } else {
331         $res = "typedef struct {\n";
332         $i += 2;
333         while ($i <= $#str) {
334             $res .= "\t" . t($str[$i]) . " $str[$i+1];\n";
335             $i+=2;
336         }
337         $res .= "} $str[0];\n\n";
338     }
339
340     $tmap{"$str[1]"} = "$str[0]";
341
342     $res_struct .= $res;
343 }
344
345 sub map_const {
346     my (@co) = @_;
347     my ($res) = "";
348     my ($l);
349     my ($space);
350
351     if (!$csmode) {
352         return;
353     }
354
355     my ($tfn) = "/tmp/etypes$$.c";
356
357     open (TFN, ">$tfn") || die (0);
358
359     for ($i = 0; $i <= $#includes; $i++) {
360         print TFN "#include \"$includes[$i]\"\n";
361     }
362     
363     print TFN "\nint main () {\n"; 
364     for ($i = 0; $i <= $#co; $i+=3) {
365
366         $l = 20 - length($co[$i+2]);
367
368         $space = "";
369         for (my ($j) = 0; $j < $l; $j++) {
370             $space = $space . " ";
371         }
372
373         print TFN "printf (\"\\tpublic const %s %s $space= $co[$i+1];\\n\",".
374             " \"$co[$i]\", \"$co[$i+2]\", $co[$i+2]);\n";
375
376     }
377     print TFN "exit (-1);\n";
378     print TFN "}\n";
379
380     close (TFN);
381
382     system ("$CC $cflags $tfn -o conftest.exe") == 0
383         or die "calling c compiler failed";
384
385     system ("rm $tfn");
386
387     $res = `./conftest.exe`;
388
389     if (!$res) {
390         die "calling a.out failde";
391     }
392
393     $res_const = $res_const . $res;
394
395     system ("rm ./conftest.exe");       
396 }
397
398 sub etypes_end {
399
400     @ae = split (/\./, $__class);
401
402     print $res_struct;
403
404     print "public class $ae[$#ae] {\n\n";
405
406     if ($res_const) {
407         print "$res_const\n\n";
408     }
409
410     print "$res_func";
411
412     printf "} // class $ae[$#ae]\n\n";
413
414     for ($i = $#ae - 1; $i >= 0; $i--) {
415         print "} // namescape $ae[$i]\n";
416     }
417
418 }
419
420 print "/*\n * Generated automatically: do not edit this file.\n */\n\n";
421
422
423 if ($csmode) {
424
425     print "using System;\n";
426     print "using System.Runtime.InteropServices;\n\n";
427
428     print "namespace System.Private {\n\n";
429
430     print $res_struct;
431
432     print "public class Wrapper {\n\n";
433
434     if ($res_const) {
435         print "$res_const\n\n";
436     }
437
438     print "$res_func";
439
440     print "}\n";
441
442     print "}\n";
443     
444 } elsif ($defmode) {
445         
446     print "LIBRARY libmonowrapper\n";
447     print "EXPORTS\n";
448     print "\tDllMain\n";
449     print $dlldef;
450
451 } else {
452
453     print "#ifndef _MONO_WRAPPER_H_\n#define _MONO_WRAPPER_H_ 1\n\n";
454
455     for ($i = 0; $i <= $#includes; $i++) {
456         print "#include <$includes[$i]>\n";
457     }
458
459     print "\n";
460
461     print $res_struct;
462
463     print $res_func;
464
465     print "#endif\n";
466 }