* DiagnosticsConfigurationHandler.cs: Make DiagnosticsConfiguration.Settings
[mono.git] / mcs / bmcs / driver.cs
1 //
2 // driver.cs: The compiler command line driver.
3 //
4 // Author: Miguel de Icaza (miguel@gnu.org)
5 //
6 // Licensed under the terms of the GNU GPL
7 //
8 // (C) 2001, 2002, 2003 Ximian, Inc (http://www.ximian.com)
9 // (C) 2004 Novell, Inc
10 //
11
12 namespace Mono.CSharp
13 {
14         using System;
15         using System.Reflection;
16         using System.Reflection.Emit;
17         using System.Collections;
18         using System.Diagnostics;
19         using System.IO;
20         using System.Text;
21         using System.Globalization;
22         using System.Xml;
23         using System.Diagnostics;
24
25         public enum Target {
26                 Library, Exe, Module, WinExe
27         };
28         
29         /// <summary>
30         ///    The compiler driver.
31         /// </summary>
32         public class Driver
33         {
34                 
35                 //
36                 // Assemblies references to be linked.   Initialized with
37                 // mscorlib.dll here.
38                 static ArrayList references;
39
40                 //
41                 // If any of these fail, we ignore the problem.  This is so
42                 // that we can list all the assemblies in Windows and not fail
43                 // if they are missing on Linux.
44                 //
45                 static ArrayList soft_references;
46
47                 //
48                 // Modules to be linked
49                 //
50                 static ArrayList modules;
51
52                 // Lookup paths
53                 static ArrayList link_paths;
54
55                 // Whether we want to only run the tokenizer
56                 static bool tokenize = false;
57                 
58                 static string first_source;
59
60                 static bool want_debugging_support = false;
61
62                 static bool parse_only = false;
63                 static bool timestamps = false;
64                 static bool pause = false;
65                 static bool show_counters = false;
66                 public static bool parser_verbose = false;
67                 
68                 //
69                 // Whether to load the initial config file (what CSC.RSP has by default)
70                 // 
71                 static bool load_default_config = true;
72
73                 static Hashtable response_file_list;
74
75                 //
76                 // A list of resource files
77                 //
78                 static ArrayList resources;
79                 static ArrayList embedded_resources;
80                 static string win32ResourceFile;
81                 static string win32IconFile;
82                 
83                 //
84                 // An array of the defines from the command line
85                 //
86                 static ArrayList defines;
87
88                 //
89                 // Output file
90                 //
91                 static string output_file = null;
92
93                 //
94                 // Last time we took the time
95                 //
96                 static DateTime last_time, first_time;
97
98                 //
99                 // Encoding: ISO-Latin1 is 28591
100                 //
101                 static Encoding encoding;
102
103                 //
104                 // Whether the user has specified a different encoder manually
105                 //
106                 static bool using_default_encoder = true;
107
108                 public static void ShowTime (string msg)
109                 {
110                         if (!timestamps)
111                                 return;
112
113                         DateTime now = DateTime.Now;
114                         TimeSpan span = now - last_time;
115                         last_time = now;
116
117                         Console.WriteLine (
118                                 "[{0:00}:{1:000}] {2}",
119                                 (int) span.TotalSeconds, span.Milliseconds, msg);
120                 }
121
122                 public static void ShowTotalTime (string msg)
123                 {
124                         if (!timestamps)
125                                 return;
126
127                         DateTime now = DateTime.Now;
128                         TimeSpan span = now - first_time;
129                         last_time = now;
130
131                         Console.WriteLine (
132                                 "[{0:00}:{1:000}] {2}",
133                                 (int) span.TotalSeconds, span.Milliseconds, msg);
134                 }              
135                
136                 static void tokenize_file (SourceFile file)
137                 {
138                         Stream input;
139
140                         try {
141                                 input = File.OpenRead (file.Name);
142                         } catch {
143                                 Report.Error (2001, "Source file '" + file.Name + "' could not be opened");
144                                 return;
145                         }
146
147                         using (input){
148                                 SeekableStreamReader reader = new SeekableStreamReader (input, encoding, using_default_encoder);
149                                 Tokenizer lexer = new Tokenizer (reader, file, defines);
150                                 int token, tokens = 0, errors = 0;
151
152                                 while ((token = lexer.token ()) != Token.EOF){
153                                         tokens++;
154                                         if (token == Token.ERROR)
155                                                 errors++;
156                                 }
157                                 Console.WriteLine ("Tokenized: " + tokens + " found " + errors + " errors");
158                         }
159                         
160                         return;
161                 }
162
163                 // MonoTODO("Change error code for aborted compilation to something reasonable")]               
164                 static void parse (SourceFile file)
165                 {
166                         CSharpParser parser;
167                         Stream input;
168
169                         try {
170                                 input = File.OpenRead (file.Name);
171                         } catch {
172                                 Report.Error (2001, "Source file '" + file.Name + "' could not be opened");
173                                 return;
174                         }
175
176                         SeekableStreamReader reader = new SeekableStreamReader (input, encoding, using_default_encoder);
177                                 
178                         parser = new CSharpParser (reader, file, defines);
179                         try {
180                                 parser.parse ();
181                         } catch (Exception ex) {
182                                 Report.Error(666, "Compilation aborted: " + ex);
183                         } finally {
184                                 input.Close ();
185                         }
186                 }
187                 
188                 static void OtherFlags ()
189                 {
190                         Console.WriteLine (
191                                 "Other flags in the compiler\n" +
192                                 "   --fatal            Makes errors fatal\n" +
193                                 "   --parse            Only parses the source file\n" +
194                                 "   --stacktrace       Shows stack trace at error location\n" +
195                                 "   --timestamp        Displays time stamps of various compiler events\n" +
196                                 "   -2                 Enables experimental C# features\n" +
197                                 "   -v                 Verbose parsing (for debugging the parser)\n" + 
198                                 "   --mcs-debug X      Sets MCS debugging level to X\n");
199                 }
200                 
201                 static void Usage ()
202                 {
203                         Console.WriteLine (
204                                 "Mono C# compiler, (C) 2001 - 2003 Ximian, Inc.\n" +
205                                 "mcs [options] source-files\n" +
206                                 "   --about            About the Mono C# compiler\n" +
207                                 "   -addmodule:MODULE  Adds the module to the generated assembly\n" + 
208                                 "   -checked[+|-]      Set default context to checked\n" +
209                                 "   -codepage:ID       Sets code page to the one in ID\n" +
210                                 "                      (number, `utf8' or `reset')\n" +
211                                 "   -clscheck[+|-]     Disables CLS Compliance verifications" + Environment.NewLine +
212                                 "   -define:S1[;S2]    Defines one or more symbols (short: /d:)\n" +
213                                 "   -debug[+|-]        Generate debugging information\n" + 
214                                 "   -delaysign[+|-]    Only insert the public key into the assembly (no signing)\n" +
215                                 "   -doc:FILE          XML Documentation file to generate\n" + 
216                                 "   -g                 Generate debugging information\n" +
217                                 "   -keycontainer:NAME The key pair container used to strongname the assembly\n" +
218                                 "   -keyfile:FILE      The strongname key file used to strongname the assembly\n" +
219                                 "   -langversion:TEXT  Specifies language version modes: ISO-1 or Default" + Environment.NewLine +
220                                 "   -lib:PATH1,PATH2   Adds the paths to the assembly link path\n" +
221                                 "   -main:class        Specified the class that contains the entry point\n" +
222                                 "   -noconfig[+|-]     Disables implicit references to assemblies\n" +
223                                 "   -nostdlib[+|-]     Does not load core libraries\n" +
224                                 "   -nowarn:W1[,W2]    Disables one or more warnings\n" + 
225                                 "   -out:FNAME         Specifies output file\n" +
226                                 "   -doc:XMLFILE         Generates xml documentation into specified file\n" +
227                                 "   -pkg:P1[,Pn]       References packages P1..Pn\n" + 
228                                 "   --expect-error X   Expect that error X will be encountered\n" +
229                                 "   -recurse:SPEC      Recursively compiles the files in SPEC ([dir]/file)\n" + 
230                                 "   -reference:ASS     References the specified assembly (-r:ASS)\n" +
231                                 "   -target:KIND       Specifies the target (KIND is one of: exe, winexe,\n" +
232                                 "                      library, module), (short: /t:)\n" +
233                                 "   -unsafe[+|-]       Allows unsafe code\n" +
234                                 "   -warnaserror[+|-]  Treat warnings as errors\n" +
235                                 "   -warn:LEVEL        Sets warning level (the highest is 4, the default is 2)\n" +
236                                 "   -help2             Show other help flags\n" + 
237                                 "\n" +
238                                 "Resources:\n" +
239                                 "   -linkresource:FILE[,ID] Links FILE as a resource\n" +
240                                 "   -resource:FILE[,ID]     Embed FILE as a resource\n" +
241                                 "   -win32res:FILE          Specifies Win32 resource file (.res)\n" +
242                                 "   -win32icon:FILE         Use this icon for the output\n" +
243                                 "   @file              Read response file for more options\n\n" +
244                                 "Options can be of the form -option or /option");
245                 }
246
247                 static void TargetUsage ()
248                 {
249                         Report.Error (2019, "Valid options for -target: are exe, winexe, library or module");
250                 }
251                 
252                 static void About ()
253                 {
254                         Console.WriteLine (
255                                 "The Mono C# compiler is (C) 2001, 2002, 2003 Ximian, Inc.\n\n" +
256                                 "The compiler source code is released under the terms of the GNU GPL\n\n" +
257
258                                 "For more information on Mono, visit the project Web site\n" +
259                                 "   http://www.go-mono.com\n\n" +
260
261                                 "The compiler was written by Miguel de Icaza, Ravi Pratap, Martin Baulig and Marek Safar");
262                         Environment.Exit (0);
263                 }
264
265                 public static int counter1, counter2;
266                 
267                 public static int Main (string[] args)
268                 {
269                         RootContext.Version = LanguageVersion.Default;
270                         bool ok = MainDriver (args);
271                         
272                         if (ok && Report.Errors == 0) {
273                                 Console.Write("Compilation succeeded");
274                                 if (Report.Warnings > 0) {
275                                         Console.Write(" - {0} warning(s)", Report.Warnings);
276                                 }
277                                 Console.WriteLine();
278                                 if (show_counters){
279                                         Console.WriteLine ("Counter1: " + counter1);
280                                         Console.WriteLine ("Counter2: " + counter2);
281                                 }
282                                 if (pause)
283                                         Console.ReadLine ();
284                                 return 0;
285                         } else {
286                                 Console.WriteLine("Compilation failed: {0} error(s), {1} warnings",
287                                         Report.Errors, Report.Warnings);
288                                 return 1;
289                         }
290                 }
291
292                 static public void LoadAssembly (string assembly, bool soft)
293                 {
294                         Assembly a;
295                         string total_log = "";
296
297                         try {
298                                 char[] path_chars = { '/', '\\' };
299
300                                 if (assembly.IndexOfAny (path_chars) != -1) {
301                                         a = Assembly.LoadFrom (assembly);
302                                 } else {
303                                         string ass = assembly;
304                                         if (ass.EndsWith (".dll"))
305                                                 ass = assembly.Substring (0, assembly.Length - 4);
306                                         a = Assembly.Load (ass);
307                                 }
308                                 TypeManager.AddAssembly (a);
309
310                         } catch (FileNotFoundException){
311                                 foreach (string dir in link_paths){
312                                         string full_path = Path.Combine (dir, assembly);
313                                         if (!assembly.EndsWith (".dll"))
314                                                 full_path += ".dll";
315
316                                         try {
317                                                 a = Assembly.LoadFrom (full_path);
318                                                 TypeManager.AddAssembly (a);
319                                                 return;
320                                         } catch (FileNotFoundException ff) {
321                                                 total_log += ff.FusionLog;
322                                                 continue;
323                                         }
324                                 }
325                                 if (!soft) {
326                                         Report.Error (6, "Cannot find assembly `" + assembly + "'" );
327                                         Console.WriteLine ("Log: \n" + total_log);
328                                 }
329                         } catch (BadImageFormatException f) {
330                                 Report.Error(6, "Cannot load assembly (bad file format)" + f.FusionLog);
331                         } catch (FileLoadException f){
332                                 Report.Error(6, "Cannot load assembly " + f.FusionLog);
333                         } catch (ArgumentNullException){
334                                 Report.Error(6, "Cannot load assembly (null argument)");
335                         }
336                 }
337
338                 static public void LoadModule (MethodInfo adder_method, string module)
339                 {
340                         Module m;
341                         string total_log = "";
342
343                         try {
344                                 try {
345                                         m = (Module)adder_method.Invoke (CodeGen.Assembly.Builder, new object [] { module });
346                                 }
347                                 catch (TargetInvocationException ex) {
348                                         throw ex.InnerException;
349                                 }
350                                 TypeManager.AddModule (m);
351
352                         } 
353                         catch (FileNotFoundException){
354                                 foreach (string dir in link_paths){
355                                         string full_path = Path.Combine (dir, module);
356                                         if (!module.EndsWith (".netmodule"))
357                                                 full_path += ".netmodule";
358
359                                         try {
360                                                 try {
361                                                         m = (Module)adder_method.Invoke (CodeGen.Assembly.Builder, new object [] { full_path });
362                                                 }
363                                                 catch (TargetInvocationException ex) {
364                                                         throw ex.InnerException;
365                                                 }
366                                                 TypeManager.AddModule (m);
367                                                 return;
368                                         } catch (FileNotFoundException ff) {
369                                                 total_log += ff.FusionLog;
370                                                 continue;
371                                         }
372                                 }
373                                 Report.Error (6, "Cannot find module `" + module + "'" );
374                                 Console.WriteLine ("Log: \n" + total_log);
375                         } catch (BadImageFormatException f) {
376                                 Report.Error(6, "Cannot load module (bad file format)" + f.FusionLog);
377                         } catch (FileLoadException f){
378                                 Report.Error(6, "Cannot load module " + f.FusionLog);
379                         } catch (ArgumentNullException){
380                                 Report.Error(6, "Cannot load module (null argument)");
381                         }
382                 }
383
384                 /// <summary>
385                 ///   Loads all assemblies referenced on the command line
386                 /// </summary>
387                 static public void LoadReferences ()
388                 {
389                         foreach (string r in references)
390                                 LoadAssembly (r, false);
391
392                         foreach (string r in soft_references)
393                                 LoadAssembly (r, true);
394                         
395                         return;
396                 }
397
398                 static void SetupDefaultDefines ()
399                 {
400                         defines = new ArrayList ();
401                         defines.Add ("__MonoCS__");
402                 }
403
404                 static string [] LoadArgs (string file)
405                 {
406                         StreamReader f;
407                         ArrayList args = new ArrayList ();
408                         string line;
409                         try {
410                                 f = new StreamReader (file);
411                         } catch {
412                                 return null;
413                         }
414
415                         StringBuilder sb = new StringBuilder ();
416                         
417                         while ((line = f.ReadLine ()) != null){
418                                 int t = line.Length;
419
420                                 for (int i = 0; i < t; i++){
421                                         char c = line [i];
422                                         
423                                         if (c == '"' || c == '\''){
424                                                 char end = c;
425                                                 
426                                                 for (i++; i < t; i++){
427                                                         c = line [i];
428
429                                                         if (c == end)
430                                                                 break;
431                                                         sb.Append (c);
432                                                 }
433                                         } else if (c == ' '){
434                                                 if (sb.Length > 0){
435                                                         args.Add (sb.ToString ());
436                                                         sb.Length = 0;
437                                                 }
438                                         } else
439                                                 sb.Append (c);
440                                 }
441                                 if (sb.Length > 0){
442                                         args.Add (sb.ToString ());
443                                         sb.Length = 0;
444                                 }
445                         }
446
447                         string [] ret_value = new string [args.Count];
448                         args.CopyTo (ret_value, 0);
449
450                         return ret_value;
451                 }
452
453                 //
454                 // Returns the directory where the system assemblies are installed
455                 //
456                 static string GetSystemDir ()
457                 {
458                         Assembly [] assemblies = AppDomain.CurrentDomain.GetAssemblies ();
459
460                         foreach (Assembly a in assemblies){
461                                 string codebase = a.Location;
462                                 string fn = System.IO.Path.GetFileName (codebase);
463                                 if (fn == "corlib.dll" || fn == "mscorlib.dll"){
464                                         return codebase.Substring (0, codebase.LastIndexOf (System.IO.Path.DirectorySeparatorChar));
465                                 }
466                         }
467
468                         Report.Error (-15, "Can not compute my system path");
469                         return "";
470                 }
471
472                 //
473                 // Given a path specification, splits the path from the file/pattern
474                 //
475                 static void SplitPathAndPattern (string spec, out string path, out string pattern)
476                 {
477                         int p = spec.LastIndexOf ('/');
478                         if (p != -1){
479                                 //
480                                 // Windows does not like /file.cs, switch that to:
481                                 // "\", "file.cs"
482                                 //
483                                 if (p == 0){
484                                         path = "\\";
485                                         pattern = spec.Substring (1);
486                                 } else {
487                                         path = spec.Substring (0, p);
488                                         pattern = spec.Substring (p + 1);
489                                 }
490                                 return;
491                         }
492
493                         p = spec.LastIndexOf ('\\');
494                         if (p != -1){
495                                 path = spec.Substring (0, p);
496                                 pattern = spec.Substring (p + 1);
497                                 return;
498                         }
499
500                         path = ".";
501                         pattern = spec;
502                 }
503
504                 static void ProcessFile (string f)
505                 {
506                         if (first_source == null)
507                                 first_source = f;
508
509                         Location.AddFile (f);
510                 }
511
512                 static void ProcessFiles ()
513                 {
514                         Location.Initialize ();
515
516                         foreach (SourceFile file in Location.SourceFiles) {
517                                 if (tokenize) {
518                                         tokenize_file (file);
519                                 } else {
520                                         parse (file);
521                                 }
522                         }
523                 }
524
525                 static void CompileFiles (string spec, bool recurse)
526                 {
527                         string path, pattern;
528
529                         SplitPathAndPattern (spec, out path, out pattern);
530                         if (pattern.IndexOf ('*') == -1){
531                                 ProcessFile (spec);
532                                 return;
533                         }
534
535                         string [] files = null;
536                         try {
537                                 files = Directory.GetFiles (path, pattern);
538                         } catch (System.IO.DirectoryNotFoundException) {
539                                 Report.Error (2001, "Source file `" + spec + "' could not be found");
540                                 return;
541                         } catch (System.IO.IOException){
542                                 Report.Error (2001, "Source file `" + spec + "' could not be found");
543                                 return;
544                         }
545                         foreach (string f in files) {
546                                 ProcessFile (f);
547                         }
548
549                         if (!recurse)
550                                 return;
551                         
552                         string [] dirs = null;
553
554                         try {
555                                 dirs = Directory.GetDirectories (path);
556                         } catch {
557                         }
558                         
559                         foreach (string d in dirs) {
560                                         
561                                 // Don't include path in this string, as each
562                                 // directory entry already does
563                                 CompileFiles (d + "/" + pattern, true);
564                         }
565                 }
566
567                 static void DefineDefaultConfig ()
568                 {
569                         //
570                         // For now the "default config" is harcoded into the compiler
571                         // we can move this outside later
572                         //
573                         string [] default_config = {
574                                 "System",
575                                 "System.Xml",
576                                 "Microsoft.VisualBasic",
577 #if false
578                                 //
579                                 // Is it worth pre-loading all this stuff?
580                                 //
581                                 "Accessibility",
582                                 "System.Configuration.Install",
583                                 "System.Data",
584                                 "System.Design",
585                                 "System.DirectoryServices",
586                                 "System.Drawing.Design",
587                                 "System.Drawing",
588                                 "System.EnterpriseServices",
589                                 "System.Management",
590                                 "System.Messaging",
591                                 "System.Runtime.Remoting",
592                                 "System.Runtime.Serialization.Formatters.Soap",
593                                 "System.Security",
594                                 "System.ServiceProcess",
595                                 "System.Web",
596                                 "System.Web.RegularExpressions",
597                                 "System.Web.Services",
598                                 "System.Windows.Forms"
599 #endif
600                         };
601                         
602                         int p = 0;
603                         foreach (string def in default_config)
604                                 soft_references.Insert (p++, def);
605                 }
606
607                 static void SetOutputFile (string name)
608                 {
609                         output_file = name;
610                 }
611
612                 static void SetWarningLevel (string s)
613                 {
614                         int level = 0;
615
616                         try {
617                                 level = Int32.Parse (s);
618                         } catch {
619                                 Report.Error (
620                                         1900,
621                                         "--wlevel requires a value from 0 to 4");
622                                 Environment.Exit (1);
623                         }
624                         if (level < 0 || level > 4){
625                                 Report.Error (1900, "Warning level must be 0 to 4");
626                                 Environment.Exit (1);
627                         }
628                         RootContext.WarningLevel = level;
629                         TestWarningConflict ();
630                 }
631
632                 static void TestWarningConflict ()
633                 {
634                         if (RootContext.WarningLevel == 0 && Report.WarningsAreErrors) {
635                                 Report.Error (1901, "Conflicting options specified: Warning level 0; Treat warnings as errors");
636                                 Environment.Exit (1);
637                         }
638                 }
639
640                 static void SetupV2 ()
641                 {
642                         RootContext.Version = LanguageVersion.Default;
643                         defines.Add ("__V2__");
644                 }
645                 
646                 static void Version ()
647                 {
648                         string version = Assembly.GetExecutingAssembly ().GetName ().Version.ToString ();
649                         Console.WriteLine ("Mono C# compiler version {0}", version);
650                         Environment.Exit (0);
651                 }
652                 
653                 //
654                 // Currently handles the Unix-like command line options, but will be
655                 // deprecated in favor of the CSCParseOption, which will also handle the
656                 // options that start with a dash in the future.
657                 //
658                 static bool UnixParseOption (string arg, ref string [] args, ref int i)
659                 {
660                         switch (arg){
661                         case "-v":
662                                 CSharpParser.yacc_verbose_flag++;
663                                 return true;
664
665                         case "--version":
666                                 Version ();
667                                 return true;
668                                 
669                         case "--parse":
670                                 parse_only = true;
671                                 return true;
672                                 
673                         case "--main": case "-m":
674                                 if ((i + 1) >= args.Length){
675                                         Usage ();
676                                         Environment.Exit (1);
677                                 }
678                                 RootContext.MainClass = args [++i];
679                                 return true;
680                                 
681                         case "--unsafe":
682                                 RootContext.Unsafe = true;
683                                 return true;
684                                 
685                         case "/?": case "/h": case "/help":
686                         case "--help":
687                                 Usage ();
688                                 Environment.Exit (0);
689                                 return true;
690                                 
691                         case "--define":
692                                 if ((i + 1) >= args.Length){
693                                         Usage ();
694                                         Environment.Exit (1);
695                                 }
696                                 defines.Add (args [++i]);
697                                 return true;
698
699                         case "--show-counters":
700                                 show_counters = true;
701                                 return true;
702                                 
703                         case "--expect-error": {
704                                 int code = 0;
705                                 
706                                 try {
707                                         code = Int32.Parse (
708                                                 args [++i], NumberStyles.AllowLeadingSign);
709                                         Report.ExpectedError = code;
710                                 } catch {
711                                         Report.Error (-14, "Invalid number specified");
712                                 } 
713                                 return true;
714                         }
715                                 
716                         case "--tokenize": 
717                                 tokenize = true;
718                                 return true;
719                                 
720                         case "-o": 
721                         case "--output":
722                                 if ((i + 1) >= args.Length){
723                                         Usage ();
724                                         Environment.Exit (1);
725                                 }
726                                 SetOutputFile (args [++i]);
727                                 return true;
728                                 
729                         case "--checked":
730                                 RootContext.Checked = true;
731                                 return true;
732                                 
733                         case "--stacktrace":
734                                 Report.Stacktrace = true;
735                                 return true;
736                                 
737                         case "--linkresource":
738                         case "--linkres":
739                                 if ((i + 1) >= args.Length){
740                                         Usage ();
741                                         Report.Error (5, "Missing argument to --linkres"); 
742                                         Environment.Exit (1);
743                                 }
744                                 if (resources == null)
745                                         resources = new ArrayList ();
746                                 
747                                 resources.Add (args [++i]);
748                                 return true;
749                                 
750                         case "--resource":
751                         case "--res":
752                                 if ((i + 1) >= args.Length){
753                                         Usage ();
754                                         Report.Error (5, "Missing argument to --resource"); 
755                                         Environment.Exit (1);
756                                 }
757                                 if (embedded_resources == null)
758                                         embedded_resources = new ArrayList ();
759                                 
760                                 embedded_resources.Add (args [++i]);
761                                 return true;
762                                 
763                         case "--target":
764                                 if ((i + 1) >= args.Length){
765                                         Environment.Exit (1);
766                                         return true;
767                                 }
768                                 
769                                 string type = args [++i];
770                                 switch (type){
771                                 case "library":
772                                         RootContext.Target = Target.Library;
773                                         RootContext.TargetExt = ".dll";
774                                         break;
775                                         
776                                 case "exe":
777                                         RootContext.Target = Target.Exe;
778                                         break;
779                                         
780                                 case "winexe":
781                                         RootContext.Target = Target.WinExe;
782                                         break;
783                                         
784                                 case "module":
785                                         RootContext.Target = Target.Module;
786                                         RootContext.TargetExt = ".dll";
787                                         break;
788                                 default:
789                                         TargetUsage ();
790                                         Environment.Exit (1);
791                                         break;
792                                 }
793                                 return true;
794                                 
795                         case "-r":
796                                 if ((i + 1) >= args.Length){
797                                         Usage ();
798                                         Environment.Exit (1);
799                                 }
800                                 
801                                 references.Add (args [++i]);
802                                 return true;
803                                 
804                         case "-L":
805                                 if ((i + 1) >= args.Length){
806                                         Usage ();       
807                                         Environment.Exit (1);
808                                 }
809                                 link_paths.Add (args [++i]);
810                                 return true;
811                                 
812                         case "--nostdlib":
813                                 RootContext.StdLib = false;
814                                 return true;
815                                 
816                         case "--fatal":
817                                 Report.Fatal = true;
818                                 return true;
819                                 
820                         case "--werror":
821                                 Report.WarningsAreErrors = true;
822                                 TestWarningConflict();
823                                 return true;
824                                 
825                         case "--nowarn":
826                                 if ((i + 1) >= args.Length){
827                                         Usage ();
828                                         Environment.Exit (1);
829                                 }
830                                 int warn = 0;
831                                 
832                                 try {
833                                         warn = Int32.Parse (args [++i]);
834                                 } catch {
835                                         Usage ();
836                                         Environment.Exit (1);
837                                 }
838                                 Report.SetIgnoreWarning (warn);
839                                 return true;
840                                 
841                         case "--wlevel":
842                                 if ((i + 1) >= args.Length){
843                                         Report.Error (
844                                                 1900,
845                                                 "--wlevel requires a value from 0 to 4");
846                                         Environment.Exit (1);
847                                 }
848
849                                 SetWarningLevel (args [++i]);
850                                 return true;
851
852                         case "--mcs-debug":
853                                 if ((i + 1) >= args.Length){
854                                         Report.Error (5, "--mcs-debug requires an argument");
855                                         Environment.Exit (1);
856                                 }
857
858                                 try {
859                                         Report.DebugFlags = Int32.Parse (args [++i]);
860                                 } catch {
861                                         Report.Error (5, "Invalid argument to --mcs-debug");
862                                         Environment.Exit (1);
863                                 }
864                                 return true;
865                                 
866                         case "--about":
867                                 About ();
868                                 return true;
869                                 
870                         case "--recurse":
871                                 if ((i + 1) >= args.Length){
872                                         Report.Error (5, "--recurse requires an argument");
873                                         Environment.Exit (1);
874                                 }
875                                 CompileFiles (args [++i], true); 
876                                 return true;
877                                 
878                         case "--timestamp":
879                                 timestamps = true;
880                                 last_time = first_time = DateTime.Now;
881                                 return true;
882
883                         case "--pause":
884                                 pause = true;
885                                 return true;
886                                 
887                         case "--debug": case "-g":
888                                 want_debugging_support = true;
889                                 return true;
890                                 
891                         case "--noconfig":
892                                 load_default_config = false;
893                                 return true;
894                         }
895
896                         return false;
897                 }
898
899                 //
900                 // Currently it is very basic option parsing, but eventually, this will
901                 // be the complete option parser
902                 //
903                 static bool CSCParseOption (string option, ref string [] args, ref int i)
904                 {
905                         int idx = option.IndexOf (':');
906                         string arg, value;
907
908                         if (idx == -1){
909                                 arg = option;
910                                 value = "";
911                         } else {
912                                 arg = option.Substring (0, idx);
913
914                                 value = option.Substring (idx + 1);
915                         }
916
917                         switch (arg){
918                         case "/nologo":
919                                 return true;
920
921                         case "/t":
922                         case "/target":
923                                 switch (value){
924                                 case "exe":
925                                         RootContext.Target = Target.Exe;
926                                         break;
927
928                                 case "winexe":
929                                         RootContext.Target = Target.WinExe;
930                                         break;
931
932                                 case "library":
933                                         RootContext.Target = Target.Library;
934                                         RootContext.TargetExt = ".dll";
935                                         break;
936
937                                 case "module":
938                                         RootContext.Target = Target.Module;
939                                         RootContext.TargetExt = ".netmodule";
940                                         break;
941
942                                 default:
943                                         TargetUsage ();
944                                         Environment.Exit (1);
945                                         break;
946                                 }
947                                 return true;
948
949                         case "/out":
950                                 if (value == ""){
951                                         Usage ();
952                                         Environment.Exit (1);
953                                 }
954                                 SetOutputFile (value);
955                                 return true;
956
957                         case "/optimize":
958                         case "/optimize+":
959                         case "/optimize-":
960                         case "/incremental":
961                         case "/incremental+":
962                         case "/incremental-":
963                                 // nothing.
964                                 return true;
965
966                         case "/d":
967                         case "/define": {
968                                 string [] defs;
969
970                                 if (value == ""){
971                                         Usage ();
972                                         Environment.Exit (1);
973                                 }
974
975                                 defs = value.Split (new Char [] {';', ','});
976                                 foreach (string d in defs){
977                                         defines.Add (d);
978                                 }
979                                 return true;
980                         }
981
982                         case "/linkres":
983                         case "/linkresource":
984                                 if (value == ""){
985                                         Report.Error (5, arg + " requires an argument");
986                                         Environment.Exit (1);
987                                 }
988                                 if (resources == null)
989                                         resources = new ArrayList ();
990                                 
991                                 resources.Add (value);
992                                 return true;
993                                 
994                         case "/pkg": {
995                                 string packages;
996
997                                 if (value == ""){
998                                         Usage ();
999                                         Environment.Exit (1);
1000                                 }
1001                                 packages = String.Join (" ", value.Split (new Char [] { ';', ',', '\n', '\r'}));
1002                                 
1003                                 ProcessStartInfo pi = new ProcessStartInfo ();
1004                                 pi.FileName = "pkg-config";
1005                                 pi.RedirectStandardOutput = true;
1006                                 pi.UseShellExecute = false;
1007                                 pi.Arguments = "--libs " + packages;
1008                                 Process p = null;
1009                                 try {
1010                                         p = Process.Start (pi);
1011                                 } catch (Exception e) {
1012                                         Report.Error (-27, "Couldn't run pkg-config: " + e.Message);
1013                                         Environment.Exit (1);
1014                                 }
1015
1016                                 if (p.StandardOutput == null){
1017                                         Report.Warning (-27, "Specified package did not return any information");
1018                                         return true;
1019                                 }
1020                                 string pkgout = p.StandardOutput.ReadToEnd ();
1021                                 p.WaitForExit ();
1022                                 if (p.ExitCode != 0) {
1023                                         Report.Error (-27, "Error running pkg-config. Check the above output.");
1024                                         Environment.Exit (1);
1025                                 }
1026
1027                                 if (pkgout != null){
1028                                         string [] xargs = pkgout.Trim (new Char [] {' ', '\n', '\r', '\t'}).
1029                                                 Split (new Char [] { ' ', '\t'});
1030                                         args = AddArgs (args, xargs);
1031                                 }
1032                                 
1033                                 p.Close ();
1034                                 return true;
1035                         }
1036                                 
1037                         case "/res":
1038                         case "/resource":
1039                                 if (value == ""){
1040                                         Report.Error (5, "-resource requires an argument");
1041                                         Environment.Exit (1);
1042                                 }
1043                                 if (embedded_resources == null)
1044                                         embedded_resources = new ArrayList ();
1045                                 
1046                                 if (embedded_resources.Contains (value)) {
1047                                         Report.Error (1508, String.Format ("The resource identifier '{0}' has already been used in this assembly.", value));
1048                                 }
1049                                 else if (value.IndexOf (',') != -1 && embedded_resources.Contains (value.Split (',')[1])) {
1050                                         Report.Error (1508, String.Format ("The resource identifier '{0}' has already been used in this assembly.", value));
1051                                 }
1052                                 else {
1053                                 embedded_resources.Add (value);
1054                                 }
1055                                 return true;
1056                                 
1057                         case "/recurse":
1058                                 if (value == ""){
1059                                         Report.Error (5, "-recurse requires an argument");
1060                                         Environment.Exit (1);
1061                                 }
1062                                 CompileFiles (value, true); 
1063                                 return true;
1064
1065                         case "/r":
1066                         case "/reference": {
1067                                 if (value == ""){
1068                                         Report.Error (5, "-reference requires an argument");
1069                                         Environment.Exit (1);
1070                                 }
1071
1072                                 string [] refs = value.Split (new char [] { ';', ',' });
1073                                 foreach (string r in refs){
1074                                         references.Add (r);
1075                                 }
1076                                 return true;
1077                         }
1078                         case "/addmodule": {
1079                                 if (value == ""){
1080                                         Report.Error (5, arg + " requires an argument");
1081                                         Environment.Exit (1);
1082                                 }
1083
1084                                 string [] refs = value.Split (new char [] { ';', ',' });
1085                                 foreach (string r in refs){
1086                                         modules.Add (r);
1087                                 }
1088                                 return true;
1089                         }
1090                         case "/win32res": {
1091                                 if (value == "") {
1092                                         Report.Error (5, arg + " requires an argument");
1093                                         Environment.Exit (1);
1094                                 }
1095
1096                                 win32ResourceFile = value;
1097                                 return true;
1098                         }
1099                         case "/win32icon": {
1100                                 if (value == "") {
1101                                         Report.Error (5, arg + " requires an argument");
1102                                         Environment.Exit (1);
1103                                 }
1104
1105                                 win32IconFile = value;
1106                                 return true;
1107                         }
1108                         case "/doc": {
1109                                 if (value == ""){
1110                                         Report.Error (2006, arg + " requires an argument");
1111                                         Environment.Exit (1);
1112                                 }
1113                                 RootContext.Documentation = new Documentation (value);
1114                                 return true;
1115                         }
1116                         case "/lib": {
1117                                 string [] libdirs;
1118                                 
1119                                 if (value == ""){
1120                                         Report.Error (5, "/lib requires an argument");
1121                                         Environment.Exit (1);
1122                                 }
1123
1124                                 libdirs = value.Split (new Char [] { ',' });
1125                                 foreach (string dir in libdirs)
1126                                         link_paths.Add (dir);
1127                                 return true;
1128                         }
1129
1130                         case "/debug-":
1131                                 want_debugging_support = false;
1132                                 return true;
1133                                 
1134                         case "/debug":
1135                         case "/debug+":
1136                                 want_debugging_support = true;
1137                                 return true;
1138
1139                         case "/checked":
1140                         case "/checked+":
1141                                 RootContext.Checked = true;
1142                                 return true;
1143
1144                         case "/checked-":
1145                                 RootContext.Checked = false;
1146                                 return true;
1147
1148                         case "/clscheck":
1149                         case "/clscheck+":
1150                                 return true;
1151
1152                         case "/clscheck-":
1153                                 RootContext.VerifyClsCompliance = false;
1154                                 return true;
1155
1156                         case "/unsafe":
1157                         case "/unsafe+":
1158                                 RootContext.Unsafe = true;
1159                                 return true;
1160
1161                         case "/unsafe-":
1162                                 RootContext.Unsafe = false;
1163                                 return true;
1164
1165                         case "/warnaserror":
1166                         case "/warnaserror+":
1167                                 Report.WarningsAreErrors = true;
1168                                 TestWarningConflict();
1169                                 return true;
1170
1171                         case "/warnaserror-":
1172                                 Report.WarningsAreErrors = false;
1173                                 return true;
1174
1175                         case "/warn":
1176                                 SetWarningLevel (value);
1177                                 return true;
1178
1179                         case "/nowarn": {
1180                                 string [] warns;
1181
1182                                 if (value == ""){
1183                                         Report.Error (5, "/nowarn requires an argument");
1184                                         Environment.Exit (1);
1185                                 }
1186                                 
1187                                 warns = value.Split (new Char [] {','});
1188                                 foreach (string wc in warns){
1189                                         try {
1190                                                 int warn = Int32.Parse (wc);
1191                                                 if (warn < 1) {
1192                                                         throw new ArgumentOutOfRangeException("warn");
1193                                                 }
1194                                                 Report.SetIgnoreWarning (warn);
1195                                         } catch {
1196                                                 Report.Error (1904, String.Format("'{0}' is not a valid warning number", wc));
1197                                                 Environment.Exit (1);
1198                                         }
1199                                 }
1200                                 return true;
1201                         }
1202
1203                         case "/noconfig-":
1204                                 load_default_config = true;
1205                                 return true;
1206                                 
1207                         case "/noconfig":
1208                         case "/noconfig+":
1209                                 load_default_config = false;
1210                                 return true;
1211
1212                         case "/help2":
1213                                 OtherFlags ();
1214                                 Environment.Exit(0);
1215                                 return true;
1216                                 
1217                         case "/help":
1218                         case "/?":
1219                                 Usage ();
1220                                 Environment.Exit (0);
1221                                 return true;
1222
1223                         case "/main":
1224                         case "/m":
1225                                 if (value == ""){
1226                                         Report.Error (5, arg + " requires an argument");                                        
1227                                         Environment.Exit (1);
1228                                 }
1229                                 RootContext.MainClass = value;
1230                                 return true;
1231
1232                         case "/nostdlib":
1233                         case "/nostdlib+":
1234                                 RootContext.StdLib = false;
1235                                 return true;
1236
1237                         case "/nostdlib-":
1238                                 RootContext.StdLib = true;
1239                                 return true;
1240
1241                         case "/fullpaths":
1242                                 return true;
1243
1244                         case "/keyfile":
1245                                 if (value == String.Empty) {
1246                                         Report.Error (5, arg + " requires an argument");
1247                                         Environment.Exit (1);
1248                                 }
1249                                 RootContext.StrongNameKeyFile = value;
1250                                 return true;
1251                         case "/keycontainer":
1252                                 if (value == String.Empty) {
1253                                         Report.Error (5, arg + " requires an argument");
1254                                         Environment.Exit (1);
1255                                 }
1256                                 RootContext.StrongNameKeyContainer = value;
1257                                 return true;
1258                         case "/delaysign+":
1259                                 RootContext.StrongNameDelaySign = true;
1260                                 return true;
1261                         case "/delaysign-":
1262                                 RootContext.StrongNameDelaySign = false;
1263                                 return true;
1264
1265                         case "/v2":
1266                         case "/2":
1267                                 Console.WriteLine ("The compiler option -2 is obsolete. Please use /langversion instead");
1268                                 SetupV2 ();
1269                                 return true;
1270                                 
1271                         case "/langversion":
1272                                 switch (value.ToLower (CultureInfo.InvariantCulture)) {
1273                                         case "iso-1":
1274                                                 RootContext.Version = LanguageVersion.ISO_1;
1275                                                 return true;
1276
1277                                         case "default":
1278                                                 SetupV2 ();
1279                                                 return true;
1280                                 }
1281                                 Report.Error (1617, "Invalid option '{0}' for /langversion; must be ISO-1 or Default", value);
1282                                 Environment.Exit (1);
1283                                 return false;
1284
1285                         case "/codepage":
1286                                 int cp = -1;
1287
1288                                 if (value == "utf8"){
1289                                         encoding = new UTF8Encoding();
1290                                         using_default_encoder = false;
1291                                         return true;
1292                                 }
1293                                 if (value == "reset"){
1294                                         //
1295                                         // 28591 is the code page for ISO-8859-1 encoding.
1296                                         //
1297                                         cp = 28591;
1298                                         using_default_encoder = true;
1299                                 }
1300                                 
1301                                 try {
1302                                         cp = Int32.Parse (value);
1303                                         encoding = Encoding.GetEncoding (cp);
1304                                         using_default_encoder = false;
1305                                 } catch {
1306                                         Report.Error (2016, String.Format("Code page '{0}' is invalid or not installed", cp));
1307                                         Environment.Exit (1);
1308                                 }
1309                                 return true;
1310                         }
1311                         //Report.Error (2007, String.Format ("Unrecognized command-line option: '{0}'", option));
1312                         //Environment.Exit (1);
1313                         return false;
1314                 }
1315                 
1316                 static string [] AddArgs (string [] args, string [] extra_args)
1317                 {
1318                         string [] new_args;
1319
1320                         new_args = new string [extra_args.Length + args.Length];
1321                         args.CopyTo (new_args, 0);
1322                         extra_args.CopyTo (new_args, args.Length);
1323
1324                         return new_args;
1325                 }
1326                 
1327                 /// <summary>
1328                 ///    Parses the arguments, and drives the compilation
1329                 ///    process.
1330                 /// </summary>
1331                 ///
1332                 /// <remarks>
1333                 ///    TODO: Mostly structured to debug the compiler
1334                 ///    now, needs to be turned into a real driver soon.
1335                 /// </remarks>
1336                 // [MonoTODO("Change error code for unknown argument to something reasonable")]
1337                 internal static bool MainDriver (string [] args)
1338                 {
1339                         int i;
1340                         bool parsing_options = true;
1341
1342                         try {
1343                                 encoding = Encoding.GetEncoding (28591);
1344                         } catch {
1345                                 Console.WriteLine ("Error: could not load encoding 28591, trying 1252");
1346                                 encoding = Encoding.GetEncoding (1252);
1347                         }
1348                         
1349                         references = new ArrayList ();
1350                         soft_references = new ArrayList ();
1351                         modules = new ArrayList ();
1352                         link_paths = new ArrayList ();
1353
1354                         SetupDefaultDefines ();
1355                         
1356                         //
1357                         // Setup defaults
1358                         //
1359                         // This is not required because Assembly.Load knows about this
1360                         // path.
1361                         //
1362
1363                         for (i = 0; i < args.Length; i++){
1364                                 string arg = args [i];
1365                                 if (arg == "")
1366                                         continue;
1367
1368                                 if (arg.StartsWith ("@")){
1369                                         string [] extra_args;
1370                                         string response_file = arg.Substring (1);
1371
1372                                         if (response_file_list == null)
1373                                                 response_file_list = new Hashtable ();
1374                                         
1375                                         if (response_file_list.Contains (response_file)){
1376                                                 Report.Error (
1377                                                         1515, "Response file `" + response_file +
1378                                                         "' specified multiple times");
1379                                                 Environment.Exit (1);
1380                                         }
1381                                         
1382                                         response_file_list.Add (response_file, response_file);
1383                                                     
1384                                         extra_args = LoadArgs (response_file);
1385                                         if (extra_args == null){
1386                                                 Report.Error (2011, "Unable to open response file: " +
1387                                                               response_file);
1388                                                 return false;
1389                                         }
1390
1391                                         args = AddArgs (args, extra_args);
1392                                         continue;
1393                                 }
1394
1395                                 if (parsing_options){
1396                                         if (arg == "--"){
1397                                                 parsing_options = false;
1398                                                 continue;
1399                                         }
1400                                         
1401                                         if (arg.StartsWith ("-")){
1402                                                 if (UnixParseOption (arg, ref args, ref i))
1403                                                         continue;
1404
1405                                                 // Try a -CSCOPTION
1406                                                 string csc_opt = "/" + arg.Substring (1);
1407                                                 if (CSCParseOption (csc_opt, ref args, ref i))
1408                                                         continue;
1409                                         } else {
1410                                                 if (arg.StartsWith ("/")){
1411                                                         if (CSCParseOption (arg, ref args, ref i))
1412                                                                 continue;
1413                                                 }
1414                                         }
1415                                 }
1416
1417                                 CompileFiles (arg, false); 
1418                         }
1419
1420                         ProcessFiles ();
1421
1422                         if (tokenize)
1423                                 return true;
1424                         
1425                         //
1426                         // If we are an exe, require a source file for the entry point
1427                         //
1428                         if (RootContext.Target == Target.Exe || RootContext.Target == Target.WinExe){
1429                         if (first_source == null){
1430                                 Report.Error (2008, "No files to compile were specified");
1431                                 return false;
1432                         }
1433
1434                         }
1435
1436                         //
1437                         // If there is nothing to put in the assembly, and we are not a library
1438                         //
1439                         if (first_source == null && embedded_resources == null && resources == null){
1440                                         Report.Error (2008, "No files to compile were specified");
1441                                         return false;
1442                         }
1443
1444                         if (Report.Errors > 0)
1445                                 return false;
1446                         
1447                         if (parse_only)
1448                                 return true;
1449                         
1450                         Tokenizer.Cleanup ();
1451                         
1452                         //
1453                         // Load Core Library for default compilation
1454                         //
1455                         if (RootContext.StdLib) 
1456                                 references.Insert (0, "mscorlib");
1457
1458                         if (load_default_config)
1459                                 DefineDefaultConfig ();
1460
1461                         if (Report.Errors > 0){
1462                                 return false;
1463                         }
1464
1465                         //
1466                         // Load assemblies required
1467                         //
1468                         if (timestamps)
1469                                 ShowTime ("Loading references");
1470                         link_paths.Add (GetSystemDir ());
1471                         link_paths.Add (Directory.GetCurrentDirectory ());
1472                         LoadReferences ();
1473                         
1474                         if (timestamps)
1475                                 ShowTime ("   References loaded");
1476                         
1477                         if (Report.Errors > 0){
1478                                 return false;
1479                         }
1480
1481                         //
1482                         // Quick hack
1483                         //
1484                         if (output_file == null){
1485                                 int pos = first_source.LastIndexOf ('.');
1486
1487                                 if (pos > 0)
1488                                         output_file = first_source.Substring (0, pos) + RootContext.TargetExt;
1489                                 else
1490                                         output_file = first_source + RootContext.TargetExt;
1491                         }
1492
1493                         CodeGen.Init (output_file, output_file, want_debugging_support);
1494
1495                         if (RootContext.Target == Target.Module) {
1496                                 PropertyInfo module_only = typeof (AssemblyBuilder).GetProperty ("IsModuleOnly", BindingFlags.Instance|BindingFlags.Public|BindingFlags.NonPublic);
1497                                 if (module_only == null) {
1498                                         Report.Error (0, new Location (-1), "Cannot use /target:module on this runtime: try the Mono runtime instead.");
1499                                         Environment.Exit (1);
1500                                 }
1501
1502                                 MethodInfo set_method = module_only.GetSetMethod (true);
1503                                 set_method.Invoke (CodeGen.Assembly.Builder, BindingFlags.Default, null, new object[]{true}, null);
1504                         }
1505
1506                         TypeManager.AddModule (CodeGen.Module.Builder);
1507
1508                         if (modules.Count > 0) {
1509                                 MethodInfo adder_method = typeof (AssemblyBuilder).GetMethod ("AddModule", BindingFlags.Instance|BindingFlags.NonPublic);
1510                                 if (adder_method == null) {
1511                                         Report.Error (0, new Location (-1), "Cannot use /addmodule on this runtime: Try the Mono runtime instead.");
1512                                         Environment.Exit (1);
1513                                 }
1514
1515                                 foreach (string module in modules)
1516                                         LoadModule (adder_method, module);
1517                         }
1518
1519                         TypeManager.ComputeNamespaces ();
1520                         
1521                         //
1522                         // Before emitting, we need to get the core
1523                         // types emitted from the user defined types
1524                         // or from the system ones.
1525                         //
1526                         if (timestamps)
1527                                 ShowTime ("Initializing Core Types");
1528                         if (!RootContext.StdLib){
1529                                 RootContext.ResolveCore ();
1530                                 if (Report.Errors > 0)
1531                                         return false;
1532                         }
1533                         
1534                         TypeManager.InitCoreTypes ();
1535                         if (timestamps)
1536                                 ShowTime ("   Core Types done");
1537
1538                         //
1539                         // The second pass of the compiler
1540                         //
1541                         if (timestamps)
1542                                 ShowTime ("Resolving tree");
1543                         RootContext.ResolveTree ();
1544
1545                         if (Report.Errors > 0)
1546                                 return false;
1547                         if (timestamps)
1548                                 ShowTime ("Populate tree");
1549                         if (!RootContext.StdLib)
1550                                 RootContext.BootCorlib_PopulateCoreTypes ();
1551                         RootContext.PopulateTypes ();
1552                         RootContext.DefineTypes ();
1553                         
1554                         if (RootContext.Documentation != null &&
1555                                 !RootContext.Documentation.OutputDocComment (
1556                                         output_file))
1557                                 return false;
1558
1559                         TypeManager.InitCodeHelpers ();
1560
1561                         //
1562                         // Verify using aliases now
1563                         //
1564                         Namespace.VerifyUsing ();
1565                         
1566                         if (Report.Errors > 0){
1567                                 return false;
1568                         }
1569                         
1570                         if (RootContext.VerifyClsCompliance) { 
1571                                 CodeGen.Assembly.ResolveClsCompliance ();
1572                                 if (CodeGen.Assembly.IsClsCompliant) {
1573                                 AttributeTester.VerifyModulesClsCompliance ();
1574                                 TypeManager.LoadAllImportedTypes ();
1575                                         AttributeTester.VerifyTopLevelNameClsCompliance ();
1576                                 }
1577                         }
1578                         
1579                         //
1580                         // The code generator
1581                         //
1582                         if (timestamps)
1583                                 ShowTime ("Emitting code");
1584                         ShowTotalTime ("Total so far");
1585                         RootContext.EmitCode ();
1586                         if (timestamps)
1587                                 ShowTime ("   done");
1588
1589                         if (Report.Errors > 0){
1590                                 return false;
1591                         }
1592
1593                         if (timestamps)
1594                                 ShowTime ("Closing types");
1595
1596                         RootContext.CloseTypes ();
1597
1598                         PEFileKinds k = PEFileKinds.ConsoleApplication;
1599                                 
1600                         switch (RootContext.Target) {
1601                         case Target.Library:
1602                         case Target.Module:
1603                                 k = PEFileKinds.Dll; break;
1604                         case Target.Exe:
1605                                 k = PEFileKinds.ConsoleApplication; break;
1606                         case Target.WinExe:
1607                                 k = PEFileKinds.WindowApplication; break;
1608                         }
1609
1610                         if (RootContext.NeedsEntryPoint) {
1611                                 MethodInfo ep = RootContext.EntryPoint;
1612
1613                                 if (ep == null) {
1614                                         if (RootContext.MainClass != null) {
1615                                                 object main_cont = RootContext.Tree.Decls [RootContext.MainClass];
1616                                                 if (main_cont == null) {
1617                                                         Report.Error (1555, output_file, "Could not find '{0}' specified for Main method", RootContext.MainClass); 
1618                                                         return false;
1619                                                 }
1620
1621                                                 if (!(main_cont is ClassOrStruct)) {
1622                                                         Report.Error (1556, output_file, "'{0}' specified for Main method must be a valid class or struct", RootContext.MainClass);
1623                                                         return false;
1624                                                 }
1625                                         }
1626
1627                                         if (Report.Errors == 0)
1628                                                 Report.Error (5001, "Program " + output_file +
1629                                                               " does not have an entry point defined");
1630                                         return false;
1631                                 }
1632                                 
1633                                 CodeGen.Assembly.Builder.SetEntryPoint (ep, k);
1634                         } else if (RootContext.MainClass != null) {
1635                                 Report.Error (2017, "Can not specify -main: when building module or library");
1636                         }
1637
1638                         //
1639                         // Add the resources
1640                         //
1641                         if (resources != null){
1642                                 foreach (string spec in resources){
1643                                         string file, res;
1644                                         int cp;
1645                                         
1646                                         cp = spec.IndexOf (',');
1647                                         if (cp != -1){
1648                                                 file = spec.Substring (0, cp);
1649                                                 res = spec.Substring (cp + 1);
1650                                         } else
1651                                                 file = res = spec;
1652
1653                                         CodeGen.Assembly.Builder.AddResourceFile (res, file);
1654                                 }
1655                         }
1656                         
1657                         if (embedded_resources != null){
1658                                 object[] margs = new object [2];
1659                                 Type[] argst = new Type [2];
1660                                 argst [0] = argst [1] = typeof (string);
1661
1662                                 MethodInfo embed_res = typeof (AssemblyBuilder).GetMethod (
1663                                         "EmbedResourceFile", BindingFlags.Instance|BindingFlags.Public|BindingFlags.NonPublic,
1664                                         null, CallingConventions.Any, argst, null);
1665                                 
1666                                 if (embed_res == null) {
1667                                         Report.Warning (0, new Location (-1),
1668                                                         "Cannot embed resources on this runtime: try the Mono runtime instead.");
1669                                 } else {
1670                                         foreach (string spec in embedded_resources) {
1671                                                 int cp;
1672
1673                                                 cp = spec.IndexOf (',');
1674                                                 if (cp != -1){
1675                                                         margs [0] = spec.Substring (cp + 1);
1676                                                         margs [1] = spec.Substring (0, cp);
1677                                                 } else {
1678                                                         margs [1] = spec;
1679                                                         margs [0] = Path.GetFileName (spec);
1680                                                 }
1681
1682                                                 if (File.Exists ((string) margs [1]))
1683                                                         embed_res.Invoke (CodeGen.Assembly.Builder, margs);
1684                                                 else {
1685                                                         Report.Error (1566, "Can not find the resource " + margs [1]);
1686                                                 }
1687                                         }
1688                                 }
1689                         }
1690
1691                         //
1692                         // Add Win32 resources
1693                         //
1694
1695                         CodeGen.Assembly.Builder.DefineVersionInfoResource ();
1696
1697                         if (win32ResourceFile != null) {
1698                                 try {
1699                                         CodeGen.Assembly.Builder.DefineUnmanagedResource (win32ResourceFile);
1700                                 }
1701                                 catch (ArgumentException) {
1702                                         Report.Warning (0, new Location (-1), "Cannot embed win32 resources on this runtime: try the Mono runtime instead.");
1703                                 }
1704                         }
1705
1706                         if (win32IconFile != null) {
1707                                 MethodInfo define_icon = typeof (AssemblyBuilder).GetMethod ("DefineIconResource", BindingFlags.Instance|BindingFlags.Public|BindingFlags.NonPublic);
1708                                 if (define_icon == null) {
1709                                         Report.Warning (0, new Location (-1), "Cannot embed icon resource on this runtime: try the Mono runtime instead.");
1710                                 }
1711                                 define_icon.Invoke (CodeGen.Assembly.Builder, new object [] { win32IconFile });
1712                         }
1713
1714                         if (Report.Errors > 0)
1715                                 return false;
1716                         
1717                         CodeGen.Save (output_file);
1718                         if (timestamps) {
1719                                 ShowTime ("Saved output");
1720                                 ShowTotalTime ("Total");
1721                         }
1722
1723                         Timer.ShowTimers ();
1724                         
1725                         if (Report.ExpectedError != 0){
1726                                 if (Report.Errors == 0) {
1727                                         Console.WriteLine ("Failed to report expected error " + Report.ExpectedError + ".\n" +
1728                                                 "No other errors reported.");
1729                                         
1730                                         Environment.Exit (2);
1731                                 } else {
1732                                         Console.WriteLine ("Failed to report expected error " + Report.ExpectedError + ".\n" +
1733                                                 "However, other errors were reported.");
1734                                         
1735                                 Environment.Exit (1);
1736                                 }
1737                                 
1738                                 
1739                                 return false;
1740                         }
1741
1742 #if DEBUGME
1743                         Console.WriteLine ("Size of strings held: " + DeclSpace.length);
1744                         Console.WriteLine ("Size of strings short: " + DeclSpace.small);
1745 #endif
1746                         return (Report.Errors == 0);
1747                 }
1748         }
1749
1750         //
1751         // This is the only public entry point
1752         //
1753         public class CompilerCallableEntryPoint : MarshalByRefObject {
1754                 static bool used = false;
1755                 
1756                 public bool InvokeCompiler (string [] args)
1757                 {
1758                         if (used)
1759                                 Reset ();
1760                         bool ok = Driver.MainDriver (args);
1761                         return ok && Report.Errors == 0;
1762                 }
1763
1764                 public void Reset ()
1765                 {
1766                 }
1767         }
1768 }