stub out the Projection classes as well as duplicating the disgusting hack used for...
[moon.git] / tools / generators / Generator.cs
blob4f04d8136dae15f07935aef2d78216e59d3a6bb6
1 /*
2 * Generator.cs
4 * Contact:
5 * Moonlight List (moonlight-list@lists.ximian.com)
7 * Copyright 2008 Novell, Inc. (http://www.novell.com)
9 * See the LICENSE file included with the distribution for details.
12 using System;
13 using System.Linq;
14 using System.Collections.Generic;
15 using System.IO;
16 using System.Text;
19 class Generator {
20 delegate void output_native_type_delegate (string t, string k);
21 static StringBuilder forward_decls = new StringBuilder ();
22 static StringBuilder cbinding_requisites = new StringBuilder ();
24 public void Generate ()
26 GlobalInfo info = GetTypes2 ();
27 //info.Dump (0);
29 GenerateValueH (info);
30 GenerateTypeH (info);
31 GenerateKindCs ();
33 GenerateTypeStaticCpp (info);
34 GenerateCBindings (info);
35 GeneratePInvokes (info);
36 GenerateTypes_G (info);
38 GenerateDPs (info);
39 GenerateManagedDPs (info);
40 GenerateManagedDOs (info);
42 GenerateManagedEvents (info);
44 GenerateJSBindings (info);
47 static void GenerateJSBindings (GlobalInfo all)
49 List<MethodInfo> methods;
50 methods = all.JSMethodsToBind;
51 StringBuilder mappings = new StringBuilder ();
52 StringBuilder header = new StringBuilder ();
53 StringBuilder body = new StringBuilder ();
55 MemberInfo current = null;
56 Dictionary<string, List<MethodInfo>> types = new Dictionary<string, List<MethodInfo>> ();
58 foreach (MemberInfo m in methods) {
59 MethodInfo method = (MethodInfo) m;
60 string name = method.Annotations.GetValue ("GenerateJSBinding");
61 if (name == null)
62 name = method.Name;
63 mappings.AppendLine ("\tMoonId_" + method.Parent.Name + "_" + name + ",");
65 if (current != method.Parent) {
66 current = method.Parent;
68 if (!types.ContainsKey (current.Name))
69 types.Add (current.Name, new List<MethodInfo>());
70 types[current.Name].Add (method);
74 foreach (KeyValuePair<string, List<MethodInfo>> t in types) {
75 string parent = t.Key;
77 header.AppendLine ("/*** Moonlight" + parent + "Class *********/");
79 header.AppendLine ("struct Moonlight" + parent + "Type : MoonlightDependencyObjectType {");
80 header.AppendLine ("\tMoonlight" + parent + "Type ();");
81 header.AppendLine ("};");
82 header.AppendLine ();
83 header.AppendLine ("extern Moonlight" + parent + "Type *Moonlight" + parent + "Class;");
84 header.AppendLine ();
85 header.AppendLine ("struct Moonlight" + parent + "Object : MoonlightDependencyObjectObject {");
86 header.AppendLine ("\tMoonlight" + parent + "Object (NPP instance) : MoonlightDependencyObjectObject (instance)");
87 header.AppendLine ("\t{");
88 header.AppendLine ("\t\tmoonlight_type = Type::" + parent.ToUpper() + ";");
89 header.AppendLine ("\t}");
90 header.AppendLine ();
91 header.AppendLine ("\tvirtual bool Invoke (int id, NPIdentifier name,");
92 header.AppendLine ("\t\tconst NPVariant *args, guint32 argCount, NPVariant *result);");
93 header.AppendLine ();
94 header.AppendLine ("};");
96 body.AppendLine ("/*** Moonlight" + parent + "Class *********/");
97 body.AppendLine ("static NPObject *");
98 body.AppendLine ("moonlight_" + parent.ToLower() + "_allocate (NPP instance, NPClass *klass)");
99 body.AppendLine ("{");
100 body.AppendLine (" return new Moonlight" + parent + "Object (instance);");
101 body.AppendLine ("}");
102 body.AppendLine ();
103 body.AppendLine ("static const MoonNameIdMapping moonlight_" + parent.ToLower() + "_mapping[] = {");
105 for (int i = 0; i < t.Value.Count; i++) {
106 MethodInfo method = t.Value[i];
107 string name = method.Annotations.GetValue ("GenerateJSBinding");
108 if (name == null)
109 name = method.Name;
110 string id = "MoonId_" + parent + "_" + name;
111 body.Append (" {\"" + name.ToLower () + "\", " + id + "}");
113 if (i < t.Value.Count - 1)
114 body.Append (",");
115 body.AppendLine ("");
119 body.AppendLine ("};");
120 body.AppendLine ("");
121 body.AppendLine ("bool");
122 body.AppendLine ("Moonlight" + parent + "Object::Invoke (int id, NPIdentifier name,");
123 body.AppendLine (" const NPVariant *args, guint32 argCount,");
124 body.AppendLine (" NPVariant *result)");
125 body.AppendLine ("{");
126 body.AppendLine (" " + parent + " *dob = (" + parent + "*)GetDependencyObject ();");
127 body.AppendLine ("");
128 body.AppendLine (" switch (id) {");
130 foreach (MethodInfo method in t.Value) {
131 string name = method.Annotations.GetValue ("GenerateJSBinding");
132 if (name == null)
133 name = method.Name;
134 string id = "MoonId_" + parent + "_" + name;
135 body.AppendLine ();
136 body.AppendLine ("\t\tcase " + id + ": {");
138 bool errorcheck = false;
139 string argcodes = "";
140 List<string> args = new List<string>();
141 List<string> parms = new List<string>();
142 for (int i = 0; i < method.Parameters.Count; i++) {
143 ParameterInfo parameter = method.Parameters[i];
145 if (parameter.ParameterType.Value == "MoonError*") {
146 errorcheck = true;
147 } else {
148 argcodes += parameter.ParameterType.GetNPType ();
150 switch (parameter.ParameterType.GetNPType ()) {
151 case "i":
152 args.Add ("\t\t\tint arg" + i + " = NPVARIANT_TO_INT32 (args[" + i + "]);");
153 parms.Add ("arg" + i);
154 break;
155 case "s":
156 args.Add ("\t\t\tchar *arg" + i + " = STRDUP_FROM_VARIANT (args[" + i + "]);");
157 parms.Add ("arg" + i);
158 break;
159 case "o":
160 args.Add ("\t\t\tNPObject *obj" + i + " = NPVARIANT_TO_OBJECT (args[" + i + "]);");
161 args.Add ("\t\t\tif (!npobject_is_dependency_object (obj" + i + "))");
162 args.Add ("\t\t\t\tTHROW_JS_EXCEPTION (\"" + name + "\");");
163 args.Add ("\t\t\tDependencyObject *arg" + i + " = ((MoonlightDependencyObjectObject *) obj" + i + ")->GetDependencyObject();");
164 parms.Add ("(" + parameter.ParameterType.WriteFormatted () + ") arg" + i);
165 break;
166 case "d":
167 args.Add ("\t\t\tdouble arg" + i + " = NPVARIANT_TO_DOUBLE (args[" + i + "]);");
168 parms.Add ("arg" + i);
169 break;
170 case "b":
171 args.Add ("\t\t\tbool arg" + i + " = NPVARIANT_TO_BOOLEAN (args[" + i + "]);");
172 parms.Add ("arg" + i);
173 break;
178 if (argcodes != "") {
179 body.AppendLine ("\t\t\tif (!check_arg_list (\"" + argcodes + "\", argCount, args))");
180 body.AppendLine ("\t\t\t\tTHROW_JS_EXCEPTION (\"" + name + "\");");
183 if (errorcheck) {
184 body.AppendLine ("\t\t\tMoonError err;");
185 parms.Add ("&err");
188 if (args.Count > 0)
189 body.AppendLine (String.Join ("\n", args.ToArray()));
191 body.Append ("\t\t\t");
193 if (method.ReturnType.GetNPType () != "v") {
194 method.ReturnType.WriteFormatted (body);
195 body.AppendLine (" ret = dob->" + method.Name + "(" + String.Join (",", parms.ToArray ()) + ");");
196 } else
197 body.AppendLine ("dob->" + method.Name + "(" + String.Join (",", parms.ToArray ()) + ");");
199 for (int i = 0; i < method.Parameters.Count; i++) {
200 ParameterInfo parameter = method.Parameters[i];
201 if (parameter.ParameterType.GetNPType () == "s")
202 body.AppendLine ("g_free (arg" + i + ");");
205 if (errorcheck)
206 body.AppendLine ("\t\t\tif (err.number != 0) THROW_JS_EXCEPTION (err.message);");
208 switch (method.ReturnType.GetNPType ()) {
209 case "i":
210 body.AppendLine ("\t\t\tINT32_TO_NPVARIANT (ret, *result);");
211 break;
212 case "s":
213 body.AppendLine ("\t\t\tstring_to_npvariant (ret, *result);");
214 break;
215 case "o":
216 body.AppendLine ("\t\t\tif (ret)");
217 body.AppendLine ("\t\t\t\tOBJECT_TO_NPVARIANT (EventObjectCreateWrapper (GetPlugin (), ret), *result);");
218 body.AppendLine ("\t\t\telse");
219 body.AppendLine ("\t\t\t\tNULL_TO_NPVARIANT (*result);");
220 break;
221 case "d":
222 body.AppendLine ("\t\t\tDOUBLE_TO_NPVARIANT (ret, *result);");
223 break;
224 case "b":
225 body.AppendLine ("\t\t\tBOOLEAN_TO_NPVARIANT (ret, *result);");
226 break;
227 case "v":
228 body.AppendLine ("\t\t\tVOID_TO_NPVARIANT (*result);");
229 break;
232 body.AppendLine ("\t\t\treturn true;");
233 body.AppendLine ("\t\t\tbreak;");
234 body.AppendLine ("\t\t}");
237 body.AppendLine ("\t}");
238 body.AppendLine ();
240 body.AppendLine ("\treturn MoonlightDependencyObjectObject::Invoke (id, name, args, argCount, result);");
241 body.AppendLine ("}");
242 body.AppendLine ();
244 body.AppendLine ("Moonlight" + parent + "Type::Moonlight" + parent + "Type ()");
245 body.AppendLine ("{");
246 body.AppendLine (" AddMapping (moonlight_" + parent.ToLower() + "_mapping, G_N_ELEMENTS (moonlight_" + parent.ToLower() + "_mapping));");
247 body.AppendLine ();
248 body.AppendLine (" allocate = moonlight_" + parent.ToLower() + "_allocate;");
249 body.AppendLine ("}");
255 string file = "plugin/plugin-class.h";
257 string contents = File.ReadAllText (file + ".in");
258 contents = contents.Replace ("/*MAP_IDS*/", mappings.ToString());
259 contents = contents.Replace ("/*MAP_HEADERS*/", header.ToString());
261 StringBuilder text = new StringBuilder ();
262 Helper.WriteWarningGenerated (text);
263 contents = text.ToString () + contents;
264 Helper.WriteAllText (file, contents);
266 file = "plugin/plugin-class.g.cpp";
267 contents = File.ReadAllText (file + ".in");
268 contents = contents.Replace ("/*MAP_BODY*/", body.ToString());
270 text = new StringBuilder ();
271 Helper.WriteWarningGenerated (text);
272 contents = text.ToString () + contents;
273 Helper.WriteAllText (file, contents);
276 static void GenerateManagedEvents (GlobalInfo all)
278 string base_dir = Environment.CurrentDirectory;
279 string class_dir = Path.Combine (base_dir, "class");
280 string sys_win_dir = Path.Combine (Path.Combine (class_dir, "System.Windows"), "System.Windows");
281 string filename = Path.Combine (sys_win_dir, "Events.g.cs");
282 string previous_namespace = "";
283 List<TypeInfo> sorted_types = new List<TypeInfo> ();
284 StringBuilder text = new StringBuilder ();
285 Dictionary <TypeInfo, List<FieldInfo>> types = new Dictionary<TypeInfo,List<FieldInfo>> ();
287 foreach (FieldInfo field in all.Events) {
288 TypeInfo parent = field.Parent as TypeInfo;
289 List <FieldInfo> fields;
290 string managed_parent = field.Annotations.GetValue ("ManagedDeclaringType");
292 if (!field.IsEvent || !field.GenerateManagedEvent)
293 continue;
295 if (managed_parent != null) {
296 parent = all.Children [managed_parent] as TypeInfo;
298 if (parent == null)
299 throw new Exception (string.Format ("Could not find the type '{0}' set as ManagedDeclaringType of '{1}'", managed_parent, field.FullName));
302 if (parent == null)
303 throw new Exception (string.Format ("The field '{0}' does not have its parent set.", field.FullName));
305 if (!types.TryGetValue (parent, out fields)) {
306 fields = new List<FieldInfo> ();
307 types.Add (parent, fields);
308 sorted_types.Add (parent);
310 fields.Add (field);
313 Helper.WriteWarningGenerated (text);
314 text.AppendLine ("using Mono;");
315 text.AppendLine ("using System;");
316 text.AppendLine ("using System.Collections.Generic;");
317 text.AppendLine ("using System.Windows;");
318 text.AppendLine ("using System.Windows.Controls;");
319 text.AppendLine ("using System.Windows.Documents;");
320 text.AppendLine ("using System.Windows.Ink;");
321 text.AppendLine ("using System.Windows.Input;");
322 text.AppendLine ("using System.Windows.Markup;");
323 text.AppendLine ("using System.Windows.Media;");
324 text.AppendLine ("using System.Windows.Media.Animation;");
325 text.AppendLine ("using System.Windows.Shapes;");
326 text.AppendLine ();
328 text.AppendLine ("namespace Mono {");
329 text.AppendLine ("\tinternal static class EventIds {");
330 foreach (TypeInfo t in all.Children.SortedTypesByKind) {
331 if (t.GetEventCount () == 0)
332 continue;
335 foreach (FieldInfo field in t.Events) {
336 text.Append ("\t\tpublic const int ");
337 text.Append (t.Name);
338 text.Append ("_");
339 text.Append (field.EventName);
340 text.Append ("Event = ");
341 text.Append (t.GetEventId (field));
342 text.AppendLine (";");
345 text.AppendLine ("\t}");
347 text.AppendLine ("\tinternal static partial class Events {");
348 text.AppendLine ("\t\tpublic static UnmanagedEventHandler CreateDispatcherFromEventId (int eventId, Delegate value) {");
349 text.AppendLine ("\t\t\tswitch (eventId) {");
351 foreach (TypeInfo t in all.Children.SortedTypesByKind) {
352 if (t.GetEventCount () == 0)
353 continue;
356 foreach (FieldInfo field in t.Events) {
357 if (field.GenerateManagedEventField == false)
358 continue;
359 text.Append ("\t\t\t\tcase EventIds.");
360 text.Append (t.Name);
361 text.Append ("_");
362 text.Append (field.EventName);
363 text.Append ("Event: return Events.");
365 text.Append (GetDispatcherMethodName(field.EventDelegateType));
366 text.Append (" ((");
367 text.Append (field.EventDelegateType);
368 text.Append (") value)");
369 text.AppendLine (";");
372 text.AppendLine ("\t\t\t\tdefault: throw new NotSupportedException ();");
373 text.AppendLine ("\t\t\t}");
374 text.AppendLine ("\t\t}");
375 text.AppendLine ("\t}");
377 text.AppendLine ("}");
379 sorted_types.Sort (new Members.MembersSortedByManagedFullName <TypeInfo> ());
380 for (int i = 0; i < sorted_types.Count; i++) {
381 TypeInfo type = sorted_types [i];
382 List<FieldInfo> fields = types [type];
383 TypeInfo parent = type;
384 string ns;
386 ns = parent.Namespace;
388 if (string.IsNullOrEmpty (ns)) {
389 Console.WriteLine ("The type '{0}' in {1} does not have a namespace annotation.", parent.FullName, parent.Header);
390 continue;
393 if (type.Annotations.ContainsKey ("ManagedEvents")) {
394 string event_mode = type.Annotations.GetValue ("ManagedEvents");
395 switch (event_mode) {
396 case "None":
397 case "Manual":
398 continue;
399 case "Generate":
400 break;
401 default:
402 throw new Exception (string.Format ("Invalid value '{0}' for ManagedEvents in '{1}'", event_mode, type.FullName));
406 if (ns == "None") {
407 Console.WriteLine ("'{0}''s Namespace = 'None', this type should have set @ManagedEvents=Manual to not create events.", type.FullName);
408 continue;
411 string check_ns = Path.Combine (Path.Combine (Path.Combine (class_dir, "System.Windows"), ns), parent.Name + ".cs");
412 if (!File.Exists (check_ns))
413 Console.WriteLine ("The file {0} does not exist, did you annotate the class with the wrong namespace?", check_ns);
415 if (previous_namespace != ns) {
416 if (previous_namespace != string.Empty) {
417 text.AppendLine ("}");
418 text.AppendLine ();
420 text.Append ("namespace ");
421 text.Append (ns);
422 text.AppendLine (" {");
423 previous_namespace = ns;
424 } else {
425 text.AppendLine ();
427 text.Append ("\tpartial class ");
428 text.Append (parent.ManagedName);
429 text.AppendLine (" {");
431 fields.Sort (new Members.MembersSortedByName <FieldInfo> ());
434 foreach (FieldInfo field in fields) {
435 if (!field.IsEvent)
436 continue;
438 text.AppendLine ();
440 // property accessor
441 text.Append ("\t\t");
442 Helper.WriteAccess (text, field.GetManagedAccessorAccess ());
443 text.Append (" event ");
444 text.Append (field.EventDelegateType);
445 text.Append (" ");
446 text.Append (field.EventName);
447 text.AppendLine (" {");
449 // property getter
450 text.Append ("\t\t\t");
451 if (field.GetManagedAccessorAccess () != field.GetManagedGetterAccess ()) {
452 Helper.WriteAccess (text, field.GetManagedGetterAccess ());
453 text.Append (" ");
456 text.Append ("add { RegisterEvent (EventIds.");
457 text.Append (field.ParentType.Name);
458 text.Append ("_");
459 text.Append (field.EventName);
460 text.Append ("Event, value, Events.");
461 text.Append (GetDispatcherMethodName(field.EventDelegateType));
462 text.Append (" (value)");
463 text.AppendLine ("); }");
465 text.Append ("\t\t\t");
466 text.Append ("remove { UnregisterEvent (EventIds.");
467 text.Append (field.ParentType.Name);
468 text.Append ("_");
469 text.Append (field.EventName);
470 text.Append ("Event, value);");
471 text.AppendLine (" }");
473 text.AppendLine ("\t\t}");
475 if (field.GenerateManagedEventField) {
476 text.Append ("\t\t");
477 text.Append (string.Format ("public static readonly RoutedEvent {0}Event = new RoutedEvent (EventIds.{1}_{2}Event);", field.EventName, field.ParentType.Name, field.EventName));
478 text.AppendLine ();
482 text.AppendLine ("\t}");
485 text.AppendLine ("}");
487 Helper.WriteAllText (filename, text.ToString ());
490 static string GetDispatcherMethodName (string delegateType)
492 if (delegateType.Contains ("<")) {
493 string[] delegate_types = delegateType.Split ('<', '>');
494 return string.Format ("Create{0}{1}Dispatcher", delegate_types[1], delegate_types[0]);
496 else
497 return string.Format ("Create{0}Dispatcher", delegateType);
500 static void GenerateManagedDOs (GlobalInfo all)
502 string base_dir = Environment.CurrentDirectory;
503 string class_dir = Path.Combine (base_dir, "class");
504 string sys_win_dir = Path.Combine (Path.Combine (class_dir, "System.Windows"), "System.Windows");
505 string filename = Path.Combine (sys_win_dir, "DependencyObject.g.cs");
506 string previous_namespace = "";
507 StringBuilder text = new StringBuilder ();
508 List<TypeInfo> types = all.GetDependencyObjects ();
510 Helper.WriteWarningGenerated (text);
511 text.AppendLine ("using Mono;");
512 text.AppendLine ("using System;");
513 text.AppendLine ("using System.Collections.Generic;");
514 text.AppendLine ("using System.Windows;");
515 text.AppendLine ("using System.Windows.Controls;");
516 text.AppendLine ("using System.Windows.Documents;");
517 text.AppendLine ("using System.Windows.Ink;");
518 text.AppendLine ("using System.Windows.Input;");
519 text.AppendLine ("using System.Windows.Markup;");
520 text.AppendLine ("using System.Windows.Media;");
521 text.AppendLine ("using System.Windows.Media3D;");
522 text.AppendLine ("using System.Windows.Media.Animation;");
523 text.AppendLine ("using System.Windows.Shapes;");
524 text.AppendLine ();
526 for (int i = 0; i < types.Count; i++) {
527 TypeInfo type = types [i];
528 bool call_initialize = type.Annotations.ContainsKey ("CallInitialize");
529 string ns;
531 ns = type.Namespace;
533 if (string.IsNullOrEmpty (ns)) {
534 Console.WriteLine ("The type '{0}' in {1} does not have a namespace annotation.", type.FullName, Path.GetFileName (type.Header));
535 continue;
538 if (ns == "None") {
539 //Console.WriteLine ("The type '{0}''s Namespace annotation is 'None'.", type.FullName);
540 continue;
543 string check_ns = Path.Combine (Path.Combine (Path.Combine (class_dir, "System.Windows"), ns), type.ManagedName.Replace ("`1", "") + ".cs");
544 if (!File.Exists (check_ns)) {
545 Console.WriteLine ("The file {0} does not exist, did you annotate the class with the wrong namespace?", check_ns);
546 continue;
549 if (previous_namespace != ns) {
550 if (previous_namespace != string.Empty) {
551 text.AppendLine ("}");
552 text.AppendLine ();
554 text.Append ("namespace ");
555 text.Append (ns);
556 text.AppendLine (" {");
557 previous_namespace = ns;
558 } else {
559 text.AppendLine ();
562 if (type.ContentProperty != null)
563 text.AppendFormat ("\t[ContentProperty (\"{0}\")]\n", type.ContentProperty);
564 text.Append ("\tpartial class ");
565 text.Append (type.ManagedName.Replace ("`1", "<T>"));
566 text.AppendLine (" {");
568 // Public ctor
569 if (!string.IsNullOrEmpty (type.C_Constructor)) {
570 string access = "Public";
571 foreach (MemberInfo member in type.Children.Values) {
572 MethodInfo method = member as MethodInfo;
574 if (method == null || !method.IsConstructor || method.IsStatic)
575 continue;
577 if (method.Parameters.Count != 0)
578 continue;
580 if (method.Annotations.ContainsKey ("ManagedAccess"))
581 access = method.Annotations.GetValue ("ManagedAccess");
582 break;
586 text.Append ("\t\t");
587 Helper.WriteAccess (text, access);
588 text.Append (" ");
589 text.Append (type.ManagedName.Replace ("`1", ""));
590 text.Append (" () : base (NativeMethods.");
591 text.Append (type.C_Constructor);
592 text.Append (" (), true)");
593 if (call_initialize) {
594 text.AppendLine ();
595 text.AppendLine ("\t\t{");
596 text.AppendLine ("\t\t\tInitialize ();");
597 text.AppendLine ("\t\t}");
598 } else {
599 text.AppendLine (" {}");
603 // Internal ctor
604 text.Append ("\t\tinternal ");
605 text.Append (type.ManagedName.Replace ("`1", ""));
606 text.Append (" (IntPtr raw, bool dropref) : base (raw, dropref)");
607 if (call_initialize) {
608 text.AppendLine ();
609 text.AppendLine ("\t\t{");
610 text.AppendLine ("\t\t\tInitialize ();");
611 text.AppendLine ("\t\t}");
612 } else {
613 text.AppendLine (" {}");
616 text.AppendLine ("\t}");
618 text.AppendLine ("}");
620 Helper.WriteAllText (filename, text.ToString ());
623 static void GenerateManagedDPs (GlobalInfo all)
625 string base_dir = Environment.CurrentDirectory;
626 string class_dir = Path.Combine (base_dir, "class");
627 string sys_win_dir = Path.Combine (Path.Combine (class_dir, "System.Windows"), "System.Windows");
628 string filename = Path.Combine (sys_win_dir, "DependencyProperty.g.cs");
629 string previous_namespace = "";
630 List<TypeInfo> sorted_types = new List<TypeInfo> ();
631 StringBuilder text = new StringBuilder ();
632 Dictionary <TypeInfo, List<FieldInfo>> types = new Dictionary<TypeInfo,List<FieldInfo>> ();
634 foreach (FieldInfo field in all.DependencyProperties) {
635 TypeInfo parent = field.Parent as TypeInfo;
636 List <FieldInfo> fields;
637 string managed_parent = field.Annotations.GetValue ("ManagedDeclaringType");
639 if (field.Annotations.GetValue ("GenerateManagedDP") == "false")
640 continue;
642 if (managed_parent != null) {
643 parent = all.Children [managed_parent] as TypeInfo;
645 if (parent == null)
646 throw new Exception (string.Format ("Could not find the type '{0}' set as ManagedDeclaringType of '{1}'", managed_parent, field.FullName));
649 if (parent == null)
650 throw new Exception (string.Format ("The field '{0}' does not have its parent set.", field.FullName));
652 if (!types.TryGetValue (parent, out fields)) {
653 fields = new List<FieldInfo> ();
654 types.Add (parent, fields);
655 sorted_types.Add (parent);
657 fields.Add (field);
660 Helper.WriteWarningGenerated (text);
661 text.AppendLine ("using Mono;");
662 text.AppendLine ("using System;");
663 text.AppendLine ("using System.Collections.Generic;");
664 text.AppendLine ("using System.Windows;");
665 text.AppendLine ("using System.Windows.Controls;");
666 text.AppendLine ("using System.Windows.Documents;");
667 text.AppendLine ("using System.Windows.Ink;");
668 text.AppendLine ("using System.Windows.Input;");
669 text.AppendLine ("using System.Windows.Markup;");
670 text.AppendLine ("using System.Windows.Media;");
671 text.AppendLine ("using System.Windows.Media3D;");
672 text.AppendLine ("using System.Windows.Media.Animation;");
673 text.AppendLine ("using System.Windows.Media.Effects;");
674 text.AppendLine ("using System.Windows.Shapes;");
675 text.AppendLine ();
677 sorted_types.Sort (new Members.MembersSortedByManagedFullName <TypeInfo> ());
678 for (int i = 0; i < sorted_types.Count; i++) {
679 TypeInfo type = sorted_types [i];
680 List<FieldInfo> fields = types [type];
681 TypeInfo parent = type;
682 string ns;
684 ns = parent.Namespace;
686 if (string.IsNullOrEmpty (ns)) {
687 Console.WriteLine ("The type '{0}' in {1} does not have a namespace annotation.", parent.FullName, parent.Header);
688 continue;
691 if (type.Annotations.ContainsKey ("ManagedDependencyProperties")) {
692 string dp_mode = type.Annotations.GetValue ("ManagedDependencyProperties");
693 switch (dp_mode) {
694 case "None":
695 case "Manual":
696 continue;
697 case "Generate":
698 break;
699 default:
700 throw new Exception (string.Format ("Invalid value '{0}' for ManagedDependencyProperties in '{1}'", dp_mode, type.FullName));
704 if (ns == "None") {
705 Console.WriteLine ("'{0}''s Namespace = 'None', this type should have set @ManagedDependencyProperties=Manual to not create DPs.", type.FullName);
706 continue;
709 string check_ns = Path.Combine (Path.Combine (Path.Combine (class_dir, "System.Windows"), ns), parent.Name + ".cs");
710 if (!File.Exists (check_ns))
711 Console.WriteLine ("The file {0} does not exist, did you annotate the class with the wrong namespace?", check_ns);
713 if (previous_namespace != ns) {
714 if (previous_namespace != string.Empty) {
715 text.AppendLine ("}");
716 text.AppendLine ();
718 text.Append ("namespace ");
719 text.Append (ns);
720 text.AppendLine (" {");
721 previous_namespace = ns;
722 } else {
723 text.AppendLine ();
725 text.Append ("\tpartial class ");
726 text.Append (parent.ManagedName);
727 text.AppendLine (" {");
729 fields.Sort (new Members.MembersSortedByName <FieldInfo> ());
731 // The DP registration
732 foreach (FieldInfo field in fields) {
733 bool conv_int_to_double = field.GetDPManagedPropertyType (all) == "int" && field.GetDPPropertyType (all).Name == "double";
735 text.Append ("\t\t");
736 Helper.WriteAccess (text, field.GetManagedFieldAccess ());
737 text.Append (" static readonly DependencyProperty ");
738 text.Append (field.Name);
739 text.Append (" = DependencyProperty.Lookup (Kind.");
740 text.Append (field.ParentType.KindName);
741 text.Append (", \"");
742 text.Append (field.GetDependencyPropertyName ());
743 text.Append ("\", typeof (");
744 if (conv_int_to_double)
745 text.Append ("double");
746 else
747 text.Append (field.GetDPManagedPropertyType (all));
748 text.AppendLine ("));");
751 foreach (FieldInfo field in fields) {
752 bool conv_int_to_double = field.GetDPManagedPropertyType (all) == "int" && field.GetDPPropertyType (all).Name == "double";
754 if (field.IsDPAttached || !field.GenerateManagedAccessors)
755 continue;
757 text.AppendLine ();
759 // property accessor
760 text.Append ("\t\t");
761 Helper.WriteAccess (text, field.GetManagedAccessorAccess ());
762 text.Append (" ");
763 text.Append (field.GetDPManagedPropertyType (all));
764 text.Append (" ");
765 text.Append (field.GetDependencyPropertyName ());
766 text.AppendLine (" {");
768 // property getter
769 text.Append ("\t\t\t");
770 if (field.GetManagedAccessorAccess () != field.GetManagedGetterAccess ()) {
771 Helper.WriteAccess (text, field.GetManagedGetterAccess ());
772 text.Append (" ");
775 text.Append ("get { return (");
776 text.Append (field.GetDPManagedPropertyType (all));
777 if (conv_int_to_double)
778 text.Append (") (double");
779 text.Append (") GetValue (");
780 text.Append (field.Name);
781 text.AppendLine ("); }");
783 // property setter
784 if (!field.IsDPReadOnly) {
785 text.Append ("\t\t\t");
786 if (field.GetManagedAccessorAccess () != field.GetManagedSetterAccess ()) {
787 Helper.WriteAccess (text, field.GetManagedSetterAccess ());
788 text.Append (" ");
790 text.Append ("set { SetValue (");
791 text.Append (field.Name);
792 text.AppendLine (", value); }");
794 text.AppendLine ("\t\t}");
797 text.AppendLine ("\t}");
799 text.AppendLine ("}");
801 Helper.WriteAllText (filename, text.ToString ());
804 class TypeEdgeCount {
805 public TypeEdgeCount (TypeInfo type)
807 Type = type;
808 Inbound = new List<TypeInfo>();
809 Outbound = new List<TypeInfo>();
812 public TypeInfo Type {
813 get; private set;
815 public List<TypeInfo> Inbound {
816 get; private set;
818 public List<TypeInfo> Outbound {
819 get; private set;
823 static List<FieldInfo> TopoSortedProperties (GlobalInfo all, List<TypeInfo> types)
825 Dictionary<TypeInfo,TypeEdgeCount> typeHash = new Dictionary<TypeInfo,TypeEdgeCount>();
827 List<TypeInfo> remainingTypes = new List<TypeInfo>();
829 foreach (TypeInfo type in types) {
830 typeHash.Add (type, new TypeEdgeCount (type));
831 remainingTypes.Add (type);
834 // build up edges for our graph
835 foreach (TypeInfo type in typeHash.Keys) {
837 // every property defines an edge from the declaring type to the property type
838 foreach (FieldInfo prop in type.Properties) {
839 if (string.IsNullOrEmpty (prop.DPDefaultValue))
840 continue;
842 TypeInfo propType = prop.GetDPPropertyType (all);
843 if (propType == type)
844 continue;
845 if (typeHash.ContainsKey (propType) && !typeHash[propType].Inbound.Contains (type)) {
846 typeHash[propType].Inbound.Add (type);
847 typeHash[type].Outbound.Add (propType);
851 // every base class has an edge to subclass
852 // (this is kind of a hack to deal with
853 // property types which are listed as base
854 // types when the default values are
855 // subclasses.
857 TypeInfo ourType = type;
858 TypeReference baseRef = ourType.Base;
859 while (baseRef != null && !string.IsNullOrEmpty (baseRef.Value)) {
860 TypeInfo baseType = (TypeInfo) all.Children [baseRef.Value];
861 if (baseType == null)
862 break;
863 if (typeHash.ContainsKey (baseType) && !typeHash[baseType].Outbound.Contains (ourType)) {
864 typeHash[baseType].Outbound.Add (ourType);
865 typeHash[ourType].Inbound.Add (baseType);
867 ourType = baseType;
868 if (!typeHash.ContainsKey (ourType))
869 break;
870 baseRef = ourType.Base;
874 List<TypeInfo> sorted = new List<TypeInfo>();
875 List<TypeInfo> roots = new List<TypeInfo>();
877 foreach (TypeEdgeCount tec in typeHash.Values) {
878 if (tec.Inbound.Count == 0)
879 roots.Add (tec.Type);
882 while (roots.Count > 0) {
883 TypeInfo type = roots[0];
884 roots.RemoveAt (0);
886 sorted.Add (type);
887 remainingTypes.Remove (type);
889 foreach (TypeInfo targetType in typeHash[type].Outbound) {
890 if (!typeHash.ContainsKey (targetType))
891 continue;
892 typeHash[targetType].Inbound.Remove (type);
893 if (typeHash[targetType].Inbound.Count == 0) {
894 roots.Add (targetType);
899 if (remainingTypes.Count > 0) {
900 throw new Exception (string.Format ("cycle in the DO/DP graph ({0} types left)", remainingTypes.Count));
903 List<FieldInfo> fields = new List<FieldInfo>();
904 foreach (TypeInfo type in sorted) {
905 foreach (FieldInfo field in type.Properties)
906 fields.Insert (0, field);
908 return fields;
911 static void GenerateDPs (GlobalInfo all)
913 string base_dir = Environment.CurrentDirectory;
914 string moon_dir = Path.Combine (base_dir, "src");
915 // int version_previous = 0;
916 StringBuilder text = new StringBuilder ();
917 List<FieldInfo> fields = all.DependencyProperties;
918 List<string> headers = new List<string> ();
920 List<TypeInfo> types = new List<TypeInfo> ();
921 foreach (FieldInfo field in fields) {
922 if (!types.Contains ((TypeInfo)field.Parent))
923 types.Add ((TypeInfo)field.Parent);
925 fields = TopoSortedProperties (all, types);
927 headers.Add ("dependencyproperty.h");
928 headers.Add ("validators.h");
929 headers.Add ("provider.h");
930 headers.Add ("color.h");
931 headers.Add ("managedtypeinfo.h");
932 foreach (FieldInfo field in fields) {
933 string h;
934 if (string.IsNullOrEmpty (field.Header))
935 continue;
936 h = Path.GetFileName (field.Header);
938 if (!headers.Contains (h))
939 headers.Add (h);
942 Helper.WriteWarningGenerated (text);
943 text.AppendLine ();
944 text.AppendLine ("#include <config.h>");
945 text.AppendLine ();
946 headers.Sort ();
947 foreach (string h in headers) {
948 text.Append ("#include \"");
949 text.Append (h);
950 text.AppendLine ("\"");
952 text.AppendLine ();
953 text.AppendLine ("void");
954 text.AppendLine ("Types::RegisterNativeProperties ()");
955 text.AppendLine ("{");
957 for (int i = 0; i < fields.Count; i++) {
958 FieldInfo field = fields [i];
959 TypeInfo type = field.ParentType;
960 TypeInfo propertyType = null;
961 string default_value = field.DPDefaultValue;
962 bool has_default_value = !string.IsNullOrEmpty (default_value);
963 string autocreator = field.DPAutoCreator;
964 bool is_nullable = field.IsDPNullable;
965 bool is_attached = field.IsDPAttached;
966 bool is_readonly = field.IsDPReadOnly;
967 bool is_always_change = field.IsDPAlwaysChange;
968 string validator = field.DPValidator;
969 bool is_full = is_attached || is_readonly || is_always_change || validator != null || autocreator != null || is_nullable;
971 propertyType = field.GetDPPropertyType (all);
973 text.Append ("\t");
975 if (propertyType == null) {
976 text.Append ("// (no PropertyType was found for this DependencyProperty) ");
977 } else {
978 headers.Add (propertyType.Header);
981 text.Append ("DependencyProperty::Register");
982 if (is_full)
983 text.Append ("Full");
985 text.Append (" (");
986 text.Append ("this, ");
987 text.Append ("Type::");
988 text.Append (type.KindName);
989 text.Append (", \"");
991 text.Append (field.GetDependencyPropertyName ());
992 text.Append ("\"");
993 text.Append (", ");
995 text.Append (field.IsCustom ? "true" : "false");
996 text.Append (", ");
998 if (is_full) {
999 if (has_default_value) {
1000 if (default_value.StartsWith ("new "))
1001 text.Append ("Value::CreateUnrefPtr (");
1002 else
1003 text.Append ("new Value (");
1004 text.Append (default_value);
1005 text.Append (")");
1006 } else {
1007 text.Append ("NULL");
1009 } else {
1010 if (has_default_value) {
1011 if (default_value.StartsWith ("new "))
1012 text.Append ("Value::CreateUnrefPtr (");
1013 else
1014 text.Append ("new Value (");
1015 text.Append (default_value);
1016 text.Append (")");
1020 if ((has_default_value || is_full))
1021 text.Append (", ");
1023 if (propertyType != null) {
1024 if (propertyType.IsEnum) {
1025 text.Append ("Type::INT32");
1026 } else {
1027 text.Append ("Type::");
1028 text.Append (propertyType.KindName);
1030 } else if (!has_default_value) {
1031 text.Append ("Type::INVALID");
1032 Console.WriteLine ("{0} does not define its property type.", field.FullName);
1035 if (is_full) {
1036 text.Append (", ");
1037 text.Append (is_attached ? "true" : "false");
1038 text.Append (", ");
1039 text.Append (is_readonly ? "true" : "false");
1040 text.Append (", ");
1041 text.Append (is_always_change ? "true" : "false");
1042 text.Append (", ");
1043 text.Append ("NULL");
1044 text.Append (", ");
1045 text.Append (validator != null ? ("Validators::" + validator) : "NULL");
1046 text.Append (", ");
1047 text.Append (autocreator != null
1048 ? (autocreator.Contains("::") ? autocreator : "AutoCreators::" + autocreator)
1049 : "NULL");
1050 text.Append (", ");
1051 text.Append (is_nullable ? "true" : "false");
1054 text.AppendLine (");");
1056 text.AppendLine ("}");
1057 text.AppendLine ();
1059 // Static initializers
1060 for (int i = 0; i < fields.Count; i++) {
1061 FieldInfo field = fields [i];
1062 text.Append ("const int ");
1063 text.Append (field.Parent.Name);
1064 text.Append ("::");
1065 text.Append (field.Name);
1066 text.Append (" = ");
1067 text.Append (i);
1068 text.AppendLine (";");
1070 text.AppendLine ();
1072 // C++ Accessors
1073 for (int i = 0; i < fields.Count; i++) {
1074 FieldInfo field = fields [i];
1075 TypeInfo prop_type;
1076 string prop_type_str;
1077 string value_str;
1078 string prop_default = null;
1079 bool both = field.Annotations.ContainsKey ("GenerateAccessors");
1080 bool setter = both || field.Annotations.ContainsKey ("GenerateSetter");
1081 bool getter = both || field.Annotations.ContainsKey ("GenerateGetter");
1082 bool is_attached = field.IsDPAttached;
1083 bool nullable_setter = setter && field.IsDPNullable;
1084 bool doing_nullable_setter = false;
1086 if (!setter && !getter)
1087 continue;
1089 prop_type = field.GetDPPropertyType (all);
1091 switch (prop_type.Name) {
1092 case "char*":
1093 prop_type_str = "const char *";
1094 value_str = "String";
1095 break;
1096 case "int":
1097 case "gint32":
1098 value_str = "Int32";
1099 prop_type_str = prop_type.Name;
1100 prop_default = "0";
1101 break;
1102 case "double":
1103 value_str = "Double";
1104 prop_type_str = prop_type.Name;
1105 prop_default = "0.0";
1106 break;
1107 case "bool":
1108 prop_type_str = prop_type.Name;
1109 value_str = "Bool";
1110 prop_default = "false";
1111 break;
1112 case "char":
1113 prop_type_str = "gunichar";
1114 value_str = "Char";
1115 prop_default = "0";
1116 break;
1117 case "object":
1118 prop_type_str = "Value *";
1119 prop_default = "NULL";
1120 value_str = null;
1121 break;
1122 default:
1123 prop_type_str = prop_type.Name;
1124 value_str = prop_type.Name;
1125 break;
1128 string GetterName = string.Format ("{0}::Get{1}", field.ParentType.Name, field.GetDependencyPropertyName());
1129 string SetterName = string.Format ("{0}::Set{1}", field.ParentType.Name, field.GetDependencyPropertyName());
1131 if (getter) {
1132 text.Append (prop_type_str);
1133 if (field.IsDPNullable || (prop_type.IsClass || prop_type.IsStruct))
1134 text.Append (" *");
1135 text.AppendLine ();
1136 text.Append (GetterName);
1137 if (is_attached)
1138 text.AppendLine (" (DependencyObject *obj)");
1139 else
1140 text.AppendLine (" ()");
1141 text.AppendLine ("{");
1144 if (value_str == null) {
1145 text.Append ("\treturn ");
1146 } else if (is_attached) {
1147 text.Append ("\tValue *value = (!obj) ? NULL : ");
1148 } else {
1149 text.Append ("\tValue *value = ");
1152 text.AppendFormat ("{0}{1}GetValue ({2}::{3});\n",
1153 is_attached ? "obj->" : "",
1154 field.ParentType.NeedsQualifiedGetValue(all) ? "DependencyObject::" : "",
1155 field.ParentType.Name, field.Name);
1157 if (is_attached) {
1158 text.AppendFormat ("\tif (!value) value = Deployment::GetCurrent ()->GetTypes ()->GetProperty ({0}::{1})->GetDefaultValue();\n",
1159 field.ParentType.Name, field.Name);
1162 if (value_str == null) {
1163 // Skip this
1164 } else if (field.IsDPNullable || (prop_type.IsClass || prop_type.IsStruct || prop_type.Name == "char*")) {
1165 text.Append ("\treturn value ? ");
1166 if (prop_type.IsEnum) {
1167 text.AppendFormat ("({0}) value->AsInt32() : ({0}) 0", prop_type.Name);
1168 } else {
1169 if (!field.IsDPNullable && (/*prop_type.IsStruct || */prop_default != null))
1170 if (string.IsNullOrEmpty (prop_default))
1171 throw new NotImplementedException (
1172 string.Format ("Generation of DependencyProperties with struct values ({0}.{1})",
1173 field.ParentType.Name, field.Name));
1175 text.AppendFormat ("value->As{0}{1} () : {2}",
1176 field.IsDPNullable && !(prop_type.IsStruct || prop_type.IsClass) ? "Nullable" : "",
1177 value_str,
1178 !field.IsDPNullable && prop_default != null ? prop_default : "NULL");
1180 } else {
1181 // Value cannot be null, so don't need to check for it
1182 text.Append ("\treturn ");
1183 if (prop_type.IsEnum) {
1184 text.AppendFormat ("({0}) value->AsInt32 ()", prop_type.Name);
1185 } else {
1186 text.AppendFormat ("value->As{0} ()", value_str);
1190 if (value_str != null)
1191 text.AppendLine (";");
1192 text.AppendLine ("}");
1193 text.AppendLine ();
1196 do_nullable_setter:
1197 if (setter) {
1198 text.AppendLine ("void");
1199 text.Append (SetterName);
1200 text.Append (" (");
1201 if (is_attached)
1202 text.Append ("DependencyObject *obj, ");
1203 text.Append (prop_type_str);
1204 if (prop_type.Name != "char*")
1205 text.Append (' ');
1206 if (!nullable_setter && (prop_type.IsClass || prop_type.IsStruct))
1207 text.Append ('*');
1208 text.AppendLine ("value)");
1210 text.AppendLine ("{");
1211 if (is_attached)
1212 text.AppendLine ("\tif (!obj) return;");
1213 if (doing_nullable_setter) {
1214 text.AppendLine ("\tif (!value)");
1215 text.Append ("\t\t");
1216 text.AppendFormat ("{0}{1}SetValue ({2}::{3}, NULL);\n",
1217 is_attached ? "obj->" : "",
1218 field.ParentType.NeedsQualifiedGetValue(all) ? "DependencyObject::" : "",
1219 field.ParentType.Name, field.Name);
1220 text.AppendLine ("\telse");
1221 text.Append ("\t\t");
1222 text.AppendFormat ("{0}{1}SetValue ({2}::{3}, Value (*value));\n",
1223 is_attached ? "obj->" : "",
1224 field.ParentType.NeedsQualifiedGetValue(all) ? "DependencyObject::" : "",
1225 field.ParentType.Name, field.Name);
1226 } else {
1227 if (!nullable_setter && prop_type.IsStruct)
1228 text.AppendLine ("\tif (!value) return;");
1229 text.Append ("\t");
1230 text.AppendFormat ("{0}{1}SetValue ({2}::{3}, ",
1231 is_attached ? "obj->" : "",
1232 field.ParentType.NeedsQualifiedGetValue(all) ? "DependencyObject::" : "",
1233 field.ParentType.Name, field.Name);
1235 if (prop_type.Name == "guint64" || prop_type.Name == "TimeSpan") {
1236 text.AppendFormat ("Value (value, Type::{0}));\n",
1237 prop_type.KindName);
1239 else if (prop_type.Name == "char") {
1240 text.AppendLine ("Value (value, Type::CHAR));");
1242 else if ((value_str == null) || (!nullable_setter && prop_type.IsStruct)) {
1243 text.AppendLine ("Value (*value));");
1245 else if (prop_type.IsClass) {
1246 text.AppendLine ("Value::CreateUnrefPtr (value));");
1248 else {
1249 text.AppendLine ("Value (value));");
1252 text.AppendLine ("}");
1253 text.AppendLine ();
1256 if (nullable_setter) {
1257 if (!prop_type.IsStruct)
1258 prop_type_str += " *";
1259 nullable_setter = false;
1260 doing_nullable_setter = true;
1261 goto do_nullable_setter;
1265 Helper.WriteAllText (Path.Combine (moon_dir, "dependencyproperty.g.cpp"), text.ToString ());
1269 static GlobalInfo GetTypes2 ()
1271 string srcdir = Path.Combine (Environment.CurrentDirectory, "src");
1272 string asfdir = Path.Combine (srcdir, "asf");
1273 string plugindir = Path.Combine (Environment.CurrentDirectory, "plugin");
1274 List<string> all_files = new List<string> ();
1276 all_files.AddRange (Directory.GetFiles (srcdir, "*.h"));
1277 all_files.AddRange (Directory.GetFiles (asfdir, "*.h"));
1278 all_files.AddRange (Directory.GetFiles (plugindir, "*.h"));
1280 RemoveExcludedSrcFiles (srcdir, all_files);
1282 Tokenizer tokenizer = new Tokenizer (all_files.ToArray ());
1283 GlobalInfo all = new GlobalInfo ();
1285 tokenizer.Advance (false);
1287 try {
1288 while (ParseMembers (all, tokenizer)) {
1290 } catch (Exception ex) {
1291 throw new Exception (string.Format ("{0}({1}): {2}", tokenizer.CurrentFile, tokenizer.CurrentLine, ex.Message), ex);
1294 // Add all the manual types
1295 TypeInfo t;
1296 TypeInfo IComparableInfo;
1297 TypeInfo IFormattableInfo;
1298 TypeInfo IConvertibleInfo;
1299 TypeInfo IEquatableBoolInfo;
1300 TypeInfo IComparableBoolInfo;
1301 TypeInfo IEquatableDoubleInfo;
1302 TypeInfo IComparableDoubleInfo;
1303 TypeInfo IEquatableFloatInfo;
1304 TypeInfo IComparableFloatInfo;
1305 TypeInfo IEquatableCharInfo;
1306 TypeInfo IComparableCharInfo;
1307 TypeInfo IEquatableIntInfo;
1308 TypeInfo IComparableIntInfo;
1309 TypeInfo IEquatableLongInfo;
1310 TypeInfo IComparableLongInfo;
1311 TypeInfo IEquatableStringInfo;
1312 TypeInfo IComparableStringInfo;
1313 TypeInfo IEquatableTimeSpanInfo;
1314 TypeInfo IComparableTimeSpanInfo;
1315 TypeInfo IEquatableUintInfo;
1316 TypeInfo IComparableUintInfo;
1317 TypeInfo IEquatableUlongInfo;
1318 TypeInfo IComparableUlongInfo;
1320 all.Children.Add (new TypeInfo ("object", "OBJECT", "INVALID", true, true));
1322 all.Children.Add (IComparableInfo = new TypeInfo ("IComparable", "ICOMPARABLE", "OBJECT", true, true, false, true));
1323 all.Children.Add (IFormattableInfo = new TypeInfo ("IFormattable", "IFORMATTABLE", "OBJECT", true, true, false, true));
1324 all.Children.Add (IConvertibleInfo = new TypeInfo ("IConvertible", "ICONVERTIBLE", "OBJECT", true, true, false, true));
1326 all.Children.Add (IEquatableBoolInfo = new TypeInfo ("IEquatable<bool>", "IEQUATABLE_BOOL", "OBJECT", true, true, false, true));
1327 all.Children.Add (IComparableBoolInfo = new TypeInfo ("IComparable<bool>", "ICOMPARABLE_BOOL", "OBJECT", true, true, false, true));
1329 all.Children.Add (IEquatableDoubleInfo = new TypeInfo ("IEquatable<double>", "IEQUATABLE_DOUBLE", "OBJECT", true, true, false, true));
1330 all.Children.Add (IComparableDoubleInfo = new TypeInfo ("IComparable<double>", "ICOMPARABLE_DOUBLE", "OBJECT", true, true, false, true));
1332 all.Children.Add (IEquatableFloatInfo = new TypeInfo ("IEquatable<float>", "IEQUATABLE_FLOAT", "OBJECT", true, true, false, true));
1333 all.Children.Add (IComparableFloatInfo = new TypeInfo ("IComparable<float>", "ICOMPARABLE_FLOAT", "OBJECT", true, true, false, true));
1335 all.Children.Add (IEquatableCharInfo = new TypeInfo ("IEquatable<char>", "IEQUATABLE_CHAR", "OBJECT", true, true, false, true));
1336 all.Children.Add (IComparableCharInfo = new TypeInfo ("IComparable<char>", "ICOMPARABLE_CHAR", "OBJECT", true, true, false, true));
1338 all.Children.Add (IEquatableIntInfo = new TypeInfo ("IEquatable<int>", "IEQUATABLE_INT", "OBJECT", true, true, false, true));
1339 all.Children.Add (IComparableIntInfo = new TypeInfo ("IComparable<int>", "ICOMPARABLE_INT", "OBJECT", true, true, false, true));
1341 all.Children.Add (IEquatableLongInfo = new TypeInfo ("IEquatable<long>", "IEQUATABLE_LONG", "OBJECT", true, true, false, true));
1342 all.Children.Add (IComparableLongInfo = new TypeInfo ("IComparable<long>", "ICOMPARABLE_LONG", "OBJECT", true, true, false, true));
1344 all.Children.Add (IEquatableStringInfo = new TypeInfo ("IEquatable<string>", "IEQUATABLE_STRING", "OBJECT", true, true, false, true));
1345 all.Children.Add (IComparableStringInfo = new TypeInfo ("IComparable<string>", "ICOMPARABLE_STRING", "OBJECT", true, true, false, true));
1347 all.Children.Add (IEquatableTimeSpanInfo = new TypeInfo ("IEquatable<TimeSpan>", "IEQUATABLE_TIMESPAN", "OBJECT", true, true, false, true));
1348 all.Children.Add (IComparableTimeSpanInfo = new TypeInfo ("IComparable<TimeSpan>", "ICOMPARABLE_TIMESPAN", "OBJECT", true, true, false, true));
1350 all.Children.Add (IEquatableUintInfo = new TypeInfo ("IEquatable<uint>", "IEQUATABLE_UINT", "OBJECT", true, true, false, true));
1351 all.Children.Add (IComparableUintInfo = new TypeInfo ("IComparable<uint>", "ICOMPARABLE_UINT", "OBJECT", true, true, false, true));
1353 all.Children.Add (IEquatableUlongInfo = new TypeInfo ("IEquatable<ulong>", "IEQUATABLE_ULONG", "OBJECT", true, true, false, true));
1354 all.Children.Add (IComparableUlongInfo = new TypeInfo ("IComparable<ulong>", "ICOMPARABLE_ULONG", "OBJECT", true, true, false, true));
1356 all.Children.Add (t = new TypeInfo ("bool", "BOOL", "OBJECT", true, true, true, false));
1357 t.Interfaces.Add (IComparableInfo);
1358 t.Interfaces.Add (IComparableBoolInfo);
1359 t.Interfaces.Add (IConvertibleInfo);
1360 t.Interfaces.Add (IEquatableBoolInfo);
1362 all.Children.Add (t = new TypeInfo ("float", "FLOAT", "OBJECT", true, true, true, false));
1363 t.Interfaces.Add (IComparableInfo);
1364 t.Interfaces.Add (IComparableFloatInfo);
1365 t.Interfaces.Add (IConvertibleInfo);
1366 t.Interfaces.Add (IEquatableFloatInfo);
1367 t.Interfaces.Add (IFormattableInfo);
1369 all.Children.Add (t = new TypeInfo ("double", "DOUBLE", "OBJECT", true, true, true, false));
1370 t.Interfaces.Add (IComparableInfo);
1371 t.Interfaces.Add (IComparableDoubleInfo);
1372 t.Interfaces.Add (IConvertibleInfo);
1373 t.Interfaces.Add (IEquatableDoubleInfo);
1374 t.Interfaces.Add (IFormattableInfo);
1376 all.Children.Add (t = new TypeInfo ("guint64", "UINT64", "OBJECT", true, true, true, false));
1377 t.Interfaces.Add (IComparableInfo);
1378 t.Interfaces.Add (IComparableUlongInfo);
1379 t.Interfaces.Add (IConvertibleInfo);
1380 t.Interfaces.Add (IEquatableUlongInfo);
1381 t.Interfaces.Add (IFormattableInfo);
1383 all.Children.Add (t = new TypeInfo ("gint64", "INT64", "OBJECT", true, true, true, false));
1384 t.Interfaces.Add (IComparableInfo);
1385 t.Interfaces.Add (IComparableLongInfo);
1386 t.Interfaces.Add (IConvertibleInfo);
1387 t.Interfaces.Add (IEquatableLongInfo);
1388 t.Interfaces.Add (IFormattableInfo);
1390 all.Children.Add (t = new TypeInfo ("guint32", "UINT32", "OBJECT", true, true, true, false));
1391 t.Interfaces.Add (IComparableInfo);
1392 t.Interfaces.Add (IComparableUintInfo);
1393 t.Interfaces.Add (IConvertibleInfo);
1394 t.Interfaces.Add (IEquatableUintInfo);
1395 t.Interfaces.Add (IFormattableInfo);
1397 all.Children.Add (t = new TypeInfo ("gint32", "INT32", "OBJECT", true, true, true, false));
1398 t.Interfaces.Add (IComparableInfo);
1399 t.Interfaces.Add (IComparableIntInfo);
1400 t.Interfaces.Add (IConvertibleInfo);
1401 t.Interfaces.Add (IEquatableIntInfo);
1402 t.Interfaces.Add (IFormattableInfo);
1404 all.Children.Add (t = new TypeInfo ("char*", "STRING", "OBJECT", true, true, true, false));
1405 t.Interfaces.Add (IComparableInfo);
1406 t.Interfaces.Add (IComparableStringInfo);
1407 t.Interfaces.Add (IConvertibleInfo);
1408 t.Interfaces.Add (IEquatableStringInfo);
1409 t.Interfaces.Add (IFormattableInfo);
1411 all.Children.Add (t = new TypeInfo ("TimeSpan", "TIMESPAN", "OBJECT", true, true, true, false));
1412 t.Interfaces.Add (IComparableInfo);
1413 t.Interfaces.Add (IComparableTimeSpanInfo);
1414 t.Interfaces.Add (IEquatableTimeSpanInfo);
1416 all.Children.Add (t = new TypeInfo ("char", "CHAR", "OBJECT", true, true, true, false));
1417 t.Interfaces.Add (IComparableInfo);
1418 t.Interfaces.Add (IComparableCharInfo);
1419 t.Interfaces.Add (IConvertibleInfo);
1420 t.Interfaces.Add (IEquatableCharInfo);
1422 all.Children.Add (new TypeInfo ("NPObj", "NPOBJ", "OBJECT", true, true, true, false));
1423 all.Children.Add (new TypeInfo ("Managed", "MANAGED", "OBJECT", true, 2, true));
1425 all.Children.Add (new TypeInfo ("System.Windows.Input.Cursor", "CURSOR", "OBJECT", true, true));
1426 all.Children.Add (new TypeInfo ("System.Windows.Markup.XmlLanguage", "XMLLANGUAGE", "OBJECT", true, true));
1428 // Set IncludeInKinds for all types which inherit from EventObject
1429 foreach (MemberInfo member in all.Children.Values) {
1430 TypeInfo type = member as TypeInfo;
1431 if (type == null)
1432 continue;
1433 if (type.Name == "EventObject")
1434 type.Annotations ["IncludeInKinds"] = null;
1436 TypeReference bR = type.Base;
1437 MemberInfo m;
1438 TypeInfo b;
1439 while (bR != null) {
1440 if (bR.Value == "EventObject") {
1441 member.Annotations ["IncludeInKinds"] = null;
1444 if (!all.Children.TryGetValue (bR.Value, out m))
1445 break;
1447 b = m as TypeInfo;
1448 if (b != null)
1449 bR = b.Base;
1450 else
1451 bR = null;
1455 return all;
1458 // Returns false if there are no more tokens (reached end of code)
1459 static bool ParseClassOrStruct (Annotations annotations, MemberInfo parent, Tokenizer tokenizer)
1461 TypeInfo type = new TypeInfo ();
1463 type.Annotations = annotations;
1464 type.Header = tokenizer.CurrentFile;
1465 type.Parent = parent;
1467 type.IsPublic = tokenizer.Accept (Token2Type.Identifier, "public");
1469 if (tokenizer.Accept (Token2Type.Identifier, "class")) {
1470 type.IsClass = true;
1471 } else if (tokenizer.Accept (Token2Type.Identifier, "struct")) {
1472 type.IsStruct = true;
1473 type.IsValueType = true;
1474 } else if (tokenizer.Accept (Token2Type.Identifier, "union")) {
1475 type.IsStruct = true; // Not entirely correct, but a union can be parsed as a struct
1476 type.IsValueType = true;
1477 } else {
1478 throw new Exception (string.Format ("Expected 'class' or 'struct', not '{0}'", tokenizer.CurrentToken.value));
1481 if (tokenizer.CurrentToken.type == Token2Type.Identifier) {
1482 type.Name = tokenizer.GetIdentifier ();
1483 } else {
1484 type.Name = "<anonymous>";
1487 if (tokenizer.Accept (Token2Type.Punctuation, ";")) {
1488 // A forward declaration.
1489 //Console.WriteLine ("ParseType: Found a forward declaration to {0}", type.Name);
1490 return true;
1493 if (tokenizer.Accept (Token2Type.Punctuation, ":")) {
1494 if (!tokenizer.Accept (Token2Type.Identifier, "public") && type.IsClass)
1495 throw new Exception (string.Format ("The base class of {0} is not public.", type.Name));
1497 type.Base = ParseTypeReference (tokenizer);
1499 // accept multiple inheritance the easy way
1500 while (tokenizer.CurrentToken.value == ",") {
1501 tokenizer.Accept (Token2Type.Punctuation, ",");
1503 while (tokenizer.CurrentToken.value != "," &&
1504 tokenizer.CurrentToken.value != "{")
1505 tokenizer.GetIdentifier ();
1508 //Console.WriteLine ("ParseType: Found {0}'s base class: {1}", type.Name, type.Base);
1511 tokenizer.AcceptOrThrow (Token2Type.Punctuation, "{");
1513 //Console.WriteLine ("ParseType: Found a type: {0} in {1}", type.Name, type.Header);
1514 parent.Children.Add (type);
1515 ParseMembers (type, tokenizer);
1517 tokenizer.AcceptOrThrow (Token2Type.Punctuation, "}");
1519 if (tokenizer.CurrentToken.type == Token2Type.Identifier)
1520 tokenizer.Advance (true);
1522 if (tokenizer.CurrentToken.value != ";")
1523 throw new Exception (string.Format ("Expected ';', not '{0}'", tokenizer.CurrentToken.value));
1525 return tokenizer.Advance (false);
1528 static bool ParseMembers (MemberInfo parent, Tokenizer tokenizer)
1530 Annotations properties = new Annotations ();
1531 TypeInfo parent_type = parent as TypeInfo;
1532 string accessibility;
1533 TypeReference returntype;
1534 bool is_dtor;
1535 bool is_ctor;
1536 bool is_virtual;
1537 bool is_static;
1538 bool is_const;
1539 bool is_extern;
1540 string name;
1542 //Console.WriteLine ("ParseMembers ({0})", type.Name);
1544 do {
1545 returntype = null;
1546 is_dtor = is_ctor = is_virtual = is_static = false;
1547 is_extern = is_const = false;
1548 name = null;
1549 properties = new Annotations ();
1551 if (parent_type != null)
1552 accessibility = parent_type.IsStruct ? "public" : "private";
1553 else
1554 accessibility = "public";
1556 if (tokenizer.Accept (Token2Type.Punctuation, ";"))
1557 continue;
1559 if (tokenizer.CurrentToken.value == "}")
1560 return true;
1562 while (tokenizer.CurrentToken.type == Token2Type.CommentProperty) {
1563 properties.Add (tokenizer.CurrentToken.value);
1564 tokenizer.Advance (true);
1567 //Console.WriteLine ("ParseMembers: Current token: {0}", tokenizer.CurrentToken);
1569 if (tokenizer.CurrentToken.type == Token2Type.Identifier) {
1570 string v = tokenizer.CurrentToken.value;
1571 switch (v) {
1572 case "public":
1573 case "protected":
1574 case "private":
1575 accessibility = v;
1576 tokenizer.Advance (true);
1577 tokenizer.Accept (Token2Type.Punctuation, ":");
1578 continue;
1579 case "enum":
1580 ParseEnum (properties, parent, tokenizer);
1581 continue;
1582 case "friend":
1583 while (!tokenizer.Accept (Token2Type.Punctuation, ";")) {
1584 tokenizer.Advance (true);
1586 continue;
1587 case "struct":
1588 case "class":
1589 case "union":
1590 if (!ParseClassOrStruct (properties, parent, tokenizer))
1591 return false;
1592 continue;
1593 case "typedef":
1594 StringBuilder requisite = new StringBuilder ();
1595 requisite.Append (tokenizer.CurrentToken.value);
1596 requisite.Append (' ');
1597 tokenizer.Advance (true);
1598 while (!tokenizer.Accept (Token2Type.Punctuation, ";")) {
1599 requisite.Append (tokenizer.CurrentToken.value);
1600 requisite.Append (' ');
1601 if (tokenizer.CurrentToken.value == "{") {
1602 tokenizer.Advance (true);
1603 while (!tokenizer.Accept (Token2Type.Punctuation, "}")) {
1604 requisite.Append (tokenizer.CurrentToken.value);
1605 requisite.Append (' ');
1606 tokenizer.Advance (true);
1608 requisite.Append (tokenizer.CurrentToken.value);
1609 requisite.Append (' ');
1611 tokenizer.Advance (true);
1613 requisite.Append (";");
1614 if (properties.ContainsKey ("CBindingRequisite"))
1615 cbinding_requisites.AppendLine (requisite.ToString ());
1617 continue;
1618 case "EVENTHANDLER":
1619 while (!tokenizer.Accept (Token2Type.Punctuation, ";"))
1620 tokenizer.Advance (true);
1621 continue;
1622 case "template":
1623 tokenizer.Advance (true);
1624 tokenizer.AcceptOrThrow (Token2Type.Punctuation, "<");
1625 tokenizer.AcceptOrThrow (Token2Type.Identifier, "typename");
1626 tokenizer.GetIdentifier ();
1627 tokenizer.AcceptOrThrow (Token2Type.Punctuation, ">");
1628 continue;
1632 do {
1633 if (tokenizer.Accept (Token2Type.Identifier, "virtual")) {
1634 is_virtual = true;
1635 continue;
1638 if (tokenizer.Accept (Token2Type.Identifier, "static")) {
1639 is_static = true;
1640 continue;
1643 if (tokenizer.Accept (Token2Type.Identifier, "const")) {
1644 is_const = true;
1645 continue;
1648 if (tokenizer.Accept (Token2Type.Identifier, "extern")) {
1649 is_extern = true;
1650 continue;
1653 if (tokenizer.Accept (Token2Type.Identifier, "volatile")) {
1654 continue;
1657 if (tokenizer.Accept (Token2Type.Identifier, "G_GNUC_INTERNAL")) {
1658 continue;
1661 break;
1662 } while (true);
1664 if (is_extern && tokenizer.Accept (Token2Type.Literal, "C")) {
1665 tokenizer.SyncWithEndBrace ();
1666 continue;
1669 if (tokenizer.Accept (Token2Type.Punctuation, "~")) {
1670 is_dtor = true;
1671 if (!is_virtual) {
1672 TypeInfo ti = parent as TypeInfo;
1673 if (ti != null && ti.Base != null)
1674 Console.WriteLine ("The class {0} has a non-virtual destructor, and it's base class is {2} ({1}).", parent.Name, parent.Header, ti != null && ti.Base != null ? ti.Base.Value : "<none>");
1678 if (is_dtor) {
1679 name = "~" + tokenizer.GetIdentifier ();
1680 returntype = new TypeReference ("void");
1681 } else {
1682 returntype = ParseTypeReference (tokenizer);
1684 if (tokenizer.CurrentToken.value == "<") {
1685 tokenizer.Advance (true);
1686 while (!tokenizer.Accept (Token2Type.Punctuation, ">"))
1687 tokenizer.Advance (true);
1690 if (returntype.Value == parent.Name && tokenizer.CurrentToken.value == "(") {
1691 is_ctor = true;
1692 name = returntype.Value;
1693 returntype.Value += "*";
1694 } else {
1695 name = tokenizer.GetIdentifier ();
1698 returntype.IsConst = is_const;
1699 returntype.IsReturnType = true;
1701 //Console.WriteLine ("ParseMembers: found member '{0}' is_ctor: {1}", name, is_ctor);
1703 if (tokenizer.Accept (Token2Type.Punctuation, "(")) {
1704 // Method
1705 MethodInfo method = new MethodInfo ();
1706 method.Header = tokenizer.CurrentFile;
1707 method.Parent = parent;
1708 method.Annotations = properties;
1709 method.Name = name;
1710 method.IsConstructor = is_ctor;
1711 method.IsDestructor = is_dtor;
1712 method.IsVirtual = is_virtual;
1713 method.IsStatic = is_static;
1714 method.IsPublic = accessibility == "public";
1715 method.IsPrivate = accessibility == "private";
1716 method.IsProtected = accessibility == "protected";
1717 method.ReturnType = returntype;
1719 //Console.WriteLine ("ParseMembers: found method '{0}' is_ctor: {1}", name, is_ctor);
1721 if (!tokenizer.Accept (Token2Type.Punctuation, ")")) {
1722 string param_value = null;
1723 do {
1724 ParameterInfo parameter = new ParameterInfo (method);
1726 while (tokenizer.CurrentToken.type == Token2Type.CommentProperty) {
1727 parameter.Annotations.Add (tokenizer.CurrentToken.value);
1728 tokenizer.Advance (true);
1731 if (tokenizer.Accept (Token2Type.Punctuation, ".") && tokenizer.Accept (Token2Type.Punctuation, ".") && tokenizer.Accept (Token2Type.Punctuation, ".")) {
1732 // ... variable argument declaration
1733 parameter.ParameterType = new TypeReference ("...");
1734 } else {
1735 parameter.ParameterType = ParseTypeReference (tokenizer);
1737 if (tokenizer.CurrentToken.value != "," && tokenizer.CurrentToken.value != ")") {
1738 parameter.Name = tokenizer.GetIdentifier ();
1739 if (tokenizer.Accept (Token2Type.Punctuation, "[")) {
1740 if (tokenizer.CurrentToken.type == Token2Type.Identifier)
1741 tokenizer.Advance (true);
1742 tokenizer.AcceptOrThrow (Token2Type.Punctuation, "]");
1744 if (tokenizer.Accept (Token2Type.Punctuation, "=")) {
1745 param_value = string.Empty;
1746 if (tokenizer.Accept (Token2Type.Punctuation, "-"))
1747 param_value = "-";
1748 param_value += tokenizer.GetIdentifier ();
1749 if (tokenizer.Accept (Token2Type.Punctuation, ":")) {
1750 tokenizer.AcceptOrThrow (Token2Type.Punctuation, ":");
1751 param_value += "::" + tokenizer.GetIdentifier ();
1755 method.Parameters.Add (parameter);
1756 //Console.WriteLine ("ParseMember: got parameter, type: '{0}' name: '{1}' value: '{2}'", parameter.ParameterType.Value, parameter.Name, param_value);
1757 } while (tokenizer.Accept (Token2Type.Punctuation, ","));
1758 tokenizer.AcceptOrThrow (Token2Type.Punctuation, ")");
1761 parent.Children.Add (method);
1763 //Allow const member functions, ignore the const keyword
1764 tokenizer.Accept (Token2Type.Identifier, "const");
1766 if (tokenizer.CurrentToken.value == "{") {
1767 //Console.WriteLine ("ParseMember: member has body, skipping it");
1768 tokenizer.SyncWithEndBrace ();
1769 } else if (is_ctor && tokenizer.Accept (Token2Type.Punctuation, ":")) {
1770 // ctor method implemented in header with field initializers and/or base class ctor call
1771 tokenizer.FindStartBrace ();
1772 tokenizer.SyncWithEndBrace ();
1773 //Console.WriteLine ("ParseMember: skipped ctor method implementation");
1774 } else if (tokenizer.Accept (Token2Type.Punctuation, "=")) {
1775 // pure virtual method
1776 tokenizer.AcceptOrThrow (Token2Type.Identifier, "0");
1777 tokenizer.AcceptOrThrow (Token2Type.Punctuation, ";");
1778 method.IsAbstract = true;
1779 } else {
1780 tokenizer.AcceptOrThrow (Token2Type.Punctuation, ";");
1782 } else {
1783 if (is_ctor || is_dtor)
1784 throw new Exception (string.Format ("Expected '(', not '{0}'", tokenizer.CurrentToken.value));
1786 if (name == "operator") {
1787 while (true) {
1788 if (tokenizer.CurrentToken.value == ";") {
1789 // End of operator
1790 break;
1791 } else if (tokenizer.CurrentToken.value == "{") {
1792 // In-line implementation
1793 tokenizer.SyncWithEndBrace ();
1794 break;
1796 tokenizer.Advance (true);
1798 //Console.WriteLine ("ParseMembers: skipped operator");
1799 } else {
1800 FieldInfo field = new FieldInfo ();
1801 field.IsConst = is_const;
1802 field.IsStatic = is_static;
1803 field.IsExtern = is_extern;
1804 field.Name = name;
1805 field.FieldType = returntype;
1806 field.IsPublic = accessibility == "public";
1807 field.IsPrivate = accessibility == "private";
1808 field.IsProtected = accessibility == "protected";
1809 field.Annotations = properties;
1811 // Field
1812 do {
1813 //Console.WriteLine ("ParseMembers: found field '{0}'", name);
1814 field.Parent = parent;
1815 parent.Children.Add (field);
1817 if (tokenizer.Accept (Token2Type.Punctuation, "[")) {
1818 while (!tokenizer.Accept (Token2Type.Punctuation, "]")) {
1819 tokenizer.Advance (true);
1822 if (tokenizer.Accept (Token2Type.Punctuation, ":")) {
1823 field.BitField = tokenizer.GetIdentifier ();
1825 if (tokenizer.Accept (Token2Type.Punctuation, ",")) {
1826 field = new FieldInfo ();
1827 if (tokenizer.Accept (Token2Type.Punctuation, "*")) {
1828 // ok
1830 field.Name = tokenizer.GetIdentifier ();
1831 field.FieldType = returntype;
1832 continue;
1834 if (tokenizer.Accept (Token2Type.Punctuation, "=")) {
1835 tokenizer.Advance (true); /* this can be an arbitrary long expression, sync with the ';'? */
1837 break;
1838 } while (true);
1840 tokenizer.Accept (Token2Type.Punctuation, ";");
1843 } while (true);
1846 static void ParseEnum (Annotations properties, MemberInfo parent, Tokenizer tokenizer)
1848 FieldInfo field;
1849 StringBuilder value = new StringBuilder ();
1850 TypeInfo type = new TypeInfo ();
1852 type.Annotations = properties;
1853 type.IsEnum = true;
1855 tokenizer.AcceptOrThrow (Token2Type.Identifier, "enum");
1856 if (tokenizer.CurrentToken.type == Token2Type.Identifier) {
1857 type.Name = tokenizer.GetIdentifier ();
1858 } else {
1859 type.Name = "<anonymous>";
1861 parent.Children.Add (type);
1863 tokenizer.AcceptOrThrow (Token2Type.Punctuation, "{");
1865 //Console.WriteLine ("ParseEnum: {0}", name);
1867 while (tokenizer.CurrentToken.type == Token2Type.Identifier) {
1868 field = new FieldInfo ();
1869 field.Name = tokenizer.GetIdentifier ();
1870 value.Length = 0;
1871 if (tokenizer.Accept (Token2Type.Punctuation, "=")) {
1872 while (tokenizer.CurrentToken.value != "," && tokenizer.CurrentToken.value != "}") {
1873 value.Append (" ");
1874 value.Append (tokenizer.CurrentToken.value);
1875 tokenizer.Advance (true);
1878 field.Value = value.ToString ();
1879 type.Children.Add (field);
1880 //Console.WriteLine ("ParseEnum: {0}: {1} {2} {3}", name, field, value.Length != 0 != null ? "=" : "", value);
1882 if (!tokenizer.Accept (Token2Type.Punctuation, ","))
1883 break;
1886 tokenizer.AcceptOrThrow (Token2Type.Punctuation, "}");
1887 tokenizer.AcceptOrThrow (Token2Type.Punctuation, ";");
1890 public static TypeReference ParseTypeReference (Tokenizer tokenizer)
1892 TypeReference tr = new TypeReference ();
1893 StringBuilder result = new StringBuilder ();
1895 if (tokenizer.Accept (Token2Type.Identifier, "const"))
1896 tr.IsConst = true;
1898 if (tokenizer.Accept (Token2Type.Identifier, "unsigned"))
1899 result.Append ("unsigned");
1901 if (tokenizer.Accept (Token2Type.Identifier, "const"))
1902 tr.IsConst = true;
1904 result.Append (tokenizer.GetIdentifier ());
1906 if (tokenizer.Accept (Token2Type.Punctuation, ":")) {
1907 tokenizer.AcceptOrThrow (Token2Type.Punctuation, ":");
1908 result.Append ("::");
1909 result.Append (tokenizer.GetIdentifier ());
1912 if (tokenizer.Accept (Token2Type.Identifier, "const"))
1913 tr.IsConst = true;
1915 while (tokenizer.Accept (Token2Type.Punctuation, "*"))
1916 result.Append ("*");
1918 if (tokenizer.Accept (Token2Type.Identifier, "const"))
1919 tr.IsConst = true;
1921 if (tokenizer.Accept (Token2Type.Punctuation, "&"))
1922 result.Append ("&");
1924 if (tokenizer.Accept (Token2Type.Identifier, "const"))
1925 tr.IsConst = true;
1927 //Console.WriteLine ("ParseTypeReference: parsed '{0}'", result.ToString ());
1929 tr.Value = result.ToString ();
1931 return tr;
1934 public static string getU (string v)
1936 if (v.Contains ("::"))
1937 v = v.Substring (v.IndexOf ("::") + 2);
1939 v = v.ToUpper ();
1940 v = v.Replace ("DEPENDENCYOBJECT", "DEPENDENCY_OBJECT");
1941 if (v.Length > "COLLECTION".Length && !v.StartsWith ("COLLECTION"))
1942 v = v.Replace ("COLLECTION", "_COLLECTION");
1943 if (v.Length > "DICTIONARY".Length)
1944 v = v.Replace ("DICTIONARY", "_DICTIONARY");
1945 return v;
1948 public void GenerateTypes_G (GlobalInfo all)
1950 string base_dir = Environment.CurrentDirectory;
1951 string class_dir = Path.Combine (base_dir, "class");
1952 string moon_moonlight_dir = Path.Combine (class_dir, "System.Windows");
1953 List<TypeInfo> types = new List<TypeInfo> (all.GetDependencyObjects ());
1955 StringBuilder text = new StringBuilder ();
1957 Helper.WriteWarningGenerated (text);
1959 text.AppendLine ("using Mono;");
1960 text.AppendLine ("using System;");
1961 text.AppendLine ("using System.Reflection;");
1962 text.AppendLine ("using System.Collections.Generic;");
1963 text.AppendLine ("");
1964 text.AppendLine ("namespace Mono {");
1965 text.AppendLine ("\tpartial class Types {");
1966 text.AppendLine ("\t\tprivate void CreateNativeTypes ()");
1967 text.AppendLine ("\t\t{");
1968 text.AppendLine ("\t\t\tType t;");
1969 text.AppendLine ("\t\t\ttry {");
1971 foreach (MemberInfo m in all.Children.Values) {
1972 TypeInfo t = m as TypeInfo;
1973 if (t == null)
1974 continue;
1975 if (types.Contains (t))
1976 continue;
1977 types.Add (t);
1980 types.Sort (new Members.MembersSortedByManagedFullName <TypeInfo> ());
1982 for (int i = 0; i < types.Count; i++) {
1983 TypeInfo t = types [i];
1984 string type = t.ManagedName;
1986 if (String.IsNullOrEmpty (t.Namespace) || t.Namespace == "None" || t.Name.StartsWith ("MoonWindow"))
1987 continue;
1989 if (type == "PresentationFrameworkCollection`1")
1990 type = "PresentationFrameworkCollection<>";
1992 //Log.WriteLine ("Found Kind.{0} in {1} which result in type: {2}.{3}", kind, file, ns, type);
1994 text.Append ("\t\t\t\tt = typeof (");
1995 text.Append (t.Namespace);
1996 text.Append (".");
1997 text.Append (type);
1998 text.AppendLine ("); ");
2000 text.Append ("\t\t\t\ttypes.Add (t, new ManagedType (t, Kind.");
2001 text.Append (t.KindName);
2002 text.AppendLine ("));");
2005 // now handle the primitive types
2006 output_native_type_delegate f = delegate (string t, string k) {
2007 text.Append ("\t\t\t\tt = typeof (");
2008 text.Append (t);
2009 text.AppendLine (");");
2012 text.Append ("\t\t\t\ttypes.Add (t, new ManagedType (t, Kind.");
2013 text.Append (k);
2014 text.AppendLine ("));");
2017 f ("char", "UINT32");
2018 f ("object", "OBJECT");
2019 f ("bool", "BOOL");
2020 f ("double", "DOUBLE");
2021 f ("float", "FLOAT");
2022 f ("ulong", "UINT64");
2023 f ("long", "INT64");
2024 f ("uint", "UINT32");
2025 f ("int", "INT32");
2026 f ("string", "STRING");
2027 f ("TimeSpan", "TIMESPAN");
2029 // all the interfaces
2030 f ("IComparable", "ICOMPARABLE");
2031 f ("IFormattable", "IFORMATTABLE");
2032 f ("IConvertible", "ICONVERTIBLE");
2033 f ("IEquatable<bool>", "IEQUATABLE_BOOL");
2034 f ("IComparable<bool>", "ICOMPARABLE_BOOL");
2035 f ("IEquatable<double>", "IEQUATABLE_DOUBLE");
2036 f ("IComparable<double>", "ICOMPARABLE_DOUBLE");
2037 f ("IEquatable<float>", "IEQUATABLE_FLOAT");
2038 f ("IComparable<float>", "ICOMPARABLE_FLOAT");
2039 f ("IEquatable<char>", "IEQUATABLE_CHAR");
2040 f ("IComparable<char>", "ICOMPARABLE_CHAR");
2041 f ("IEquatable<int>", "IEQUATABLE_INT");
2042 f ("IComparable<int>", "ICOMPARABLE_INT");
2043 f ("IEquatable<long>", "IEQUATABLE_LONG");
2044 f ("IComparable<long>", "ICOMPARABLE_LONG");
2045 f ("IEquatable<string>", "IEQUATABLE_STRING");
2046 f ("IComparable<string>", "ICOMPARABLE_STRING");
2047 f ("IEquatable<TimeSpan>", "IEQUATABLE_TIMESPAN");
2048 f ("IComparable<TimeSpan>", "ICOMPARABLE_TIMESPAN");
2049 f ("IEquatable<uint>", "IEQUATABLE_UINT");
2050 f ("IComparable<uint>", "ICOMPARABLE_UINT");
2051 f ("IEquatable<ulong>", "IEQUATABLE_ULONG");
2052 f ("IComparable<ulong>", "ICOMPARABLE_ULONG");
2054 f ("System.Windows.Application", "APPLICATION");
2055 f ("System.Windows.Thickness", "THICKNESS");
2056 f ("System.Windows.CornerRadius", "CORNERRADIUS");
2057 f ("System.Windows.PropertyPath", "PROPERTYPATH");
2058 f ("System.Windows.Point", "POINT");
2059 f ("System.Windows.Rect", "RECT");
2060 f ("System.Windows.Size", "SIZE");
2061 f ("System.Windows.FontStretch", "FONTSTRETCH");
2062 f ("System.Windows.FontWeight", "FONTWEIGHT");
2063 f ("System.Windows.FontStyle", "FONTSTYLE");
2064 f ("System.Windows.Input.Cursor", "CURSOR");
2065 f ("System.Windows.Media.FontFamily", "FONTFAMILY");
2066 f ("System.Windows.Markup.XmlLanguage", "XMLLANGUAGE");
2068 text.AppendLine ("\t\t\t} catch (Exception ex) {");
2069 text.AppendLine ("\t\t\t\tConsole.WriteLine (\"There was an error while loading native types: \" + ex.ToString ());");
2070 text.AppendLine ("\t\t\t}");
2071 text.AppendLine ("\t\t}");
2072 text.AppendLine ("\t}");
2073 text.AppendLine ("}");
2075 Log.WriteLine ("typeandkidngen done");
2077 Helper.WriteAllText (Path.Combine (Path.Combine (moon_moonlight_dir, "Mono"), "Types.g.cs"), text.ToString ());
2080 private static void GenerateCBindings (GlobalInfo info, string dir)
2082 List<MethodInfo> methods;
2083 StringBuilder header = new StringBuilder ();
2084 StringBuilder impl = new StringBuilder ();
2085 List <string> headers = new List<string> ();
2086 List <string> classes = new List<string> ();
2087 List <string> structs = new List<string> ();
2089 string last_type = string.Empty;
2091 methods = info.CPPMethodsToBind;
2093 Helper.WriteWarningGenerated (header);;
2094 Helper.WriteWarningGenerated (impl);
2096 header.AppendLine ("#ifndef __MOONLIGHT_C_BINDING_H__");
2097 header.AppendLine ("#define __MOONLIGHT_C_BINDING_H__");
2098 header.AppendLine ();
2099 header.AppendLine ("#include <glib.h>");
2100 header.AppendLine ("#include <cairo.h>");
2101 header.AppendLine ();
2102 header.AppendLine ("#include \"enums.h\"");
2103 header.AppendLine ();
2104 foreach (MemberInfo member in info.Children.Values) {
2105 TypeInfo type = member as TypeInfo;
2106 if (type == null)
2107 continue;
2109 if (type.IsClass) {
2110 if (!classes.Contains (type.Name))
2111 classes.Add (type.Name);
2112 } else if (type.IsStruct) {
2113 if (!structs.Contains (type.Name))
2114 structs.Add (type.Name);
2118 foreach (MemberInfo method in methods) {
2119 string h;
2121 if (method.ParentType != null) {
2122 TypeInfo type = method.ParentType;
2123 if (type.IsClass) {
2124 if (!classes.Contains (type.Name))
2125 classes.Add (type.Name);
2126 } else if (type.IsStruct) {
2127 if (!structs.Contains (type.Name))
2128 structs.Add (type.Name);
2132 if (string.IsNullOrEmpty (method.Header))
2133 continue;
2134 if (!method.Header.StartsWith (dir))
2135 continue;
2137 h = Path.GetFileName (method.Header);
2139 if (!headers.Contains (h))
2140 headers.Add (h);
2142 header.AppendLine (forward_decls.ToString ());
2143 classes.Sort ();
2144 structs.Sort ();
2145 foreach (string c in classes) {
2146 header.Append ("class ");
2147 header.Append (c);
2148 header.AppendLine (";");
2150 header.AppendLine ();
2151 foreach (string s in structs) {
2152 header.Append ("struct ");
2153 header.Append (s);
2154 header.AppendLine (";");
2156 header.AppendLine ();
2157 header.AppendLine (cbinding_requisites.ToString ());
2159 header.AppendLine ();
2160 header.AppendLine ("G_BEGIN_DECLS");
2161 header.AppendLine ();
2163 impl.AppendLine ("#include <config.h>");
2164 impl.AppendLine ();
2165 impl.AppendLine ("#include <stdio.h>");
2166 impl.AppendLine ("#include <stdlib.h>");
2167 impl.AppendLine ();
2168 impl.AppendLine ("#include \"cbinding.h\"");
2169 impl.AppendLine ();
2170 headers.Sort ();
2171 foreach (string h in headers) {
2172 impl.Append ("#include \"");
2173 impl.Append (h);
2174 impl.AppendLine ("\"");
2177 foreach (MemberInfo member in methods) {
2178 MethodInfo method = (MethodInfo) member;
2180 if (!method.Header.StartsWith (dir))
2181 continue;
2183 if (last_type != method.Parent.Name) {
2184 last_type = method.Parent.Name;
2185 foreach (StringBuilder text in new StringBuilder [] {header, impl}) {
2186 text.AppendLine ("/**");
2187 text.Append (" * ");
2188 text.AppendLine (last_type);
2189 text.AppendLine (" **/");
2193 WriteHeaderMethod (method.CMethod, method, header, info);
2194 header.AppendLine ();
2196 WriteImplMethod (method.CMethod, method, impl, info);
2197 impl.AppendLine ();
2198 impl.AppendLine ();
2201 header.AppendLine ();
2202 header.AppendLine ("G_END_DECLS");
2203 header.AppendLine ();
2204 header.AppendLine ("#endif");
2206 Helper.WriteAllText (Path.Combine (dir, "cbinding.h"), header.ToString ());
2207 Helper.WriteAllText (Path.Combine (dir, "cbinding.cpp"), impl.ToString ());
2210 public static void GenerateCBindings (GlobalInfo info)
2212 string base_dir = Environment.CurrentDirectory;
2213 string plugin_dir = Path.Combine (base_dir, "plugin");
2214 string moon_dir = Path.Combine (base_dir, "src");
2216 GenerateCBindings (info, moon_dir);
2217 GenerateCBindings (info, plugin_dir);
2220 static void WriteHeaderMethod (MethodInfo cmethod, MethodInfo cppmethod, StringBuilder text, GlobalInfo info)
2222 Log.WriteLine ("Writing header: {0}::{1} (Version: '{2}', GenerateManaged: {3})",
2223 cmethod.Parent.Name, cmethod.Name,
2224 cmethod.Annotations.GetValue ("Version"),
2225 cmethod.Annotations.ContainsKey ("GenerateManaged"));
2227 if (cmethod.Annotations.ContainsKey ("GeneratePInvoke"))
2228 text.AppendLine ("/* @GeneratePInvoke */");
2229 cmethod.ReturnType.Write (text, SignatureType.NativeC, info);
2230 if (!cmethod.ReturnType.IsPointer)
2231 text.Append (" ");
2232 text.Append (cmethod.Name);
2233 cmethod.Parameters.Write (text, SignatureType.NativeC, false);
2234 text.AppendLine (";");
2237 static void WriteImplMethod (MethodInfo cmethod, MethodInfo cppmethod, StringBuilder text, GlobalInfo info)
2239 bool is_void = cmethod.ReturnType.Value == "void";
2240 bool is_ctor = cmethod.IsConstructor;
2241 bool is_static = cmethod.IsStatic;
2242 bool is_dtor = cmethod.IsDestructor;
2243 bool check_instance = !is_static && !is_ctor;
2244 bool check_error = false;
2246 foreach (ParameterInfo parameter in cmethod.Parameters) {
2247 if (parameter.ParameterType.Value == "MoonError*") {
2248 check_error = true;
2249 break;
2253 cmethod.ReturnType.Write (text, SignatureType.NativeC, info);
2254 text.AppendLine ();
2255 text.Append (cmethod.Name);
2256 cmethod.Parameters.Write (text, SignatureType.NativeC, false);
2257 text.AppendLine ("");
2258 text.AppendLine ("{");
2260 if (is_ctor) {
2261 text.Append ("\treturn new ");
2262 text.Append (cmethod.Parent.Name);
2263 cmethod.Parameters.Write (text, SignatureType.NativeC, true);
2264 text.AppendLine (";");
2265 } else if (is_dtor) {
2266 text.AppendLine ("\tdelete instance;");
2267 } else {
2268 if (check_instance) {
2269 text.AppendLine ("\tif (instance == NULL)");
2271 if (cmethod.ReturnType.Value == "void") {
2272 text.Append ("\t\treturn");
2273 } else if (cmethod.ReturnType.Value.Contains ("*")) {
2274 text.Append ("\t\treturn NULL");
2275 } else if (cmethod.ReturnType.Value == "Type::Kind") {
2276 text.Append ("\t\treturn Type::INVALID");
2277 } else if (cmethod.ReturnType.Value == "bool") {
2278 text.Append ("\t\treturn false");
2279 } else if (cmethod.ReturnType.Value == "Point") {
2280 text.Append ("\t\treturn Point (0, 0)");
2281 } else {
2282 text.AppendLine ("\t\t// Need to find a proper way to get the default value for the specified type and return that if instance is NULL.");
2283 text.Append ("\t\treturn");
2284 text.Append (" (");
2285 text.Append (cmethod.ReturnType.Value);
2286 text.Append (") 0");
2288 text.AppendLine (";");
2290 text.AppendLine ("\t");
2293 if (check_error) {
2294 text.AppendLine ("\tif (error == NULL)");
2295 text.Append ("\t\tg_warning (\"Moonlight: Called ");
2296 text.Append (cmethod.Name);
2297 text.AppendLine (" () with error == NULL.\");");
2300 text.Append ("\t");
2301 if (!is_void)
2302 text.Append ("return ");
2304 if (is_static) {
2305 text.Append (cmethod.Parent.Name);
2306 text.Append ("::");
2307 } else {
2308 text.Append ("instance->");
2309 cmethod.Parameters [0].DisableWriteOnce = true;
2311 text.Append (cppmethod.Name);
2312 cmethod.Parameters.Write (text, SignatureType.NativeC, true);
2313 text.AppendLine (";");
2316 text.AppendLine ("}");
2319 static void GenerateTypeStaticCpp (GlobalInfo all)
2321 string header;
2322 List<string> headers = new List<string> ();
2324 StringBuilder text = new StringBuilder ();
2326 Helper.WriteWarningGenerated (text);
2328 text.AppendLine ("#include <config.h>");
2329 text.AppendLine ();
2330 text.AppendLine ("#include <stdlib.h>");
2332 headers.Add ("cbinding.h");
2333 foreach (TypeInfo t in all.Children.SortedTypesByKind) {
2334 if (t.C_Constructor == string.Empty || t.C_Constructor == null || !t.GenerateCBindingCtor) {
2335 //Console.WriteLine ("{0} does not have a C ctor", t.FullName);
2336 if (t.GetTotalEventCount () == 0)
2337 continue;
2340 if (string.IsNullOrEmpty (t.Header)) {
2341 // Console.WriteLine ("{0} does not have a header", t.FullName);
2342 continue;
2345 //Console.WriteLine ("{0}'s header is {1}", t.FullName, t.Header);
2347 header = Path.GetFileName (t.Header);
2348 if (!headers.Contains (header))
2349 headers.Add (header);
2352 // Loop through all the classes and check which headers
2353 // are needed for the c constructors
2354 text.AppendLine ("");
2355 headers.Sort ();
2356 foreach (string h in headers) {
2357 text.Append ("#include \"");
2358 text.Append (h);
2359 text.AppendLine ("\"");
2361 text.AppendLine ();
2363 foreach (TypeInfo t in all.Children.SortedTypesByKind) {
2364 if (t.GetEventCount () == 0)
2365 continue;
2368 foreach (FieldInfo field in t.Events) {
2369 text.Append ("const int ");
2370 text.Append (t.Name);
2371 text.Append ("::");
2372 text.Append (field.EventName);
2373 text.Append ("Event = ");
2374 text.Append (t.GetEventId (field));
2375 text.AppendLine (";");
2379 // Create the arrays of event names for the classes which have events
2380 text.AppendLine ("");
2381 foreach (TypeInfo t in all.Children.SortedTypesByKind) {
2383 if (t.Events.Count > 0) {
2384 text.Append ("const char *");
2385 text.Append (t.KindName);
2386 text.Append ("_Events [] = { ");
2388 foreach (FieldInfo field in t.Events) {
2389 text.Append ("\"");
2390 text.Append (field.EventName);
2391 text.Append ("\", ");
2394 text.AppendLine ("NULL };");
2397 if (t.Interfaces.Count > 0) {
2398 text.Append ("const Type::Kind ");
2399 text.Append (t.KindName);
2400 text.Append ("_Interfaces[] = { ");
2402 for (int i = 0; i < t.Interfaces.Count; i ++) {
2403 text.Append ("Type::");
2404 text.Append (t.Interfaces[i].KindName);
2405 if (i < t.Interfaces.Count - 1)
2406 text.Append (", ");
2409 text.AppendLine (" };");
2413 // Create the array of type data
2414 text.AppendLine ("");
2415 text.AppendLine ("void");
2416 text.AppendLine ("Types::RegisterNativeTypes ()");
2417 text.AppendLine ("{");
2418 text.AppendLine ("\tDeployment *deployment = Deployment::GetCurrent ();");
2419 text.AppendLine ("\ttypes [(int) Type::INVALID] = new Type (deployment, Type::INVALID, Type::INVALID, false, false, NULL, 0, 0, NULL, 0, NULL, false, NULL, NULL );");
2420 foreach (TypeInfo type in all.Children.SortedTypesByKind) {
2421 MemberInfo member;
2422 TypeInfo parent = null;
2423 string events = "NULL";
2424 string interfaces = "NULL";
2426 if (!type.Annotations.ContainsKey ("IncludeInKinds"))
2427 continue;
2429 if (type.Base != null && type.Base.Value != null && all.Children.TryGetValue (type.Base.Value, out member))
2430 parent = (TypeInfo) member;
2432 if (type.Events != null && type.Events.Count != 0)
2433 events = type.KindName + "_Events";
2435 if (type.Interfaces.Count != 0)
2436 interfaces = type.KindName + "_Interfaces";
2438 text.AppendLine (string.Format (@" types [(int) {0}] = new Type (deployment, {0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}, {9}, {10}, {11}, {12});",
2439 "Type::" + type.KindName,
2440 type.KindName == "OBJECT" ? "Type::INVALID" : ("Type::" + (parent != null ? parent.KindName : "OBJECT")),
2441 type.IsValueType ? "true" : "false",
2442 type.IsInterface ? "true" : "false",
2443 "\"" + type.Name + "\"",
2444 type.GetEventCount (),
2445 type.GetTotalEventCount (),
2446 events,
2447 type.Interfaces.Count,
2448 interfaces,
2449 type.DefaultCtorVisible ? "true" : "false",
2450 (type.C_Constructor != null && type.GenerateCBindingCtor) ? string.Concat ("(create_inst_func *) ", type.C_Constructor) : "NULL",
2451 type.ContentProperty != null ? string.Concat ("\"", type.ContentProperty, "\"") : "NULL"
2456 text.AppendLine ("\ttypes [(int) Type::LASTTYPE] = new Type (deployment, Type::LASTTYPE, Type::INVALID, false, false, NULL, 0, 0, NULL, 0, NULL, false, NULL, NULL);");
2458 text.AppendLine ("}");
2460 text.AppendLine ();
2462 Helper.WriteAllText ("src/type-generated.cpp", text.ToString ());
2465 static void GenerateTypeH (GlobalInfo all)
2467 const string file = "src/type.h";
2468 StringBuilder text;
2469 string contents = File.ReadAllText (file + ".in");
2471 contents = contents.Replace ("/*DO_KINDS*/", all.Children.GetKindsForEnum ().ToString ());
2473 text = new StringBuilder ();
2475 Helper.WriteWarningGenerated (text);
2477 contents = text.ToString () + contents;
2479 Helper.WriteAllText (file, contents);
2482 static void GenerateKindCs ()
2484 const string file = "src/type.h";
2485 StringBuilder text = new StringBuilder ();
2486 string contents = File.ReadAllText (file);
2487 int a = contents.IndexOf ("// START_MANAGED_MAPPING") + "// START_MANAGED_MAPPING".Length;
2488 int b = contents.IndexOf ("// END_MANAGED_MAPPING");
2489 string values = contents.Substring (a, b - a);
2491 Helper.WriteWarningGenerated (text);
2493 text.AppendLine ("namespace Mono {");
2494 text.AppendLine ("#if NET_2_1");
2495 text.AppendLine ("\tinternal enum Kind {");
2496 text.AppendLine ("#else");
2497 text.AppendLine ("\tpublic enum Kind {");
2498 text.AppendLine ("#endif");
2499 text.AppendLine (values);
2500 text.AppendLine ("\t}");
2501 text.AppendLine ("}");
2503 string realfile = "class/System.Windows/Mono/Kind.cs".Replace ('/', Path.DirectorySeparatorChar);
2504 Helper.WriteAllText (realfile, text.ToString ());
2507 static void GenerateValueH (GlobalInfo all)
2509 const string file = "src/value.h";
2510 StringBuilder result = new StringBuilder ();
2512 Helper.WriteWarningGenerated (result);
2514 using (StreamReader reader = new StreamReader (file + ".in")) {
2515 string line;
2516 line = reader.ReadLine ();
2517 while (line != null) {
2518 if (line.Contains ("/*DO_FWD_DECLS*/")) {
2519 foreach (TypeInfo type in all.Children.SortedTypesByKind) {
2520 if (!type.Annotations.ContainsKey("IncludeInKinds") ||
2521 type.Annotations.ContainsKey("SkipValue") ||
2522 type.IsNested ||
2523 type.IsStruct)
2524 continue;
2526 if (type.IsStruct) {
2527 forward_decls.Append ("struct ");
2528 } else {
2529 forward_decls.Append ("class ");
2531 forward_decls.Append (type.Name);
2532 forward_decls.AppendLine (";");
2534 forward_decls.AppendLine ();
2535 result.Append (forward_decls.ToString ());
2536 } else if (line.Contains ("/*DO_AS*/")) {
2537 foreach (TypeInfo type in all.Children.SortedTypesByKind) {
2538 if (!type.Annotations.ContainsKey("IncludeInKinds") ||
2539 type.Annotations.ContainsKey("SkipValue") ||
2540 type.IsNested ||
2541 type.IsStruct)
2542 continue;
2544 //do_as.AppendLine (string.Format (" {1,-30} As{0} () {{ checked_get_subclass (Type::{2}, {0}) }}", type.Name, type.Name + "*", type.KindName));
2546 result.Append ('\t');
2547 result.Append (type.Name);
2548 result.Append ("*");
2549 result.Append (' ', 40 - type.Name.Length);
2550 result.Append ("As");
2551 result.Append (type.Name);
2552 result.Append (" (Types *types = NULL) { checked_get_subclass (Type::");
2553 result.Append (type.KindName);
2554 result.Append (", ");
2555 result.Append (type.Name);
2556 result.Append (") }");
2557 result.AppendLine ();
2559 result.AppendLine ();
2560 } else {
2561 result.AppendLine (line);
2563 line = reader.ReadLine ();
2567 Helper.WriteAllText (file, result.ToString ());
2570 #if false
2571 static bool IsManuallyDefined (string NativeMethods_cs, string method)
2573 if (NativeMethods_cs.Contains (" " + method + " "))
2574 return true;
2575 else if (NativeMethods_cs.Contains (" " + method + "("))
2576 return true;
2577 else if (NativeMethods_cs.Contains ("\"" + method + "\""))
2578 return true;
2579 else
2580 return false;
2582 #endif
2584 static void GeneratePInvokes (GlobalInfo all)
2586 string base_dir = Environment.CurrentDirectory;
2587 List <MethodInfo> methods = new List<MethodInfo> ();
2588 StringBuilder text = new StringBuilder ();
2589 string NativeMethods_cs;
2591 NativeMethods_cs = File.ReadAllText (Path.Combine (base_dir, "class/System.Windows/Mono/NativeMethods.cs".Replace ('/', Path.DirectorySeparatorChar)));
2593 methods = all.CPPMethodsToBind;
2595 foreach (MemberInfo info in all.Children.Values) {
2596 MethodInfo minfo = info as MethodInfo;
2597 if (minfo == null)
2598 continue;
2599 if (!minfo.Annotations.ContainsKey ("GeneratePInvoke"))
2600 continue;
2601 foreach (MethodInfo mi in methods) {
2602 if (mi.CMethod.Name == minfo.Name) {
2603 minfo = null;
2604 break;
2607 if (minfo == null)
2608 continue;
2609 //Console.WriteLine ("Added: {0} IsSrc: {1} IsPlugin: {2} Header: {3}", minfo.Name, minfo.IsSrcMember, minfo.IsPluginMember, minfo.Header);
2610 methods.Add (minfo);
2613 Helper.WriteWarningGenerated (text);
2614 text.AppendLine ("using System;");
2615 text.AppendLine ("using System.Windows;");
2616 text.AppendLine ("using System.Runtime.InteropServices;");
2617 text.AppendLine ("");
2618 text.AppendLine ("namespace Mono {");
2619 text.AppendLine ("\tinternal static partial class NativeMethods");
2620 text.AppendLine ("\t{");
2621 text.AppendLine ("\t\t/* moonplugin methods */");
2622 text.AppendLine ("\t");
2623 foreach (MethodInfo method in methods) {
2624 if (!method.IsPluginMember || !method.Annotations.ContainsKey ("GeneratePInvoke"))
2625 continue;
2626 WritePInvokeMethod (NativeMethods_cs, method, text, "moonplugin");
2627 text.AppendLine ();
2630 text.AppendLine ("\t");
2631 text.AppendLine ("\t\t/* libmoon methods */");
2632 text.AppendLine ("\t");
2633 foreach (MethodInfo method in methods) {
2634 if (!method.IsSrcMember || !method.Annotations.ContainsKey ("GeneratePInvoke"))
2635 continue;
2636 WritePInvokeMethod (NativeMethods_cs, method, text, "moon");
2637 text.AppendLine ();
2639 text.AppendLine ("\t}");
2640 text.AppendLine ("}");
2642 Helper.WriteAllText (Path.Combine (base_dir, "class/System.Windows/Mono/GeneratedPInvokes.cs".Replace ('/', Path.DirectorySeparatorChar)), text.ToString ());
2645 static void WritePInvokeMethod (string NativeMethods_cs, MethodInfo method, StringBuilder text, string library)
2647 bool marshal_string_returntype = false;
2648 bool marshal_moonerror = false;
2649 bool generate_wrapper = false;
2650 // bool is_manually_defined;
2651 bool comment_out;
2652 bool is_void = false;
2653 bool contains_unknown_types;
2654 string name;
2655 string managed_name;
2656 string tabs;
2657 TypeReference returntype;
2658 MethodInfo cmethod = method.CMethod;
2659 ParameterInfo error_parameter = null;
2661 if (method.ReturnType == null)
2662 throw new Exception (string.Format ("Method {0} in type {1} does not have a return type.", method.Name, method.Parent.Name));
2664 if (method.ReturnType.Value == "char*") {
2665 marshal_string_returntype = true;
2666 generate_wrapper = true;
2667 } else if (method.ReturnType.Value == "void") {
2668 is_void = true;
2671 // Check for parameters we can automatically generate code for.
2672 foreach (ParameterInfo parameter in cmethod.Parameters) {
2673 if (parameter.Name == "error" && parameter.ParameterType.Value == "MoonError*") {
2674 marshal_moonerror = true;
2675 generate_wrapper = true;
2676 error_parameter = parameter;
2680 name = method.CMethod.Name;
2681 managed_name = name;
2682 if (marshal_moonerror)
2683 managed_name = managed_name.Replace ("_with_error", "");
2685 returntype = method.ReturnType;
2686 // is_manually_defined = IsManuallyDefined (NativeMethods_cs, managed_name);
2687 contains_unknown_types = method.ContainsUnknownTypes;
2688 comment_out = contains_unknown_types;
2689 tabs = comment_out ? "\t\t// " : "\t\t";
2691 // if (is_manually_defined)
2692 // text.AppendLine ("\t\t// NOTE: There is a method in NativeMethod.cs with the same name.");
2694 if (contains_unknown_types)
2695 text.AppendLine ("\t\t// This method contains types the generator didn't know about. Fix the generator (find the method 'GetManagedType' in TypeReference.cs and add the missing case) and try again.");
2697 text.Append (tabs);
2698 text.Append ("[DllImport (\"");
2699 text.Append (library);
2700 if (generate_wrapper) {
2701 text.Append ("\", EntryPoint=\"");
2702 text.Append (name);
2704 text.AppendLine ("\")]");
2706 if (method.ReturnType.Value == "bool") {
2707 text.Append (tabs);
2708 text.AppendLine ("[return: MarshalAs (UnmanagedType.U1)]");
2709 } else if (method.ReturnType.Value == "gboolean") {
2710 text.Append (tabs);
2711 text.AppendLine ("[return: MarshalAs (UnmanagedType.Bool)]");
2714 // Always output the native signature too, makes it easier to check if the generation is wrong.
2715 text.Append ("\t\t// ");
2716 cmethod.WriteFormatted (text);
2717 text.AppendLine ();
2719 text.Append (tabs);
2720 text.Append (generate_wrapper ? "private " : "public ");
2721 text.Append ("extern static ");
2722 if (marshal_string_returntype)
2723 text.Append ("IntPtr");
2724 else
2725 returntype.Write (text, SignatureType.PInvoke, null);
2726 text.Append (" ");
2727 text.Append (name);
2728 if (generate_wrapper)
2729 text.Append ("_");
2730 cmethod.Parameters.Write (text, SignatureType.PInvoke, false);
2731 text.AppendLine (";");
2733 if (generate_wrapper) {
2734 text.Append (tabs);
2735 text.Append ("public static ");
2736 returntype.Write (text, SignatureType.Managed, null);
2737 text.Append (" ");
2738 text.Append (managed_name);
2740 foreach (ParameterInfo parameter in cmethod.Parameters)
2741 parameter.DisableWriteOnce = parameter.ManagedWrapperCode != null;
2743 if (error_parameter != null)
2744 error_parameter.DisableWriteOnce = true;
2746 cmethod.Parameters.Write (text, SignatureType.Managed, false);
2747 text.AppendLine ();
2749 text.Append (tabs);
2750 text.Append ("{");
2751 text.AppendLine ();
2753 text.Append (tabs);
2755 if (marshal_string_returntype) {
2756 text.AppendLine ("\tIntPtr result;");
2757 } else if (!is_void) {
2758 text.Append ("\t");
2759 returntype.Write (text, SignatureType.Managed, null);
2760 text.AppendLine (" result;");
2763 if (marshal_moonerror) {
2764 text.Append (tabs);
2765 text.AppendLine ("\tMoonError error;");
2768 text.Append (tabs);
2769 text.Append ("\t");
2770 if (!is_void)
2771 text.Append ("result = ");
2773 text.Append (cmethod.Name);
2774 text.Append ("_");
2775 cmethod.Parameters.Write (text, SignatureType.Managed, true);
2777 text.AppendLine (";");
2779 if (marshal_moonerror) {
2780 text.Append (tabs);
2781 text.AppendLine ("\tif (error.Number != 0)");
2783 text.Append (tabs);
2784 text.AppendLine ("\t\tthrow CreateManagedException (error);");
2787 if (marshal_string_returntype) {
2788 text.Append (tabs);
2789 text.AppendLine ("\tif (result == IntPtr.Zero)");
2790 text.Append (tabs);
2791 text.AppendLine ("\t\treturn null;");
2792 text.Append (tabs);
2793 text.AppendLine ("\tstring s = Marshal.PtrToStringAnsi (result);\t// *copy* unmanaged string");
2794 text.Append (tabs);
2795 if (!method.ReturnType.IsConst) {
2796 text.AppendLine ("\tMarshal.FreeHGlobal (result);\t\t\t// g_free the unmanaged string");
2797 text.Append (tabs);
2799 text.AppendLine ("\treturn s;");
2800 } else if (!is_void) {
2801 text.Append (tabs);
2802 text.AppendLine ("\treturn result;");
2805 text.Append (tabs);
2806 text.Append ("}");
2807 text.AppendLine ();
2812 static void RemoveExcludedSrcFiles (string srcdir, List<string> files)
2814 files.Remove (Path.Combine (srcdir, "cbinding.h"));
2815 files.Remove (Path.Combine (srcdir, "ptr.h"));