* xpidl2cs.pl: whitespace clean up
[mono.git] / mcs / class / Mono.WebBrowser / tools / xpidl2cs / xpidl2cs.pl
1 #!/usr/bin/perl
2 #
3 # xpidl2cs.pl : Generates C# interfaces from idl
4 #
5 # Author: Andreia Gaita <shana.ufie@gmail.com>
6 #
7 # Copyright (c) 2007 Novell, Inc.
8 #
9 # This program is free software; you can redistribute it and/or
10 # modify it under the terms of version 2 of the GNU General Public
11 # License as published by the Free Software Foundation.
12 #
13 # This program is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 # General Public License for more details.
17 #
18 # You should have received a copy of the GNU General Public
19 # License along with this program; if not, write to the
20 # Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 # Boston, MA 02111-1307, USA.
22 ##############################################################
23
24 die "Usage: xpidl2cs.pl file.idl [/path/to/idl/]" if scalar(@ARGV) < 1;
25
26 my $file = shift;
27 my $path = shift if scalar(@ARGV) > 0;
28 my $nosig = shift if scalar(@ARGV) > 0;
29 $nosig = "" if !$nosig;
30
31 open FILE, '<', $path.$file or die "Can't open file $path$file";
32
33 my %interface = (
34                  properties => (), 
35                  items => "", 
36                  uuid => "", 
37                  class => "", 
38                  parent => ""
39                  );
40 my %properties;
41 my %methods = {
42         type => "",
43         params => ()
44 };
45
46 my %types;
47 $types{"short"} = {name => "short", out => "out", marshal => ""};
48 $types{"PRUint8"} = {name => "char", out => "out", marshal => ""};
49 $types{"PRInt8"} = {name => "char", out => "out", marshal => ""};
50 $types{"unsigned,short"} = {name => "ushort", out => "out", marshal => ""};
51 $types{"PRUint16"} = {name => "ushort", out => "out", marshal => ""};
52 $types{"PRInt16"} = {name => "short", out => "out", marshal => ""};
53 $types{"int"} = {name => "int", out => "out", marshal => ""};
54 $types{"nsresult"} = {name => "int", out => "out", marshal => ""};
55 $types{"unsigned,int"} = {name => "uint", out => "out", marshal => ""};
56 $types{"PRUint32"} = {name => "UInt32", out => "out", marshal => ""};
57 $types{"PRInt32"} = {name => "Int32", out => "out", marshal => ""};
58 $types{"PRInt64"} = {name => "long", out => "out", marshal => ""};
59 $types{"long"} = {name => "int", out => "out", marshal => ""};
60 $types{"size_t"} = {name => "int", out => "out", marshal => ""};
61 $types{"unsigned,long"} = {name => "uint", out => "out", marshal => ""};
62 $types{"float"} = {name => "float", out => "out", marshal => ""};
63 $types{"boolean"} = {name => "bool", out => "out", marshal => ""};
64 $types{"PRBool"} = {name => "bool", out => "out", marshal => ""};
65 $types{"void"} = {name => "", out => "", marshal => ""};
66 $types{"octet"} = {name => "byte", out => "out", marshal => ""};
67 $types{"octet[]"} = {name => "IntPtr", out => "out", marshal => " "};
68 $types{"byte"} = {name => "byte", out => "out", marshal => ""};
69 $types{"DOMString"} = {name => "/*DOMString*/ HandleRef", out => "", marshal => ""};
70 $types{"AUTF8String"} = {name => "/*AUTF8String*/ HandleRef", out => "", marshal => ""};
71 $types{"ACString"} = {name => "/*ACString*/ HandleRef", out => "", marshal => ""};
72 $types{"AString"} = {name => "/*AString*/ HandleRef", out => "", marshal => ""};
73 $types{"wstring"} = {name => "string", out => "", marshal => "MarshalAs(UnmanagedType.LPWStr)"};
74 $types{"nsCIDRef"} = {name => "Guid", out => "out", marshal => "MarshalAs (UnmanagedType.LPStruct)"};
75 $types{"nsIIDRef"} = {name => "Guid", out => "out", marshal => "MarshalAs (UnmanagedType.LPStruct)"};
76 $types{"Guid"} = {name => "Guid", out => "out", marshal => "MarshalAs (UnmanagedType.LPStruct)"};
77 $types{"nsCID"} = {name => "Guid", out => "out", marshal => "MarshalAs (UnmanagedType.LPStruct)"};
78 $types{"nsCIDPtr"} = {name => "Guid", out => "out", marshal => "MarshalAs (UnmanagedType.LPStruct)"};
79 $types{"string"} = {name => "string", out => "ref", marshal => "MarshalAs (UnmanagedType.LPStr)"};
80 $types{"refstring"} = {name => "IntPtr", out => "ref", marshal => ""};
81 $types{"charPtr"} = {name => "StringBuilder", out => "", marshal => ""};
82 $types{"voidPtr"} = {name => "IntPtr", out => "", marshal => ""};
83 $types{"nsISupports"} = {name => "IntPtr", out => "out", marshal =>"MarshalAs (UnmanagedType.Interface)"};
84 $types{"DOMTimeStamp"} = {name => "int", out => "out", marshal => ""};
85 $types{"nsWriteSegmentFun"} = {name => "nsIWriteSegmentFunDelegate", out => "", marshal => ""};
86 $types{"nsReadSegmentFun"} = {name => "nsIReadSegmentFunDelegate", out => "", marshal => ""};
87 $types{"nsTimerCallbackFunc"} = {name => "nsITimerCallbackDelegate", out => "", marshal => ""};
88 $types{"nsLoadFlags"} = {name => "ulong", out => "out", marshal => ""};
89 $types{"nsQIResult"} = {name => "IntPtr", out => "out", marshal => ""};
90 $types{"nsIIDPtr[]"} = {name => "IntPtr", out => "out", marshal => ""};
91 $types{"PRFileDescStar"} = {name => "IntPtr", out => "out", marshal => ""};
92 $types{"PRLibraryStar"} = {name => "IntPtr", out => "out", marshal => ""};
93 $types{"FILE"} = {name => "IntPtr", out => "out", marshal => ""};
94 $types{"nsIPresShell"} = {name => "/*nsIPresShell*/ IntPtr", out => "out", marshal => ""};
95 $types{"nsIDocument"} = {name => "/*nsIDocument*/ IntPtr", out => "out", marshal => ""};
96 $types{"nsIFrame"} = {name => "/*nsIFrame*/ IntPtr", out => "out", marshal => ""};
97 $types{"nsObjectFrame"} = {name => "/*nsObjectFrame*/ IntPtr", out => "out", marshal => ""};
98 $types{"nsIContent"} = {name => "/*nsIContent*/ IntPtr", out => "out", marshal => ""};
99 $types{"others"} = {name => "", out => "out", marshal => "MarshalAs (UnmanagedType.Interface)"};
100
101 my %returnvalues;
102 $returnvalues{"short"} = {value => "0"};
103 $returnvalues{"ushort"} = {value => "0"};
104 $returnvalues{"int"} = {value => "0"};
105 $returnvalues{"uint"} = {value => "0"};
106 $returnvalues{"UInt32"} = {value => "0"};
107 $returnvalues{"Int32"} = {value => "0"};
108 $returnvalues{"long"} = {value => "0"};
109 $returnvalues{"ulong"} = {value => "0"};
110 $returnvalues{"IntPtr"} = {value => "0"};
111 $returnvalues{"float"} = {value => "0"};
112 $returnvalues{"byte"} = {value => "0"};
113 $returnvalues{"IntPtr"} = {value => "IntPtr.Zero"};
114 $returnvalues{"string"} = {value => "String.Empty"};
115 $returnvalues{"bool"} = {value => "false"};
116 $returnvalues{"/*DOMString*/ HandleRef"} = {value => "null"};
117 $returnvalues{"/*AUTF8String*/ HandleRef"} = {value => "null"};
118 $returnvalues{"ACString*/ HandleRef"} = {value => "null"};
119 $returnvalues{"/*AString*/ HandleRef"} = {value => "null"};
120 $returnvalues{""} = {value => ""};
121 $returnvalues{"others"} = {value => "null"};
122
123 my %names;
124 $names{"event"} = {name => "_event"};
125 $names{"lock"} = {name => "_lock"};
126
127 my %dependents;
128    
129 my $class_implementation;
130
131 sub trim{
132 #print "trim\n";
133     $_[0]=~s/^\s+//;
134     $_[0]=~s/\s+$//;
135     return;
136 }
137
138 sub parse_parent {
139 #print "parse_parent\n";
140     my $x = shift;
141
142         print "Parsing parent $x\n";
143     `perl xpidl2cs.pl $x.idl $path $nosig`;
144
145     open my $f, '<', "$x.cs";
146     my $start = 0;
147     my $out;
148     while (my $line = <$f>) {
149                 chop $line;
150                 if (!$start) {
151                         if ($line =~ /#region/) {
152                                 $start = 1;
153                                 $out .= $line . "\n";
154                         }
155                 }
156                 elsif ($line =~ /\}/) {
157             last;
158                 }
159                 else {
160                         $out .= $line . "\n";
161                 }
162     }
163
164     return $out;
165 }
166
167 sub has_setter {
168 #print "has_setter\n";
169     my $x = shift;
170     return !$properties{$x}->{"setter"};
171 }
172
173 sub get_name {
174 #print "get_name\n";
175     my $x = shift;
176
177     if (exists $names{$x}) {
178                 return $names{$x}->{"name"};
179     }
180     return $x;
181 }
182
183 sub get_type {
184 #print "get_type\n";
185     my $x = shift;
186     my $out = shift;
187     my $arr = shift;
188
189 #    print "arr = $arr ; out = $out ; name = $x\n";
190
191     if ($out) {
192                 if ($arr && exists $types{"$out$x\[\]"}) {
193                         return $types{"$out$x\[\]"}->{"name"};
194                 } elsif ($arr && exists $types{"$out$x"}) {
195                         return $types{"$out$x"}->{"name"}."[]";
196                 } elsif (exists $types{"$out$x"}) {
197                         return $types{"$out$x"}->{"name"};
198                 }
199     }
200
201     if (exists $types{$x} || ($arr && exists $types{"$x\[\]"})) {
202                 if ($arr && exists $types{"$x\[\]"}) {
203                         return $types{"$x\[\]"}->{"name"};
204                 } elsif ($arr) {
205                         return $types{$x}->{"name"}."[]";
206                 } else {
207                         return $types{$x}->{"name"};
208                 }
209     }
210     return $x;
211 }
212
213 sub get_out {
214 #print "get_out\n";
215     my $x = shift;
216     if (exists $types{$x}) {
217                 return $types{$x}->{"out"};
218     }
219     return $types{"others"}->{"out"};
220 }
221
222 sub get_marshal {
223 #print "get_marshal\n";
224     my $x = shift;
225     my $out = shift;
226     my $arr = shift;
227
228     if ($out) {
229                 if ($arr && exists $types{"$out$x\[\]"}) {
230                         return $types{"$out$x\[\]"}->{"marshal"};
231                 } elsif (exists $types{"$out$x"}) {
232                         return $types{"$out$x"}->{"marshal"};
233                 }
234     }
235
236     if (exists $types{$x} || ($arr && exists $types{"$x\[\]"})) {
237                 if ($arr && exists $types{"$x\[\]"}) {
238                         return $types{"$x\[\]"}->{"marshal"};
239                 } else {
240                         return $types{$x}->{"marshal"};
241                 }
242     }
243
244     return $types{"others"}->{"marshal"};
245 }
246
247 sub get_return_value {
248 #print "get_return_value\n";
249     my $x = shift;
250     if (exists $returnvalues{$x}) {
251                 return $returnvalues{$x}->{"value"};
252     }
253     return $returnvalues{"others"}->{"value"};
254 }
255
256                 
257 sub is_property {
258 #print "is_property\n";
259     my $x = shift;
260     return (exists $properties{$x});
261 }
262
263 sub add_external {
264 #print "add_external\n";
265     my $x = shift;
266     if ($x !~ /nsISupports/ && !exists $types{$x} && !exists $dependents{$x}) {
267                 $dependents{$x} = $x;
268     }
269 #    print "add_external $x\n";
270 }
271
272 sub get_params {
273 #print "get_params\n";
274     my $x = shift;
275     my %list;
276 #print $methods{$x}->{"params"}."\n";
277     my @params = split /,/, $methods{$x}->{"params"};
278         my $lastoutparam = "";
279         my @ret = ();
280         
281 #print "params:@params:\n";
282     for my $param (@params) {
283                 my $marshal;
284                 my $name;
285                 my $type;
286                 my $out;
287                 my $isout;
288
289
290 #       print "param:$param:\n";
291                 my @p = split (" ", $param);
292 #       print "@p\n";
293 # need to backtrack to a previous parameter defined by iid_is(name) and 
294 # replace the type of this one with that. who the $%#@ came up with this idea? le sigh.
295
296                 if (@p[0] =~ m/iid_is/) {
297                     shift @p;
298                     $name = &get_name (@p[0]);
299                     $name =~ s/ //;
300                     $type = $list{$name}->{"type"};
301                 $marshal = $list{$name}->{"marshal"};
302                     $marshal = " " if !$marshal;
303                     $name = "";
304                     until (scalar(@p) == 3) {
305                                 shift @p;
306                     }
307                 }
308         
309                 if (@p[0] =~ m/array/ || @p[1] =~ m/array/) {
310                     until (scalar(@p) == 3) {
311                                 shift @p;
312                     }
313                 $isout = 1 if (@p[0] =~ m/out/);
314                     shift @p;
315                     $marshal = &get_marshal (@p[0], "", 1);
316                 $type = &get_type(@p[0], "", 1);
317                 }
318
319                 shift @p unless @p[0] =~ /(in|out)/;
320                 $isout = 1 if (@p[0] =~ m/out/);
321                 shift @p unless scalar(@p) <= 2;
322
323         # if an out parameter is of type nsQIResult, that means
324         # it will return a pointer to an interface (that can be anything). 
325         # That means we want to return an IntPtr, and later cast it to
326         # the proper type, so reset type and marshalling
327                 if ($isout && @p[0] =~ /nsQIResult/) {
328                     $marshal = "";
329                 $type = "";
330                 }
331
332                 if (!$type) {
333                 $type = join ",", @p[0..@p-2];
334                     $type=~s/\[.*\],//;
335                     until (scalar(@p) == 1) {
336                                 shift @p;
337                         }
338
339                     $marshal = &get_marshal ($type);
340                 $marshal = " " if !$marshal;
341                     $type = &get_type ($type);
342                     $name = &get_name (@p[0]);
343                 }
344 #print "marshal:$marshal\ttype:$type\tname:$name\n";
345                 $out = &get_out($type) if $isout;
346
347                 $type = &get_type (@p[0]) unless $type;
348                 shift @p unless scalar(@p) == 1;
349                 $marshal = &get_marshal ($type) unless $marshal;
350                 $name = &get_name (@p[0]) unless $name;
351
352 #print "marshal:$marshal\ttype:$type\tname:$name\n";
353
354                 $list{$name} = {
355                     name => $name,
356                     type => $type,
357                     marshal => $marshal,
358                 out => $out,
359                         isout => $isout
360                 };
361
362                 &add_external ($type);
363
364                 $marshal = "" if $marshal eq " ";
365
366 #               my $tmp = "\n\t\t\t\t";
367                 my $tmp = "";
368                 $tmp .= "[$marshal] " if $marshal;
369                 $tmp .= "$out $type $name";
370                 push (@ret, $tmp);
371                 $lastoutparam = $name if $isout;
372 #print "tmp:$tmp\n";
373     }
374
375 #print "$methods{$x}->{\"type\"}\n";
376 #print "nosig:$nosig;x:$x;type:" . &get_type ($methods{$x}->{"type"}) . ";\n";
377         if (!$nosig && $x !~ /void/ && &get_type ($methods{$x}->{"type"}) ne "") {
378                 $type = $methods{$x}->{"type"};
379                 $type =~ s/\[.*\],//;
380                 $marshal = &get_marshal ($type);
381
382                 my $tmp = "";
383                 $tmp = "[$marshal] " if $marshal;
384                 $tmp .= &get_out($type);
385                 $tmp .= " " . &get_type ($type);
386                 $tmp .= " ret";
387 #print "tmp 2:$tmp\n";
388                 push (@ret, $tmp);
389                 
390                 &add_external ($type);
391     }
392
393         if ($nosig && &get_type ($methods{$x}->{"type"}) eq "" && $lastoutparam) {
394                 $methods{$x}->{"type"} = $list{$lastoutparam}->{"type"};
395                 pop (@ret);
396         }
397 #print "@ret\n";
398         
399         return join (",\n\t\t\t\t", @ret);
400 }
401
402 sub parse_file {
403 #print "parse_file\n";
404     my $method = 0;
405     my $mname = '';
406     my $mtype = '';
407     my $mparams = '';
408     my $start = 0;
409         my $comment = 0;
410
411     while (my $line = <FILE>) {
412                 chop $line;
413
414                 next if !$start && $line !~ /uuid\(/;
415                 $start = 1;
416                 last if $start && $line =~ /\};/;
417
418                 trim ($line);
419
420                 if (index($line, "/*") > -1) {
421                         $comment = 1;
422                         next;
423                 }
424                 if ($comment && index($line, "*/") > -1) {
425                         $comment = 0;
426                         next;
427                 }
428
429                 next if $comment;
430
431                 if (index($line, "*") == -1 && index ($line, "//") == -1 && index ($line, "#include") == -1) {
432
433                         $line =~ s/\[noscript\] //;
434                 
435                         if (index ($line, "uuid(") != -1) {
436                                 my $uuid = $line;
437                                 $uuid =~ s/\[.*uuid\((.*)\)\]/\1/;
438                                 $interface->{"uuid"} = $uuid;
439                         }
440
441                         elsif (index($line, "interface") != -1) {
442                                 my $class = $line;
443                                 $class =~ s/interface ([^\:|\s]+)\s*:\s*(.*)/\1/;
444 #               print "\t\tclass:$class\n";
445                                 my $parent = $line;
446                                 $parent =~ s/([^\:]+):\s*(.*)[\s|\{]/\2/;
447 #               print "\t\tparent:$parent\n";
448                                 $interface->{"class"} = $class;
449                                 $interface->{"parent"} = $parent;
450                         }
451                         elsif (index ($line, "const") != -1 && index ($line, "[") == -1) {
452                                 next;
453                         }
454                         elsif (index ($line, "attribute") != -1) {
455                                 my $att = substr($line, index($line, "attribute") + 10);
456
457                                 my @atts = split / /, $att;
458
459                                 my $name = pop @atts;
460                                 $name =~ s/;//;
461 #           print $name . "\n";
462                                 my @nospaces = grep /[^ ]/, @atts;
463                                 my $type = join ",", @nospaces;
464
465                                 my $setter = 0;
466                                 if (index ($line, "readonly") != -1) {
467                                         $setter = 1;
468                                 }
469 #            print $type . "\n";
470                                 $properties{$name} = {type => $type, setter => $setter};
471                                 $interface->{"items"} .= $name . ",";
472                         }
473                         elsif ($line !~ m/[{|}]/ && $line =~ m/./) {
474 #               print $line . "\n";
475                                 if (!$method) {
476                                         $method = 1;
477                                         my  $m = substr($line, 0, index($line, "("));
478                                         my @atts = split / /, $m;
479
480 #                   print "$m\n";
481                                         $mname = pop @atts;
482 #                   print "name=$mname\n";
483                                         my @nospaces = grep /[^ ]/, @atts;
484                                         $mtype = join ",", @nospaces;
485                                         $mtype =~ s/\[.*\],//;
486 #                   print "type=$mtype\n";
487                                         $mparams .= substr($line, index($line, "(") + 1);
488                                         $mparams =~ s/;//;
489                                         $mparams =~ s/\)//;
490
491                                         @atts = split / /, $mparams;
492                                         @nospaces = grep /[^ ]/, @atts;
493                                         $mparams = join " ", @nospaces;
494 #                   print "params=>$mparams\n";
495                                         
496                                 }
497                                 elsif (index ($line, "raises") == -1) {
498                                         $mparams .= $line;
499                                         $mparams =~ s/;//;
500                                         $mparams =~ s/\)//;
501                                         my @atts = split / /, $mparams;
502                                         my @nospaces = grep /[^ ]/, @atts;
503                                         $mparams = join " ", @nospaces;
504 #                   print "params=>$mparams\n";
505                                 }
506                                 if (index ($line, ";") != -1) {
507                                         $method = 0;
508                                         $mparams =~ s/\[([^\]]+),([^\]]+),([^\]]+)\]/\1 \2 \3/;
509                                         $mparams =~ s/\[([^\]]+),([^\]]+)\]/\1 \2/;
510                                         $mparams =~ s/\(/ /;
511                                         $mparams =~ s/\)//;
512                                         $mparams =~ s/retval//;
513
514                                         $methods{$mname} = {type => $mtype, params => $mparams};
515                                         $interface->{"items"} .= $mname . ",";
516 #                   print "params=>$mparams\n";
517                                         $mname = '';
518                                         $mtype = '';
519                                         $mparams = '';
520                                 }
521                         }       
522                 }
523     }
524 }
525
526
527 sub output {
528 #print "output\n";
529     my $name = $interface->{"class"};
530     print "$name.cs\n";
531     open X, ">$name.cs";
532     print X "// THIS FILE AUTOMATICALLY GENERATED BY xpidl2cs.pl\n";
533     print X "// EDITING IS PROBABLY UNWISE\n";
534     print X "// Permission is hereby granted, free of charge, to any person obtaining\n";
535     print X "// a copy of this software and associated documentation files (the\n";
536     print X "// \"Software\"), to deal in the Software without restriction, including\n";
537     print X "// without limitation the rights to use, copy, modify, merge, publish,\n";
538     print X "// distribute, sublicense, and/or sell copies of the Software, and to\n";
539     print X "// permit persons to whom the Software is furnished to do so, subject to\n";
540     print X "// the following conditions:\n";
541     print X "// \n";
542     print X "// The above copyright notice and this permission notice shall be\n";
543     print X "// included in all copies or substantial portions of the Software.\n";
544     print X "// \n";
545     print X "// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n";
546     print X "// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n";
547     print X "// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n";
548     print X "// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\n";
549     print X "// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\n";
550     print X "// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\n";
551     print X "// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n";
552     print X "//\n";
553     print X "// Copyright (c) 2007, 2008 Novell, Inc.\n";
554     print X "//\n";
555     print X "// Authors:\n";
556     print X "// Andreia Gaita (avidigal\@novell.com)\n";
557     print X "//\n";
558     print X "\n";
559     print X "using System;\n";
560     print X "using System.Runtime.InteropServices;\n";
561     print X "using System.Runtime.CompilerServices;\n";
562     print X "using System.Text;\n";
563     print X "\n";
564     print X "namespace Mono.Mozilla {\n";
565     print X "\n";
566
567     my $uuid = $interface->{"uuid"};
568     my $parent = $interface->{"parent"};
569     print X "\t[Guid (\"$uuid\")]\n";
570     print X "\t[InterfaceType (ComInterfaceType.InterfaceIsIUnknown)]\n";
571     print X "\t[ComImport ()]\n";
572     print X "\tinternal interface $name";
573     print X " : $parent" if $parent !~ /nsISupports/;
574     print X " {\n";
575
576     if ($parent !~ /nsISupports/) {
577                 print X &parse_parent ($parent);
578     }
579     print X "\n";
580     print X "#region $name\n";
581
582     my @items = split ",", $interface->{"items"};
583     for my $item (@items) {
584         
585                 if (!$nosig) {
586                         print X "\t\t[PreserveSigAttribute]\n";
587                 }
588                 print X "\t\t[MethodImpl (MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]\n";
589
590                 if (&is_property ($item)) {
591                         my $out = &get_out($properties{$item}->{"type"});
592                         my $marshal = &get_marshal($properties{$item}->{"type"}, $out);
593                         my $type = &get_type ($properties{$item}->{"type"}, $out);
594                         my $name = ucfirst ($item);
595
596                         &add_external ($properties{$item}->{"type"});
597 ## getter
598                         print X "\t\t";
599                         if ($nosig) {
600                                 print X "[return: $marshal] " if $marshal;
601                                 print X "$type get$name ();\n";
602                         } else {
603                                 print X "int get$name (";
604                                 print X "[$marshal] " if $marshal;
605                                 print X "$out $type ret);\n";
606                         }
607                         print X "\n";
608
609                         $type = &get_type ($properties{$item}->{"type"});
610                         $marshal = &get_marshal($properties{$item}->{"type"});
611
612 ## setter
613                         if (&has_setter($item)) {
614                                 if (!$nosig) {
615                                         print X "\t\t[PreserveSigAttribute]\n";
616                                 }
617                                 print X "\t\t[MethodImpl (MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]\n";
618                                 if ($nosig) {
619                                         print X "\t\tvoid";
620                                 } else {
621                                         print X "\t\tint";
622                                 }
623                                 print X " set$name (";
624                                 print X "[$marshal] " if $marshal;
625                                 print X "$type value);\n";
626                                 print X "\n";
627                         }
628
629                 } else {
630                         my $type = &get_type ($methods{$item}->{"type"});
631                         my $out = &get_out($methods{$item}->{"type"}) if $type;
632                         my $marshal = &get_marshal($methods{$item}->{"type"}, $out) if $type;
633                         $type = "void" if !$type;
634
635                         print X "\t\t";
636                         if ($nosig) {
637                                 print X "[return: $marshal] " if $marshal;
638                                 print X "$type $item (";
639                                 print X &get_params($item);
640                                 print X ");";
641                         } else {
642                                 print X "int $item (";
643                                 print X &get_params($item);
644                                 print X ");";
645                         }
646                         print X "\n\n";
647                 }
648     }
649     print X "#endregion\n";
650     print X "\t}\n";
651
652
653 # mozilla-specific helper classes to proxy objects between threads
654 # remove if you're not running this for mono.mozilla
655
656     print X "\n\n";
657     $helpername = $name;
658     $helpername =~ s/nsI/ns/;
659     print X "\tinternal class $helpername";
660     print X " {\n";
661     print X "\t\tpublic static $name GetProxy (Mono.WebBrowser.IWebBrowser control, $name obj)\n";
662     print X "\t\t{\n";
663     print X "\t\t\tobject o = Base.GetProxyForObject (control, typeof($name).GUID, obj);\n";
664     print X "\t\t\treturn o as $name;\n";
665     print X "\t\t}\n";
666     print X "\t}\n";
667
668 #end of mozilla-specific helper classes
669
670     print X "}\n";
671         
672         
673         &generate_class_implementation_example ();
674         
675         
676     close X;
677 }
678
679 sub generate_dependents {
680 #print "generate_dependents\n";
681     for my $dependent (keys %dependents) {
682                 if (! (-e "$dependent.cs") && -e "$path$dependent.idl" && $file != $dependent) {
683                         print "generating $path$dependent.idl\n";
684                         my $ret = `perl xpidl2cs.pl $dependent.idl $path $nosig`;
685                         print "\n$ret";
686                 }
687     }
688 }
689
690 sub generate_class_implementation_example {
691 #print "generate_class_implementation_example\n";
692     my $name = $interface->{"class"};
693         my $interfacename = $interface->{"class"};
694     my $helpername = $name;
695     $helpername =~ s/nsI//;
696     my $parent = $interface->{"parent"};
697
698         print X "#if example\n\n";
699     print X "using System;\n";
700     print X "using System.Runtime.InteropServices;\n";
701     print X "using System.Runtime.CompilerServices;\n";
702     print X "using System.Text;\n";
703     print X "\n";
704
705     print X "\tinternal class $helpername";
706     print X " : $interfacename";
707     print X " {\n";
708
709     print X "\n";
710     print X "#region $interfacename\n";
711
712     my @items = split ",", $interface->{"items"};
713     for my $item (@items) {
714
715                 if (&is_property ($item)) {
716                         my $out = &get_out($properties{$item}->{"type"});
717                         my $marshal = &get_marshal($properties{$item}->{"type"}, $out);
718                         my $type = &get_type ($properties{$item}->{"type"}, $out);
719
720                         my $retval = &get_return_value($type);
721                         my $name = ucfirst ($item);
722
723 ## getter
724                         print X "\t\t";
725                         if ($nosig) {
726                                 print X "[return: $marshal] " if $marshal;
727                                 print X "$type $interfacename.get$name ()\n";
728                         } else {
729                                 print X "int $interfacename.get$name (";
730                                 print X "[$marshal] " if $marshal;
731                                 print X "$out $type ret)\n";
732                         }
733
734                         print X "\n\t\t{\n";
735                         print X "\t\t\t";
736
737                         print X "return $retval;\n";
738
739                         print X "\t\t";
740                         print X "}\n";
741                         print X "\n";
742
743                         $type = &get_type ($properties{$item}->{"type"});
744                         $retval = &get_return_value($type);
745                         $marshal = &get_marshal($properties{$item}->{"type"});
746
747 ## setter
748                         if (&has_setter($item)) {
749                                 if ($nosig) {
750                                         print X "\t\tvoid";
751                                 } else {
752                                         print X "\t\tint";
753                                 }
754                                 print X " $interfacename.set$name (";
755                                 print X "[$marshal] " if $marshal;
756                                 print X "$type value)\n";
757                                 print X "\n";
758
759                                 print X "\n\t\t{\n";
760                                 print X "\t\t\t";
761
762                                 print X "return $retval;\n";
763
764                                 print X "\t\t";
765                                 print X "}\n";
766                                 print X "\n";
767                         }
768
769                 } else {
770                         my $type = &get_type ($methods{$item}->{"type"});
771                         my $out = &get_out($methods{$item}->{"type"}) if $type;
772                         my $marshal = &get_marshal($methods{$item}->{"type"}, $out) if $type;
773                         $type = "void" if !$type;
774
775                         print X "\t\t";
776                         if ($nosig) {
777                                 print X "[return: $marshal] " if $marshal;
778                                 print X "$type $interfacename.$item (";
779                                 print X &get_params($item);
780                                 print X ")";
781                         } else {
782                                 print X "int $interfacename.$item (";
783                                 print X &get_params($item);
784                                 print X ")";
785                         }
786
787                         print X "\n\t\t{\n";
788                         print X "\t\t\t";
789
790                         print X "return $retval;\n";
791
792                         print X "\t\t";
793                         print X "}\n";
794                         print X "\n";
795                         print X "\n\n";
796                 }
797     }
798     print X "#endregion\n";
799     print X "\t}\n";
800
801
802     print X "#endif\n";
803         
804 }
805
806
807 &parse_file ();
808 &output ();
809 &generate_dependents ();