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