Fix warning.
[mono.git] / mcs / gmcs / driver.cs
1 //
2 // driver.cs: The compiler command line driver.
3 //
4 // Author: Miguel de Icaza (miguel@gnu.org)
5 //
6 // Licensed under the terms of the GNU GPL
7 //
8 // (C) 2001, 2002, 2003 Ximian, Inc (http://www.ximian.com)
9 // (C) 2004, 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.Diagnostics;
19         using System.IO;
20         using System.Text;
21         using System.Globalization;
22         using System.Xml;
23
24         public enum Target {
25                 Library, Exe, Module, WinExe
26         };
27         
28         /// <summary>
29         ///    The compiler driver.
30         /// </summary>
31         public class Driver
32         {
33                 
34                 //
35                 // Assemblies references to be linked.   Initialized with
36                 // mscorlib.dll here.
37                 static ArrayList references;
38
39                 //
40                 // If any of these fail, we ignore the problem.  This is so
41                 // that we can list all the assemblies in Windows and not fail
42                 // if they are missing on Linux.
43                 //
44                 static ArrayList soft_references;
45
46                 //
47                 // Modules to be linked
48                 //
49                 static ArrayList modules;
50
51                 // Lookup paths
52                 static ArrayList link_paths;
53
54                 // Whether we want to only run the tokenizer
55                 static bool tokenize = false;
56                 
57                 static string first_source;
58
59                 static bool want_debugging_support = false;
60
61                 static bool parse_only = false;
62                 static bool timestamps = false;
63                 static bool pause = false;
64                 static bool show_counters = false;
65                 
66                 //
67                 // Whether to load the initial config file (what CSC.RSP has by default)
68                 // 
69                 static bool load_default_config = true;
70
71                 //
72                 // A list of resource files
73                 //
74                 static ArrayList resources;
75                 static ArrayList embedded_resources;
76                 static string win32ResourceFile;
77                 static string win32IconFile;
78                 
79                 //
80                 // An array of the defines from the command line
81                 //
82                 static ArrayList defines;
83
84                 //
85                 // Output file
86                 //
87                 static string output_file = null;
88
89                 //
90                 // Last time we took the time
91                 //
92                 static DateTime last_time, first_time;
93
94                 //
95                 // Encoding.
96                 //
97                 static Encoding default_encoding;
98                 static Encoding encoding;
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                         RootContext.Version = LanguageVersion.Default;
285                         Location.InEmacs = Environment.GetEnvironmentVariable ("EMACS") == "t";
286
287                         bool ok = MainDriver (args);
288                         
289                         if (ok && Report.Errors == 0) {
290                                 if (Report.Warnings > 0) {
291                                         Console.WriteLine ("Compilation succeeded - {0} warning(s)", Report.Warnings);
292                                 }
293                                 if (show_counters){
294                                         Console.WriteLine ("Counter1: " + counter1);
295                                         Console.WriteLine ("Counter2: " + counter2);
296                                 }
297                                 if (pause)
298                                         Console.ReadLine ();
299                                 return 0;
300                         } else {
301                                 Console.WriteLine("Compilation failed: {0} error(s), {1} warnings",
302                                         Report.Errors, Report.Warnings);
303                                 return 1;
304                         }
305                 }
306
307                 static public void LoadAssembly (string assembly, bool soft)
308                 {
309                         Assembly a;
310                         string total_log = "";
311
312                         try {
313                                 char[] path_chars = { '/', '\\' };
314
315                                 if (assembly.IndexOfAny (path_chars) != -1) {
316                                         a = Assembly.LoadFrom (assembly);
317                                 } else {
318                                         string ass = assembly;
319                                         if (ass.EndsWith (".dll") || ass.EndsWith (".exe"))
320                                                 ass = assembly.Substring (0, assembly.Length - 4);
321                                         a = Assembly.Load (ass);
322                                 }
323                                 TypeManager.AddAssembly (a);
324
325                         } catch (FileNotFoundException){
326                                 foreach (string dir in link_paths){
327                                         string full_path = Path.Combine (dir, assembly);
328                                         if (!assembly.EndsWith (".dll") && !assembly.EndsWith (".exe"))
329                                                 full_path += ".dll";
330
331                                         try {
332                                                 a = Assembly.LoadFrom (full_path);
333                                                 TypeManager.AddAssembly (a);
334                                                 return;
335                                         } catch (FileNotFoundException ff) {
336                                                 total_log += ff.FusionLog;
337                                                 continue;
338                                         }
339                                 }
340                                 if (!soft) {
341                                         Report.Error (6, "Cannot find assembly `" + assembly + "'" );
342                                         Console.WriteLine ("Log: \n" + total_log);
343                                 }
344                         } catch (BadImageFormatException f) {
345                                 Report.Error(6, "Cannot load assembly (bad file format)" + f.FusionLog);
346                         } catch (FileLoadException f){
347                                 Report.Error(6, "Cannot load assembly " + f.FusionLog);
348                         } catch (ArgumentNullException){
349                                 Report.Error(6, "Cannot load assembly (null argument)");
350                         }
351                 }
352
353                 static public void LoadModule (MethodInfo adder_method, string module)
354                 {
355                         Module m;
356                         string total_log = "";
357
358                         try {
359                                 try {
360                                         m = (Module)adder_method.Invoke (CodeGen.Assembly.Builder, new object [] { module });
361                                 }
362                                 catch (TargetInvocationException ex) {
363                                         throw ex.InnerException;
364                                 }
365                                 TypeManager.AddModule (m);
366
367                         } 
368                         catch (FileNotFoundException){
369                                 foreach (string dir in link_paths){
370                                         string full_path = Path.Combine (dir, module);
371                                         if (!module.EndsWith (".netmodule"))
372                                                 full_path += ".netmodule";
373
374                                         try {
375                                                 try {
376                                                         m = (Module)adder_method.Invoke (CodeGen.Assembly.Builder, new object [] { full_path });
377                                                 }
378                                                 catch (TargetInvocationException ex) {
379                                                         throw ex.InnerException;
380                                                 }
381                                                 TypeManager.AddModule (m);
382                                                 return;
383                                         } catch (FileNotFoundException ff) {
384                                                 total_log += ff.FusionLog;
385                                                 continue;
386                                         }
387                                 }
388                                 Report.Error (6, "Cannot find module `" + module + "'" );
389                                 Console.WriteLine ("Log: \n" + total_log);
390                         } catch (BadImageFormatException f) {
391                                 Report.Error(6, "Cannot load module (bad file format)" + f.FusionLog);
392                         } catch (FileLoadException f){
393                                 Report.Error(6, "Cannot load module " + f.FusionLog);
394                         } catch (ArgumentNullException){
395                                 Report.Error(6, "Cannot load module (null argument)");
396                         }
397                 }
398
399                 /// <summary>
400                 ///   Loads all assemblies referenced on the command line
401                 /// </summary>
402                 static public void LoadReferences ()
403                 {
404                         foreach (string r in references)
405                                 LoadAssembly (r, false);
406
407                         foreach (string r in soft_references)
408                                 LoadAssembly (r, true);
409                         
410                         return;
411                 }
412
413                 static void SetupDefaultDefines ()
414                 {
415                         defines = new ArrayList ();
416                         defines.Add ("__MonoCS__");
417                 }
418
419                 static string [] LoadArgs (string file)
420                 {
421                         StreamReader f;
422                         ArrayList args = new ArrayList ();
423                         string line;
424                         try {
425                                 f = new StreamReader (file);
426                         } catch {
427                                 return null;
428                         }
429
430                         StringBuilder sb = new StringBuilder ();
431                         
432                         while ((line = f.ReadLine ()) != null){
433                                 int t = line.Length;
434
435                                 for (int i = 0; i < t; i++){
436                                         char c = line [i];
437                                         
438                                         if (c == '"' || c == '\''){
439                                                 char end = c;
440                                                 
441                                                 for (i++; i < t; i++){
442                                                         c = line [i];
443
444                                                         if (c == end)
445                                                                 break;
446                                                         sb.Append (c);
447                                                 }
448                                         } else if (c == ' '){
449                                                 if (sb.Length > 0){
450                                                         args.Add (sb.ToString ());
451                                                         sb.Length = 0;
452                                                 }
453                                         } else
454                                                 sb.Append (c);
455                                 }
456                                 if (sb.Length > 0){
457                                         args.Add (sb.ToString ());
458                                         sb.Length = 0;
459                                 }
460                         }
461
462                         string [] ret_value = new string [args.Count];
463                         args.CopyTo (ret_value, 0);
464
465                         return ret_value;
466                 }
467
468                 //
469                 // Returns the directory where the system assemblies are installed
470                 //
471                 static string GetSystemDir ()
472                 {
473                         return Path.GetDirectoryName (typeof (object).Assembly.Location);
474                 }
475
476                 //
477                 // Given a path specification, splits the path from the file/pattern
478                 //
479                 static void SplitPathAndPattern (string spec, out string path, out string pattern)
480                 {
481                         int p = spec.LastIndexOf ('/');
482                         if (p != -1){
483                                 //
484                                 // Windows does not like /file.cs, switch that to:
485                                 // "\", "file.cs"
486                                 //
487                                 if (p == 0){
488                                         path = "\\";
489                                         pattern = spec.Substring (1);
490                                 } else {
491                                         path = spec.Substring (0, p);
492                                         pattern = spec.Substring (p + 1);
493                                 }
494                                 return;
495                         }
496
497                         p = spec.LastIndexOf ('\\');
498                         if (p != -1){
499                                 path = spec.Substring (0, p);
500                                 pattern = spec.Substring (p + 1);
501                                 return;
502                         }
503
504                         path = ".";
505                         pattern = spec;
506                 }
507
508                 static void ProcessFile (string f)
509                 {
510                         if (first_source == null)
511                                 first_source = f;
512
513                         Location.AddFile (f);
514                 }
515
516                 static void ProcessFiles ()
517                 {
518                         Location.Initialize ();
519
520                         foreach (SourceFile file in Location.SourceFiles) {
521                                 if (tokenize) {
522                                         tokenize_file (file);
523                                 } else {
524                                         parse (file);
525                                 }
526                         }
527                 }
528
529                 static void CompileFiles (string spec, bool recurse)
530                 {
531                         string path, pattern;
532
533                         SplitPathAndPattern (spec, out path, out pattern);
534                         if (pattern.IndexOf ('*') == -1){
535                                 ProcessFile (spec);
536                                 return;
537                         }
538
539                         string [] files = null;
540                         try {
541                                 files = Directory.GetFiles (path, pattern);
542                         } catch (System.IO.DirectoryNotFoundException) {
543                                 Report.Error (2001, "Source file `" + spec + "' could not be found");
544                                 return;
545                         } catch (System.IO.IOException){
546                                 Report.Error (2001, "Source file `" + spec + "' could not be found");
547                                 return;
548                         }
549                         foreach (string f in files) {
550                                 ProcessFile (f);
551                         }
552
553                         if (!recurse)
554                                 return;
555                         
556                         string [] dirs = null;
557
558                         try {
559                                 dirs = Directory.GetDirectories (path);
560                         } catch {
561                         }
562                         
563                         foreach (string d in dirs) {
564                                         
565                                 // Don't include path in this string, as each
566                                 // directory entry already does
567                                 CompileFiles (d + "/" + pattern, true);
568                         }
569                 }
570
571                 static void DefineDefaultConfig ()
572                 {
573                         //
574                         // For now the "default config" is harcoded into the compiler
575                         // we can move this outside later
576                         //
577                         string [] default_config = {
578                                 "System",
579                                 "System.Xml",
580 #if false
581                                 //
582                                 // Is it worth pre-loading all this stuff?
583                                 //
584                                 "Accessibility",
585                                 "System.Configuration.Install",
586                                 "System.Data",
587                                 "System.Design",
588                                 "System.DirectoryServices",
589                                 "System.Drawing.Design",
590                                 "System.Drawing",
591                                 "System.EnterpriseServices",
592                                 "System.Management",
593                                 "System.Messaging",
594                                 "System.Runtime.Remoting",
595                                 "System.Runtime.Serialization.Formatters.Soap",
596                                 "System.Security",
597                                 "System.ServiceProcess",
598                                 "System.Web",
599                                 "System.Web.RegularExpressions",
600                                 "System.Web.Services",
601                                 "System.Windows.Forms"
602 #endif
603                         };
604                         
605                         int p = 0;
606                         foreach (string def in default_config)
607                                 soft_references.Insert (p++, def);
608                 }
609
610                 public static string OutputFile
611                 {
612                         set {
613                                 output_file = value;
614                         }
615                         get {
616                                 return Path.GetFileName (output_file);
617                         }
618                 }
619
620                 static void SetWarningLevel (string s)
621                 {
622                         int level = -1;
623
624                         try {
625                                 level = Int32.Parse (s);
626                         } catch {
627                         }
628                         if (level < 0 || level > 4){
629                                 Report.Error (1900, "Warning level must be in the range 0-4");
630                                 return;
631                         }
632                         RootContext.WarningLevel = level;
633                 }
634
635                 static void SetupV2 ()
636                 {
637                         RootContext.Version = LanguageVersion.Default;
638                         defines.Add ("__V2__");
639                 }
640                 
641                 static void Version ()
642                 {
643                         string version = Assembly.GetExecutingAssembly ().GetName ().Version.ToString ();
644                         Console.WriteLine ("Mono C# compiler version {0}", version);
645                         Environment.Exit (0);
646                 }
647                 
648                 //
649                 // Currently handles the Unix-like command line options, but will be
650                 // deprecated in favor of the CSCParseOption, which will also handle the
651                 // options that start with a dash in the future.
652                 //
653                 static bool UnixParseOption (string arg, ref string [] args, ref int i)
654                 {
655                         switch (arg){
656                         case "-v":
657                                 CSharpParser.yacc_verbose_flag++;
658                                 return true;
659
660                         case "--version":
661                                 Version ();
662                                 return true;
663                                 
664                         case "--parse":
665                                 parse_only = true;
666                                 return true;
667                                 
668                         case "--main": case "-m":
669                                 Report.Warning (-29, "Compatibility: Use -main:CLASS instead of --main CLASS or -m CLASS");
670                                 if ((i + 1) >= args.Length){
671                                         Usage ();
672                                         Environment.Exit (1);
673                                 }
674                                 RootContext.MainClass = args [++i];
675                                 return true;
676                                 
677                         case "--unsafe":
678                                 Report.Warning (-29, "Compatibility: Use -unsafe instead of --unsafe");
679                                 RootContext.Unsafe = true;
680                                 return true;
681                                 
682                         case "/?": case "/h": case "/help":
683                         case "--help":
684                                 Usage ();
685                                 Environment.Exit (0);
686                                 return true;
687                                 
688                         case "--define":
689                                 Report.Warning (-29, "Compatibility: Use -d:SYMBOL instead of --define SYMBOL");
690                                 if ((i + 1) >= args.Length){
691                                         Usage ();
692                                         Environment.Exit (1);
693                                 }
694                                 defines.Add (args [++i]);
695                                 return true;
696
697                         case "--show-counters":
698                                 show_counters = true;
699                                 return true;
700                                 
701                         case "--expect-error": {
702                                 int code = 0;
703                                 
704                                 try {
705                                         code = Int32.Parse (
706                                                 args [++i], NumberStyles.AllowLeadingSign);
707                                         Report.ExpectedError = code;
708                                 } catch {
709                                         Report.Error (-14, "Invalid number specified");
710                                 } 
711                                 return true;
712                         }
713                                 
714                         case "--tokenize": 
715                                 tokenize = true;
716                                 return true;
717                                 
718                         case "-o": 
719                         case "--output":
720                                 Report.Warning (-29, "Compatibility: Use -out:FILE instead of --output FILE or -o FILE");
721                                 if ((i + 1) >= args.Length){
722                                         Usage ();
723                                         Environment.Exit (1);
724                                 }
725                                 OutputFile = args [++i];
726                                 return true;
727
728                         case "--checked":
729                                 Report.Warning (-29, "Compatibility: Use -checked instead of --checked");
730                                 RootContext.Checked = true;
731                                 return true;
732                                 
733                         case "--stacktrace":
734                                 Report.Stacktrace = true;
735                                 return true;
736                                 
737                         case "--linkresource":
738                         case "--linkres":
739                                 Report.Warning (-29, "Compatibility: Use -linkres:VALUE instead of --linkres VALUE");
740                                 if ((i + 1) >= args.Length){
741                                         Usage ();
742                                         Report.Error (5, "Missing argument to --linkres"); 
743                                         Environment.Exit (1);
744                                 }
745                                 if (resources == null)
746                                         resources = new ArrayList ();
747                                 
748                                 resources.Add (args [++i]);
749                                 return true;
750                                 
751                         case "--resource":
752                         case "--res":
753                                 Report.Warning (-29, "Compatibility: Use -res:VALUE instead of --res VALUE");
754                                 if ((i + 1) >= args.Length){
755                                         Usage ();
756                                         Report.Error (5, "Missing argument to --resource"); 
757                                         Environment.Exit (1);
758                                 }
759                                 if (embedded_resources == null)
760                                         embedded_resources = new ArrayList ();
761                                 
762                                 embedded_resources.Add (args [++i]);
763                                 return true;
764                                 
765                         case "--target":
766                                 Report.Warning (-29, "Compatibility: Use -target:KIND instead of --target KIND");
767                                 if ((i + 1) >= args.Length){
768                                         Environment.Exit (1);
769                                         return true;
770                                 }
771                                 
772                                 string type = args [++i];
773                                 switch (type){
774                                 case "library":
775                                         RootContext.Target = Target.Library;
776                                         RootContext.TargetExt = ".dll";
777                                         break;
778                                         
779                                 case "exe":
780                                         RootContext.Target = Target.Exe;
781                                         break;
782                                         
783                                 case "winexe":
784                                         RootContext.Target = Target.WinExe;
785                                         break;
786                                         
787                                 case "module":
788                                         RootContext.Target = Target.Module;
789                                         RootContext.TargetExt = ".dll";
790                                         break;
791                                 default:
792                                         TargetUsage ();
793                                         break;
794                                 }
795                                 return true;
796                                 
797                         case "-r":
798                                 Report.Warning (-29, "Compatibility: Use -r:LIBRARY instead of -r library");
799                                 if ((i + 1) >= args.Length){
800                                         Usage ();
801                                         Environment.Exit (1);
802                                 }
803                                 
804                                 references.Add (args [++i]);
805                                 return true;
806                                 
807                         case "-L":
808                                 Report.Warning (-29, "Compatibility: Use -lib:ARG instead of --L arg");
809                                 if ((i + 1) >= args.Length){
810                                         Usage ();       
811                                         Environment.Exit (1);
812                                 }
813                                 link_paths.Add (args [++i]);
814                                 return true;
815                                 
816                         case "--nostdlib":
817                                 Report.Warning (-29, "Compatibility: Use -nostdlib instead of --nostdlib");
818                                 RootContext.StdLib = false;
819                                 return true;
820                                 
821                         case "--fatal":
822                                 Report.Fatal = true;
823                                 return true;
824                                 
825                         case "--werror":
826                                 Report.Warning (-29, "Compatibility: Use -warnaserror: option instead of --werror");
827                                 Report.WarningsAreErrors = true;
828                                 return true;
829                                 
830                         case "--nowarn":
831                                 Report.Warning (-29, "Compatibility: Use -nowarn instead of --nowarn");
832                                 if ((i + 1) >= args.Length){
833                                         Usage ();
834                                         Environment.Exit (1);
835                                 }
836                                 int warn = 0;
837                                 
838                                 try {
839                                         warn = Int32.Parse (args [++i]);
840                                 } catch {
841                                         Usage ();
842                                         Environment.Exit (1);
843                                 }
844                                 Report.SetIgnoreWarning (warn);
845                                 return true;
846                                 
847                         case "--wlevel":
848                                 Report.Warning (-29, "Compatibility: Use -warn:LEVEL instead of --wlevel LEVEL");
849                                 if ((i + 1) >= args.Length){
850                                         Report.Error (
851                                                 1900,
852                                                 "--wlevel requires a value from 0 to 4");
853                                         Environment.Exit (1);
854                                 }
855
856                                 SetWarningLevel (args [++i]);
857                                 return true;
858
859                         case "--mcs-debug":
860                                 if ((i + 1) >= args.Length){
861                                         Report.Error (5, "--mcs-debug requires an argument");
862                                         Environment.Exit (1);
863                                 }
864
865                                 try {
866                                         Report.DebugFlags = Int32.Parse (args [++i]);
867                                 } catch {
868                                         Report.Error (5, "Invalid argument to --mcs-debug");
869                                         Environment.Exit (1);
870                                 }
871                                 return true;
872                                 
873                         case "--about":
874                                 About ();
875                                 return true;
876                                 
877                         case "--recurse":
878                                 Report.Warning (-29, "Compatibility: Use -recurse:PATTERN option instead --recurse PATTERN");
879                                 if ((i + 1) >= args.Length){
880                                         Report.Error (5, "--recurse requires an argument");
881                                         Environment.Exit (1);
882                                 }
883                                 CompileFiles (args [++i], true); 
884                                 return true;
885                                 
886                         case "--timestamp":
887                                 timestamps = true;
888                                 last_time = first_time = DateTime.Now;
889                                 return true;
890
891                         case "--pause":
892                                 pause = true;
893                                 return true;
894                                 
895                         case "--debug": case "-g":
896                                 Report.Warning (-29, "Compatibility: Use -debug option instead of -g or --debug");
897                                 want_debugging_support = true;
898                                 return true;
899                                 
900                         case "--noconfig":
901                                 Report.Warning (-29, "Compatibility: Use -noconfig option instead of --noconfig");
902                                 load_default_config = false;
903                                 return true;
904                         }
905
906                         return false;
907                 }
908
909                 //
910                 // This parses the -arg and /arg options to the compiler, even if the strings
911                 // in the following text use "/arg" on the strings.
912                 //
913                 static bool CSCParseOption (string option, ref string [] args, ref int i)
914                 {
915                         int idx = option.IndexOf (':');
916                         string arg, value;
917
918                         if (idx == -1){
919                                 arg = option;
920                                 value = "";
921                         } else {
922                                 arg = option.Substring (0, idx);
923
924                                 value = option.Substring (idx + 1);
925                         }
926
927                         switch (arg){
928                         case "/nologo":
929                                 return true;
930
931                         case "/t":
932                         case "/target":
933                                 switch (value){
934                                 case "exe":
935                                         RootContext.Target = Target.Exe;
936                                         break;
937
938                                 case "winexe":
939                                         RootContext.Target = Target.WinExe;
940                                         break;
941
942                                 case "library":
943                                         RootContext.Target = Target.Library;
944                                         RootContext.TargetExt = ".dll";
945                                         break;
946
947                                 case "module":
948                                         RootContext.Target = Target.Module;
949                                         RootContext.TargetExt = ".netmodule";
950                                         break;
951
952                                 default:
953                                         TargetUsage ();
954                                         break;
955                                 }
956                                 return true;
957
958                         case "/out":
959                                 if (value == ""){
960                                         Usage ();
961                                         Environment.Exit (1);
962                                 }
963                                 OutputFile = value;
964                                 return true;
965
966                         case "/optimize":
967                         case "/optimize+":
968                                 RootContext.Optimize = true;
969                                 return true;
970
971                         case "/optimize-":
972                                 RootContext.Optimize = false;
973                                 return true;
974
975                         case "/incremental":
976                         case "/incremental+":
977                         case "/incremental-":
978                                 // nothing.
979                                 return true;
980
981                         case "/d":
982                         case "/define": {
983                                 string [] defs;
984
985                                 if (value == ""){
986                                         Usage ();
987                                         Environment.Exit (1);
988                                 }
989
990                                 defs = value.Split (new Char [] {';', ','});
991                                 foreach (string d in defs){
992                                         defines.Add (d);
993                                 }
994                                 return true;
995                         }
996
997                         case "/bugreport":
998                                 //
999                                 // We should collect data, runtime, etc and store in the file specified
1000                                 //
1001                                 Console.WriteLine ("To file bug reports, please visit: http://www.mono-project.com/Bugs");
1002                                 return true;
1003
1004                         case "/linkres":
1005                         case "/linkresource":
1006                                 if (value == ""){
1007                                         Report.Error (5, arg + " requires an argument");
1008                                         Environment.Exit (1);
1009                                 }
1010                                 if (resources == null)
1011                                         resources = new ArrayList ();
1012                                 
1013                                 resources.Add (value);
1014                                 return true;
1015                                 
1016                         case "/pkg": {
1017                                 string packages;
1018
1019                                 if (value == ""){
1020                                         Usage ();
1021                                         Environment.Exit (1);
1022                                 }
1023                                 packages = String.Join (" ", value.Split (new Char [] { ';', ',', '\n', '\r'}));
1024                                 
1025                                 ProcessStartInfo pi = new ProcessStartInfo ();
1026                                 pi.FileName = "pkg-config";
1027                                 pi.RedirectStandardOutput = true;
1028                                 pi.UseShellExecute = false;
1029                                 pi.Arguments = "--libs " + packages;
1030                                 Process p = null;
1031                                 try {
1032                                         p = Process.Start (pi);
1033                                 } catch (Exception e) {
1034                                         Report.Error (-27, "Couldn't run pkg-config: " + e.Message);
1035                                         Environment.Exit (1);
1036                                 }
1037
1038                                 if (p.StandardOutput == null){
1039                                         Report.Warning (-27, "Specified package did not return any information");
1040                                         return true;
1041                                 }
1042                                 string pkgout = p.StandardOutput.ReadToEnd ();
1043                                 p.WaitForExit ();
1044                                 if (p.ExitCode != 0) {
1045                                         Report.Error (-27, "Error running pkg-config. Check the above output.");
1046                                         Environment.Exit (1);
1047                                 }
1048
1049                                 if (pkgout != null){
1050                                         string [] xargs = pkgout.Trim (new Char [] {' ', '\n', '\r', '\t'}).
1051                                                 Split (new Char [] { ' ', '\t'});
1052                                         args = AddArgs (args, xargs);
1053                                 }
1054                                 
1055                                 p.Close ();
1056                                 return true;
1057                         }
1058                                 
1059                         case "/res":
1060                         case "/resource":
1061                                 if (value == ""){
1062                                         Report.Error (5, "-resource requires an argument");
1063                                         Environment.Exit (1);
1064                                 }
1065                                 if (embedded_resources == null)
1066                                         embedded_resources = new ArrayList ();
1067                                 
1068                                 if (embedded_resources.Contains (value)) {
1069                                         Report.Error (1508, String.Format ("The resource identifier `{0}' has already been used in this assembly.", value));
1070                                 }
1071                                 else if (value.IndexOf (',') != -1 && embedded_resources.Contains (value.Split (',')[1])) {
1072                                         Report.Error (1508, String.Format ("The resource identifier `{0}' has already been used in this assembly.", value));
1073                                 }
1074                                 else {
1075                                 embedded_resources.Add (value);
1076                                 }
1077                                 return true;
1078                                 
1079                         case "/recurse":
1080                                 if (value == ""){
1081                                         Report.Error (5, "-recurse requires an argument");
1082                                         Environment.Exit (1);
1083                                 }
1084                                 CompileFiles (value, true); 
1085                                 return true;
1086
1087                         case "/r":
1088                         case "/reference": {
1089                                 if (value == ""){
1090                                         Report.Error (5, "-reference requires an argument");
1091                                         Environment.Exit (1);
1092                                 }
1093
1094                                 string [] refs = value.Split (new char [] { ';', ',' });
1095                                 foreach (string r in refs){
1096                                         references.Add (r);
1097                                 }
1098                                 return true;
1099                         }
1100                         case "/addmodule": {
1101                                 if (value == ""){
1102                                         Report.Error (5, arg + " requires an argument");
1103                                         Environment.Exit (1);
1104                                 }
1105
1106                                 string [] refs = value.Split (new char [] { ';', ',' });
1107                                 foreach (string r in refs){
1108                                         modules.Add (r);
1109                                 }
1110                                 return true;
1111                         }
1112                         case "/win32res": {
1113                                 if (value == "") {
1114                                         Report.Error (5, arg + " requires an argument");
1115                                         Environment.Exit (1);
1116                                 }
1117
1118                                 win32ResourceFile = value;
1119                                 return true;
1120                         }
1121                         case "/win32icon": {
1122                                 if (value == "") {
1123                                         Report.Error (5, arg + " requires an argument");
1124                                         Environment.Exit (1);
1125                                 }
1126
1127                                 win32IconFile = value;
1128                                 return true;
1129                         }
1130                         case "/doc": {
1131                                 if (value == ""){
1132                                         Report.Error (2006, arg + " requires an argument");
1133                                         Environment.Exit (1);
1134                                 }
1135                                 RootContext.Documentation = new Documentation (value);
1136                                 return true;
1137                         }
1138                         case "/lib": {
1139                                 string [] libdirs;
1140                                 
1141                                 if (value == ""){
1142                                         Report.Error (5, "/lib requires an argument");
1143                                         Environment.Exit (1);
1144                                 }
1145
1146                                 libdirs = value.Split (new Char [] { ',' });
1147                                 foreach (string dir in libdirs)
1148                                         link_paths.Add (dir);
1149                                 return true;
1150                         }
1151
1152                         case "/debug-":
1153                                 want_debugging_support = false;
1154                                 return true;
1155                                 
1156                         case "/debug":
1157                         case "/debug+":
1158                                 want_debugging_support = true;
1159                                 return true;
1160
1161                         case "/checked":
1162                         case "/checked+":
1163                                 RootContext.Checked = true;
1164                                 return true;
1165
1166                         case "/checked-":
1167                                 RootContext.Checked = false;
1168                                 return true;
1169
1170                         case "/clscheck":
1171                         case "/clscheck+":
1172                                 return true;
1173
1174                         case "/clscheck-":
1175                                 RootContext.VerifyClsCompliance = false;
1176                                 return true;
1177
1178                         case "/unsafe":
1179                         case "/unsafe+":
1180                                 RootContext.Unsafe = true;
1181                                 return true;
1182
1183                         case "/unsafe-":
1184                                 RootContext.Unsafe = false;
1185                                 return true;
1186
1187                         case "/warnaserror":
1188                         case "/warnaserror+":
1189                                 Report.WarningsAreErrors = true;
1190                                 return true;
1191
1192                         case "/warnaserror-":
1193                                 Report.WarningsAreErrors = false;
1194                                 return true;
1195
1196                         case "/warn":
1197                                 SetWarningLevel (value);
1198                                 return true;
1199
1200                         case "/nowarn": {
1201                                 string [] warns;
1202
1203                                 if (value == ""){
1204                                         Report.Error (5, "/nowarn requires an argument");
1205                                         Environment.Exit (1);
1206                                 }
1207                                 
1208                                 warns = value.Split (new Char [] {','});
1209                                 foreach (string wc in warns){
1210                                         try {
1211                                                 int warn = Int32.Parse (wc);
1212                                                 if (warn < 1) {
1213                                                         throw new ArgumentOutOfRangeException("warn");
1214                                                 }
1215                                                 Report.SetIgnoreWarning (warn);
1216                                         } catch {
1217                                                 Report.Error (1904, String.Format("`{0}' is not a valid warning number", wc));
1218                                         }
1219                                 }
1220                                 return true;
1221                         }
1222
1223                         case "/noconfig-":
1224                                 load_default_config = true;
1225                                 return true;
1226                                 
1227                         case "/noconfig":
1228                         case "/noconfig+":
1229                                 load_default_config = false;
1230                                 return true;
1231
1232                         case "/help2":
1233                                 OtherFlags ();
1234                                 Environment.Exit(0);
1235                                 return true;
1236                                 
1237                         case "/help":
1238                         case "/?":
1239                                 Usage ();
1240                                 Environment.Exit (0);
1241                                 return true;
1242
1243                         case "/main":
1244                         case "/m":
1245                                 if (value == ""){
1246                                         Report.Error (5, arg + " requires an argument");                                        
1247                                         Environment.Exit (1);
1248                                 }
1249                                 RootContext.MainClass = value;
1250                                 return true;
1251
1252                         case "/nostdlib":
1253                         case "/nostdlib+":
1254                                 RootContext.StdLib = false;
1255                                 return true;
1256
1257                         case "/nostdlib-":
1258                                 RootContext.StdLib = true;
1259                                 return true;
1260
1261                         case "/fullpaths":
1262                                 return true;
1263
1264                         case "/keyfile":
1265                                 if (value == String.Empty) {
1266                                         Report.Error (5, arg + " requires an argument");
1267                                         Environment.Exit (1);
1268                                 }
1269                                 RootContext.StrongNameKeyFile = value;
1270                                 return true;
1271                         case "/keycontainer":
1272                                 if (value == String.Empty) {
1273                                         Report.Error (5, arg + " requires an argument");
1274                                         Environment.Exit (1);
1275                                 }
1276                                 RootContext.StrongNameKeyContainer = value;
1277                                 return true;
1278                         case "/delaysign+":
1279                                 RootContext.StrongNameDelaySign = true;
1280                                 return true;
1281                         case "/delaysign-":
1282                                 RootContext.StrongNameDelaySign = false;
1283                                 return true;
1284
1285                         case "/v2":
1286                         case "/2":
1287                                 Console.WriteLine ("The compiler option -2 is obsolete. Please use /langversion instead");
1288                                 SetupV2 ();
1289                                 return true;
1290                                 
1291                         case "/langversion":
1292                                 switch (value.ToLower (CultureInfo.InvariantCulture)) {
1293                                         case "iso-1":
1294                                                 RootContext.Version = LanguageVersion.ISO_1;
1295                                                 return true;
1296
1297                                         case "default":
1298                                                 SetupV2 ();
1299                                                 return true;
1300                                 }
1301                                 Report.Error (1617, "Invalid option `{0}' for /langversion. It must be either `ISO-1' or `Default'", value);
1302                                 return true;
1303
1304                         case "/codepage":
1305                                 switch (value) {
1306                                 case "utf8":
1307                                         encoding = new UTF8Encoding();
1308                                         break;
1309                                 case "reset":
1310                                         encoding = default_encoding;
1311                                         break;
1312                                 default:
1313                                         try {
1314                                                 encoding = Encoding.GetEncoding (
1315                                                 Int32.Parse (value));
1316                                         } catch {
1317                                                 Report.Error (2016, "Code page `{0}' is invalid or not installed", value);
1318                                         }
1319                                         break;
1320                                 }
1321                                 return true;
1322                         }
1323
1324                         return false;
1325                 }
1326                 
1327                 static void Error_WrongOption (string option)
1328                 {
1329                         Report.Error (2007, "Unrecognized command-line option: `{0}'", option);
1330                 }
1331
1332                 static string [] AddArgs (string [] args, string [] extra_args)
1333                 {
1334                         string [] new_args;
1335                         new_args = new string [extra_args.Length + args.Length];
1336
1337                         // if args contains '--' we have to take that into account
1338                         // split args into first half and second half based on '--'
1339                         // and add the extra_args before --
1340                         int split_position = Array.IndexOf (args, "--");
1341                         if (split_position != -1)
1342                         {
1343                                 Array.Copy (args, new_args, split_position);
1344                                 extra_args.CopyTo (new_args, split_position);
1345                                 Array.Copy (args, split_position, new_args, split_position + extra_args.Length, args.Length - split_position);
1346                         }
1347                         else
1348                         {
1349                                 args.CopyTo (new_args, 0);
1350                                 extra_args.CopyTo (new_args, args.Length);
1351                         }
1352
1353                         return new_args;
1354                 }
1355                 
1356                 /// <summary>
1357                 ///    Parses the arguments, and drives the compilation
1358                 ///    process.
1359                 /// </summary>
1360                 ///
1361                 /// <remarks>
1362                 ///    TODO: Mostly structured to debug the compiler
1363                 ///    now, needs to be turned into a real driver soon.
1364                 /// </remarks>
1365                 // [MonoTODO("Change error code for unknown argument to something reasonable")]
1366                 internal static bool MainDriver (string [] args)
1367                 {
1368                         int i;
1369                         bool parsing_options = true;
1370
1371                         try {
1372                                 // Latin1
1373                                 default_encoding = Encoding.GetEncoding (28591);
1374                         } catch (Exception) {
1375                                 // iso-8859-1
1376                                 default_encoding = Encoding.GetEncoding (1252);
1377                         }
1378                         encoding = default_encoding;
1379
1380                         references = new ArrayList ();
1381                         soft_references = new ArrayList ();
1382                         modules = new ArrayList ();
1383                         link_paths = new ArrayList ();
1384
1385                         SetupDefaultDefines ();
1386                         
1387                         //
1388                         // Setup defaults
1389                         //
1390                         // This is not required because Assembly.Load knows about this
1391                         // path.
1392                         //
1393
1394                         Hashtable response_file_list = null;
1395
1396                         for (i = 0; i < args.Length; i++){
1397                                 string arg = args [i];
1398                                 if (arg == "")
1399                                         continue;
1400
1401                                 if (arg.StartsWith ("@")){
1402                                         string [] extra_args;
1403                                         string response_file = arg.Substring (1);
1404
1405                                         if (response_file_list == null)
1406                                                 response_file_list = new Hashtable ();
1407                                         
1408                                         if (response_file_list.Contains (response_file)){
1409                                                 Report.Error (
1410                                                         1515, "Response file `" + response_file +
1411                                                         "' specified multiple times");
1412                                                 Environment.Exit (1);
1413                                         }
1414                                         
1415                                         response_file_list.Add (response_file, response_file);
1416                                                     
1417                                         extra_args = LoadArgs (response_file);
1418                                         if (extra_args == null){
1419                                                 Report.Error (2011, "Unable to open response file: " +
1420                                                               response_file);
1421                                                 return false;
1422                                         }
1423
1424                                         args = AddArgs (args, extra_args);
1425                                         continue;
1426                                 }
1427
1428                                 if (parsing_options){
1429                                         if (arg == "--"){
1430                                                 parsing_options = false;
1431                                                 continue;
1432                                         }
1433                                         
1434                                         if (arg.StartsWith ("-")){
1435                                                 if (UnixParseOption (arg, ref args, ref i))
1436                                                         continue;
1437
1438                                                 // Try a -CSCOPTION
1439                                                 string csc_opt = "/" + arg.Substring (1);
1440                                                 if (CSCParseOption (csc_opt, ref args, ref i))
1441                                                         continue;
1442
1443                                                 Error_WrongOption (arg);
1444                                                 return false;
1445                                         } else {
1446                                                 if (arg [0] == '/'){
1447                                                         if (CSCParseOption (arg, ref args, ref i))
1448                                                                 continue;
1449
1450                                                         // Need to skip `/home/test.cs' however /test.cs is considered as error
1451                                                         if (arg.Length < 2 || arg.IndexOf ('/', 2) == -1) {
1452                                                                 Error_WrongOption (arg);
1453                                                                 return false;
1454                                                         }
1455                                                 }
1456                                         }
1457                                 }
1458
1459                                 CompileFiles (arg, false); 
1460                         }
1461
1462                         ProcessFiles ();
1463
1464                         if (tokenize)
1465                                 return true;
1466                         
1467                         //
1468                         // This will point to the NamespaceEntry of the last file that was parsed, and may
1469                         // not be meaningful when resolving classes from other files.  So, reset it to prevent
1470                         // silent bugs.
1471                         //
1472                         RootContext.Tree.Types.NamespaceEntry = null;
1473
1474                         //
1475                         // If we are an exe, require a source file for the entry point
1476                         //
1477                         if (RootContext.Target == Target.Exe || RootContext.Target == Target.WinExe){
1478                         if (first_source == null){
1479                                 Report.Error (2008, "No files to compile were specified");
1480                                 return false;
1481                         }
1482
1483                         }
1484
1485                         //
1486                         // If there is nothing to put in the assembly, and we are not a library
1487                         //
1488                         if (first_source == null && embedded_resources == null && resources == null){
1489                                         Report.Error (2008, "No files to compile were specified");
1490                                         return false;
1491                         }
1492
1493                         if (Report.Errors > 0)
1494                                 return false;
1495                         
1496                         if (parse_only)
1497                                 return true;
1498                         
1499                         //
1500                         // Load Core Library for default compilation
1501                         //
1502                         if (RootContext.StdLib)
1503                                 references.Insert (0, "mscorlib");
1504
1505                         if (load_default_config)
1506                                 DefineDefaultConfig ();
1507
1508                         if (Report.Errors > 0){
1509                                 return false;
1510                         }
1511
1512                         //
1513                         // Load assemblies required
1514                         //
1515                         if (timestamps)
1516                                 ShowTime ("Loading references");
1517                         link_paths.Add (GetSystemDir ());
1518                         link_paths.Add (Directory.GetCurrentDirectory ());
1519                         LoadReferences ();
1520                         
1521                         if (timestamps)
1522                                 ShowTime ("   References loaded");
1523                         
1524                         if (Report.Errors > 0){
1525                                 return false;
1526                         }
1527
1528                         //
1529                         // Quick hack
1530                         //
1531                         if (output_file == null){
1532                                 int pos = first_source.LastIndexOf ('.');
1533
1534                                 if (pos > 0)
1535                                         output_file = first_source.Substring (0, pos) + RootContext.TargetExt;
1536                                 else
1537                                         output_file = first_source + RootContext.TargetExt;
1538                         }
1539
1540                         if (!CodeGen.Init (output_file, output_file, want_debugging_support))
1541                                 return false;
1542
1543                         if (RootContext.Target == Target.Module) {
1544                                 PropertyInfo module_only = typeof (AssemblyBuilder).GetProperty ("IsModuleOnly", BindingFlags.Instance|BindingFlags.Public|BindingFlags.NonPublic);
1545                                 if (module_only == null) {
1546                                         Report.RuntimeMissingSupport (Location.Null, "/target:module");
1547                                         Environment.Exit (1);
1548                                 }
1549
1550                                 MethodInfo set_method = module_only.GetSetMethod (true);
1551                                 set_method.Invoke (CodeGen.Assembly.Builder, BindingFlags.Default, null, new object[]{true}, null);
1552                         }
1553
1554                         TypeManager.AddModule (CodeGen.Module.Builder);
1555
1556                         if (modules.Count > 0) {
1557                                 MethodInfo adder_method = typeof (AssemblyBuilder).GetMethod ("AddModule", BindingFlags.Instance|BindingFlags.NonPublic);
1558                                 if (adder_method == null) {
1559                                         Report.RuntimeMissingSupport (Location.Null, "/addmodule");
1560                                         Environment.Exit (1);
1561                                 }
1562
1563                                 foreach (string module in modules)
1564                                         LoadModule (adder_method, module);
1565                         }
1566
1567                         TypeManager.ComputeNamespaces ();
1568                         
1569                         //
1570                         // Before emitting, we need to get the core
1571                         // types emitted from the user defined types
1572                         // or from the system ones.
1573                         //
1574                         if (timestamps)
1575                                 ShowTime ("Initializing Core Types");
1576                         if (!RootContext.StdLib){
1577                                 RootContext.ResolveCore ();
1578                                 if (Report.Errors > 0)
1579                                         return false;
1580                         }
1581                         
1582                         TypeManager.InitCoreTypes ();
1583                         if (timestamps)
1584                                 ShowTime ("   Core Types done");
1585
1586                         CodeGen.Module.ResolveAttributes ();
1587
1588                         //
1589                         // The second pass of the compiler
1590                         //
1591                         if (timestamps)
1592                                 ShowTime ("Resolving tree");
1593                         RootContext.ResolveTree ();
1594
1595                         if (Report.Errors > 0)
1596                                 return false;
1597                         if (timestamps)
1598                                 ShowTime ("Populate tree");
1599                         if (!RootContext.StdLib)
1600                                 RootContext.BootCorlib_PopulateCoreTypes ();
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, Location.Null));
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 }