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