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