* Syscall.cs: Make all fork(2) and exec(2) functions `private`. It
[mono.git] / mcs / class / Mono.Posix / Mono.Unix / make-map.cs
1 //
2 // MakeMap.cs: Builds a C map of constants defined on C# land
3 //
4 // Authors:
5 //  Miguel de Icaza (miguel@novell.com)
6 //  Jonathan Pryor (jonpryor@vt.edu)
7 //
8 // (C) 2003 Novell, Inc.
9 // (C) 2004 Jonathan Pryor
10 //
11
12 //
13 // Permission is hereby granted, free of charge, to any person obtaining
14 // a copy of this software and associated documentation files (the
15 // "Software"), to deal in the Software without restriction, including
16 // without limitation the rights to use, copy, modify, merge, publish,
17 // distribute, sublicense, and/or sell copies of the Software, and to
18 // permit persons to whom the Software is furnished to do so, subject to
19 // the following conditions:
20 // 
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
23 // 
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 //
32 using System;
33 using System.IO;
34 using System.Reflection;
35
36 delegate void CreateFileHandler (string assembly_name, string file_prefix);
37 delegate void AssemblyAttributesHandler (Assembly assembly);
38 delegate void TypeHandler (Type t, string ns, string fn, string etype, bool bits);
39 delegate void CloseFileHandler (string file_prefix);
40
41 class MakeMap {
42
43         public static int Main (string [] args)
44         {
45                 FileGenerator[] generators = new FileGenerator[]{
46                         new HeaderFileGenerator (),
47                         new SourceFileGenerator (),
48                         new WrapperFileGenerator ()
49                 };
50
51                 MakeMap composite = new MakeMap ();
52                 foreach (FileGenerator g in generators) {
53                         composite.FileCreators += new CreateFileHandler (g.CreateFile);
54                         composite.AssemblyAttributesHandler += 
55                                 new AssemblyAttributesHandler (g.WriteAssemblyAttributes);
56                         composite.TypeHandler += new TypeHandler (g.WriteType);
57                         composite.FileClosers += new CloseFileHandler (g.CloseFile);
58                 }
59
60                 return composite.Run (args);
61         }
62
63         event CreateFileHandler FileCreators;
64         event AssemblyAttributesHandler AssemblyAttributesHandler;
65         event TypeHandler TypeHandler;
66         event CloseFileHandler FileClosers;
67
68         int Run (string[] args)
69         {
70                 if (args.Length != 2){
71                         Console.WriteLine ("Usage is: make-map assembly output");
72                         return 1;
73                 }
74                 
75                 string assembly_name = args[0];
76                 string output = args[1];
77
78                 FileCreators (assembly_name, output);
79
80                 Assembly assembly = Assembly.LoadFrom (assembly_name);
81                 AssemblyAttributesHandler (assembly);
82                 
83                 Type [] exported_types = assembly.GetTypes ();
84                         
85                 foreach (Type t in exported_types) {
86                         bool bits;
87                         if (!CanMapType (t, out bits))
88                                 continue;
89
90                         string fn = t.FullName.Replace (".", "_");
91                         fn = fn.Replace ("Mono_Unix", "Mono_Posix");
92                         string ns = t.Namespace.Replace (".", "_");
93                         ns = ns.Replace ("Mono_Unix", "Mono_Posix");
94                         string etype = GetNativeType (t);
95
96                         TypeHandler (t, ns, fn, etype, bits);
97                 }
98                 FileClosers (output);
99
100                 return 0;
101         }
102
103         static bool CanMapType (Type t, out bool bits)
104         {
105                 object [] attributes = t.GetCustomAttributes (false);
106                 bool map = false;
107                 bits = false;
108                 
109                 foreach (object attr in attributes) {
110                         if (attr.GetType ().Name == "MapAttribute")
111                                 map = true;
112                         if (attr.GetType ().Name == "FlagsAttribute")
113                                 bits = true;
114                 }
115                 return map;
116         }
117
118         static string GetNativeType (Type t)
119         {
120                 string ut = Enum.GetUnderlyingType (t).Name;
121                 switch (ut) {
122                         case "Byte":   return "unsigned char";
123                         case "SByte":  return "signed char";
124                         case "Int16":  return "short";
125                         case "UInt16": return "unsigned short";
126                         case "Int32":  return "int";
127                         case "UInt32": return "unsigned int";
128                         case "Int64":  return "gint64";
129                         case "UInt64": return "guint64";
130                 }
131                 return "int /* **unknown** " + ut + " */";
132         }
133 }
134
135 abstract class FileGenerator {
136         public abstract void CreateFile (string assembly_name, string file_prefix);
137
138         public virtual void WriteAssemblyAttributes (Assembly assembly)
139         {
140         }
141
142         public abstract void WriteType (Type t, string ns, string fn, string etype, bool bits);
143         public abstract void CloseFile (string file_prefix);
144
145         protected static void WriteHeader (StreamWriter s, string assembly)
146         {
147                 s.WriteLine (
148                         "/*\n" +
149                         " * This file was automatically generated by make-map from {0}.\n" +
150                         " *\n" +
151                         " * DO NOT MODIFY.\n" +
152                         " */\n" +
153                         "#include <config.h>\n",
154                         assembly);
155         }
156 }
157
158 class HeaderFileGenerator : FileGenerator {
159         StreamWriter sh;
160
161         public override void CreateFile (string assembly_name, string file_prefix)
162         {
163                 sh = File.CreateText (file_prefix + ".h");
164                 WriteHeader (sh, assembly_name);
165                 sh.WriteLine ("#ifndef INC_Mono_Posix_" + file_prefix + "_H");
166                 sh.WriteLine ("#define INC_Mono_Posix_" + file_prefix + "_H\n");
167                 sh.WriteLine ("#include <glib/gtypes.h>\n");
168                 sh.WriteLine ("G_BEGIN_DECLS\n");
169         }
170
171         public override void WriteType (Type t, string ns, string fn, string etype, bool bits)
172         {
173                 WriteLiteralValues (sh, t, fn);
174                 sh.WriteLine ("int {1}_From{2} ({0} x, {0} *r);", etype, ns, t.Name);
175                 sh.WriteLine ("int {1}_To{2} ({0} x, {0} *r);", etype, ns, t.Name);
176                 sh.WriteLine ();
177         }
178
179         static void WriteLiteralValues (StreamWriter sh, Type t, string n)
180         {
181                 object inst = Activator.CreateInstance (t);
182                 foreach (FieldInfo fi in t.GetFields ()){
183                         if (!fi.IsLiteral)
184                                 continue;
185                         sh.WriteLine ("#define {0}_{1} 0x{2:x}", n, fi.Name, fi.GetValue (inst));
186                 }
187         }
188
189         public override void CloseFile (string file_prefix)
190         {
191                 sh.WriteLine ("G_END_DECLS\n");
192                 sh.WriteLine ("#endif /* ndef INC_Mono_Posix_" + file_prefix + "_H */\n");
193                 sh.Close ();
194         }
195 }
196
197 class SourceFileGenerator : FileGenerator {
198         StreamWriter sc;
199
200         public override void CreateFile (string assembly_name, string file_prefix)
201         {
202                 sc = File.CreateText (file_prefix + ".c");
203                 WriteHeader (sc, assembly_name);
204
205                 if (file_prefix.IndexOf ("/") != -1)
206                         file_prefix = file_prefix.Substring (file_prefix.IndexOf ("/") + 1);
207                 sc.WriteLine ("#include \"{0}.h\"", file_prefix);
208                 sc.WriteLine ();
209         }
210
211         public override void WriteAssemblyAttributes (Assembly assembly)
212         {
213                 object [] x = assembly.GetCustomAttributes (false);
214                 Console.WriteLine ("Got: " + x.Length);
215                 foreach (object aattr in assembly.GetCustomAttributes (false)) {
216                         Console.WriteLine ("Got: " + aattr.GetType ().Name);
217                         if (aattr.GetType ().Name == "IncludeAttribute"){
218                                 WriteDefines (sc, aattr);
219                                 WriteIncludes (sc, aattr);
220                         }
221                 }
222         }
223
224         static void WriteDefines (TextWriter writer, object o)
225         {
226                 PropertyInfo prop = o.GetType ().GetProperty ("Defines");
227                 if (prop == null)
228                         throw new Exception ("Cannot find 'Defines' property");
229
230                 MethodInfo method = prop.GetGetMethod ();
231                 string [] defines = (string []) method.Invoke (o, null);
232                 foreach (string def in defines) {
233                         writer.WriteLine ("#ifndef {0}", def);
234                         writer.WriteLine ("#define {0}", def);
235                         writer.WriteLine ("#endif /* ndef {0} */", def);
236                 }
237         }
238
239         static void WriteIncludes (TextWriter writer, object o)
240         {
241                 PropertyInfo prop = o.GetType ().GetProperty ("Includes");
242                 if (prop == null)
243                         throw new Exception ("Cannot find 'Includes' property");
244
245                 MethodInfo method = prop.GetGetMethod ();
246                 string [] includes = (string []) method.Invoke (o, null);
247                 foreach (string inc in includes){
248                         if (inc [0] == '>'){
249                                 string i = inc.Substring (1);
250                                 writer.WriteLine ("#ifdef HAVE_" + (i.ToUpper ().Replace ("/", "_").Replace (".", "_")));
251                                 writer.WriteLine ("#include <{0}>", i);
252                                 writer.WriteLine ("#endif");
253                         } else 
254                                 writer.WriteLine ("#include <{0}>", inc);
255                 }
256                 writer.WriteLine ();
257         }
258
259         public override void WriteType (Type t, string ns, string fn, string etype, bool bits)
260         {
261                 WriteFromManagedType (t, ns, fn, etype, bits);
262                 WriteToManagedType (t, ns, fn, etype, bits);
263         }
264
265         private void WriteFromManagedType (Type t, string ns, string fn, string etype, bool bits)
266         {
267                 sc.WriteLine ("int {1}_From{2} ({0} x, {0} *r)", etype, ns, t.Name);
268                 sc.WriteLine ("{");
269                 sc.WriteLine ("\t*r = 0;");
270                 // For many values, 0 is a valid value, but doesn't have it's own symbol.
271                 // Examples: Error (0 means "no error"), WaitOptions (0 means "no options").
272                 // Make 0 valid for all conversions.
273                 sc.WriteLine ("\tif (x == 0)\n\t\treturn 0;");
274                 foreach (FieldInfo fi in t.GetFields ()) {
275                         if (!fi.IsLiteral)
276                                 continue;
277                         if (bits)
278                                 // properly handle case where [Flags] enumeration has helper
279                                 // synonyms.  e.g. DEFFILEMODE and ACCESSPERMS for mode_t.
280                                 sc.WriteLine ("\tif ((x & {0}_{1}) == {0}_{1})", fn, fi.Name);
281                         else
282                                 sc.WriteLine ("\tif (x == {0}_{1})", fn, fi.Name);
283                         sc.WriteLine ("#ifdef {0}", fi.Name);
284                         if (bits)
285                                 sc.WriteLine ("\t\t*r |= {1};", fn, fi.Name);
286                         else
287                                 sc.WriteLine ("\t\t{{*r = {1}; return 0;}}", fn, fi.Name);
288                         sc.WriteLine ("#else /* def {0} */\n\t\t{{errno = EINVAL; return -1;}}", fi.Name);
289                         sc.WriteLine ("#endif /* ndef {0} */", fi.Name);
290                 }
291                 if (bits)
292                         sc.WriteLine ("\treturn 0;");
293                 else
294                         sc.WriteLine ("\terrno = EINVAL; return -1;"); // return error if not matched
295                 sc.WriteLine ("}\n");
296         }
297
298         private void WriteToManagedType (Type t, string ns, string fn, string etype, bool bits)
299         {
300                 sc.WriteLine ("int {1}_To{2} ({0} x, {0} *r)", etype, ns, t.Name);
301                 sc.WriteLine ("{");
302                 sc.WriteLine ("\t*r = 0;", etype);
303                 // For many values, 0 is a valid value, but doesn't have it's own symbol.
304                 // Examples: Error (0 means "no error"), WaitOptions (0 means "no options").
305                 // Make 0 valid for all conversions.
306                 sc.WriteLine ("\tif (x == 0)\n\t\treturn 0;");
307                 foreach (FieldInfo fi in t.GetFields ()) {
308                         if (!fi.IsLiteral)
309                                 continue;
310                         sc.WriteLine ("#ifdef {0}", fi.Name);
311                         if (bits)
312                                 // properly handle case where [Flags] enumeration has helper
313                                 // synonyms.  e.g. DEFFILEMODE and ACCESSPERMS for mode_t.
314                                 sc.WriteLine ("\tif ((x & {1}) == {1})\n\t\t*r |= {0}_{1};", fn, fi.Name);
315                         else
316                                 sc.WriteLine ("\tif (x == {1})\n\t\t{{*r = {0}_{1}; return 0;}}", fn, fi.Name);
317                         sc.WriteLine ("#endif /* ndef {0} */", fi.Name);
318                 }
319                 if (bits)
320                         sc.WriteLine ("\treturn 0;");
321                 else
322                         sc.WriteLine ("\terrno = EINVAL; return -1;");
323                 sc.WriteLine ("}\n");
324         }
325
326         public override void CloseFile (string file_prefix)
327         {
328                 sc.Close ();
329         }
330 }
331
332 class WrapperFileGenerator : FileGenerator {
333         StreamWriter scs;
334
335         public override void CreateFile (string assembly_name, string file_prefix)
336         {
337                 scs = File.CreateText (file_prefix + ".cs");
338                 WriteHeader (scs, assembly_name);
339                 scs.WriteLine ("using System;");
340                 scs.WriteLine ("using System.Runtime.InteropServices;");
341                 scs.WriteLine ("using Mono.Posix;\n");
342                 scs.WriteLine ("namespace Mono.Posix {\n");
343                 scs.WriteLine ("\tpublic sealed /* static */ class PosixConvert");
344                 scs.WriteLine ("\t{");
345                 scs.WriteLine ("\t\tprivate PosixConvert () {}\n");
346                 scs.WriteLine ("\t\tprivate const string LIB = \"MonoPosixHelper\";\n");
347                 scs.WriteLine ("\t\tprivate static void ThrowArgumentException (object value)");
348                 scs.WriteLine ("\t\t{");
349                 scs.WriteLine ("\t\t\tthrow new ArgumentOutOfRangeException (\"value\", value,");
350                 scs.WriteLine ("\t\t\t\tLocale.GetText (\"Current platform doesn't support this value.\"));");
351                 scs.WriteLine ("\t\t}\n");
352         }
353
354         public override void WriteType (Type t, string ns, string fn, string etype, bool bits)
355         {
356                 string mtype = Enum.GetUnderlyingType(t).Name;
357                 scs.WriteLine ("\t\t[DllImport (LIB, " + 
358                         "EntryPoint=\"{0}_From{1}\")]\n" +
359                         "\t\tprivate static extern int From{1} ({1} value, out {2} rval);\n",
360                         ns, t.Name, mtype);
361                 scs.WriteLine ("\t\tpublic static bool TryFrom{1} ({1} value, out {2} rval)\n" +
362                         "\t\t{{\n" +
363                         "\t\t\treturn From{1} (value, out rval) == 0;\n" +
364                         "\t\t}}\n", ns, t.Name, mtype);
365                 scs.WriteLine ("\t\tpublic static {0} From{1} ({1} value)", mtype, t.Name);
366                 scs.WriteLine ("\t\t{");
367                 scs.WriteLine ("\t\t\t{0} rval;", mtype);
368                 scs.WriteLine ("\t\t\tif (From{0} (value, out rval) == -1)\n" + 
369                                 "\t\t\t\tThrowArgumentException (value);", t.Name);
370                 scs.WriteLine ("\t\t\treturn rval;");
371                 scs.WriteLine ("\t\t}\n");
372                 scs.WriteLine ("\t\t[DllImport (LIB, " + 
373                         "EntryPoint=\"{0}_To{1}\")]\n" +
374                         "\t\tprivate static extern int To{1} ({2} value, out {1} rval);\n",
375                         ns, t.Name, mtype);
376                 scs.WriteLine ("\t\tpublic static bool TryTo{1} ({0} value, out {1} rval)\n" +
377                         "\t\t{{\n" +
378                         "\t\t\treturn To{1} (value, out rval) == 0;\n" +
379                         "\t\t}}\n", mtype, t.Name);
380                 scs.WriteLine ("\t\tpublic static {1} To{1} ({0} value)", mtype, t.Name);
381                 scs.WriteLine ("\t\t{");
382                 scs.WriteLine ("\t\t\t{0} rval;", t.Name);
383                 scs.WriteLine ("\t\t\tif (To{0} (value, out rval) == -1)\n" + 
384                                 "\t\t\t\tThrowArgumentException (value);", t.Name);
385                 scs.WriteLine ("\t\t\treturn rval;");
386                 scs.WriteLine ("\t\t}\n");
387         }
388
389         public override void CloseFile (string file_prefix)
390         {
391                 scs.WriteLine ("\t}");
392                 scs.WriteLine ("}\n");
393                 scs.Close ();
394         }
395 }
396
397 // vim: noexpandtab