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