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