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