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