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