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