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