Add v1 runtime target (broken by design)
[mono.git] / mcs / mcs / driver.cs
1 //
2 // driver.cs: The compiler command line driver.
3 //
4 // Authors:
5 //   Miguel de Icaza (miguel@gnu.org)
6 //   Marek Safar (marek.safar@gmail.com)
7 //
8 // Dual licensed under the terms of the MIT X11 or GNU GPL
9 //
10 // Copyright 2001, 2002, 2003 Ximian, Inc (http://www.ximian.com)
11 // Copyright 2004, 2005, 2006, 2007, 2008 Novell, Inc
12 //
13
14 using System;
15 using System.Reflection;
16 using System.Reflection.Emit;
17 using System.Collections.Generic;
18 using System.IO;
19 using System.Text;
20 using System.Globalization;
21 using System.Diagnostics;
22
23 namespace Mono.CSharp
24 {
25         /// <summary>
26         ///    The compiler driver.
27         /// </summary>
28         class Driver
29         {
30                 string first_source;
31
32                 bool timestamps;
33                 internal int fatal_errors;
34                 
35                 //
36                 // Last time we took the time
37                 //
38                 Stopwatch stopwatch;
39                 DateTime first_time;
40
41                 internal readonly CompilerContext ctx;
42
43                 static readonly char[] argument_value_separator = new char [] { ';', ',' };
44
45                 private Driver (CompilerContext ctx)
46                 {
47                         this.ctx = ctx;
48                 }
49
50                 public static Driver Create (string[] args, bool require_files, ReportPrinter printer)
51                 {
52                         Driver d = new Driver (new CompilerContext (new Report (printer)));
53
54                         if (!d.ParseArguments (args, require_files))
55                                 return null;
56
57                         return d;
58                 }
59
60                 Report Report {
61                         get { return ctx.Report; }
62                 }
63
64                 void ShowTime (string msg)
65                 {
66                         if (!timestamps)
67                                 return;
68
69                         stopwatch.Stop ();
70
71                         Console.WriteLine ("{0,5}ms {1}", stopwatch.ElapsedMilliseconds, msg);
72
73                         stopwatch = Stopwatch.StartNew ();
74                 }
75
76                 void ShowTotalTime (string msg)
77                 {
78                         if (!timestamps)
79                                 return;
80
81                         DateTime now = DateTime.Now;
82                         TimeSpan span = now - first_time;
83
84                         Console.WriteLine (
85                                 "[{0:00}:{1:000}] {2}",
86                                 (int) span.TotalSeconds, span.Milliseconds, msg);
87                 }              
88                
89                 void tokenize_file (CompilationUnit file, CompilerContext ctx)
90                 {
91                         Stream input;
92
93                         try {
94                                 input = File.OpenRead (file.Name);
95                         } catch {
96                                 Report.Error (2001, "Source file `" + file.Name + "' could not be found");
97                                 return;
98                         }
99
100                         using (input){
101                                 SeekableStreamReader reader = new SeekableStreamReader (input, RootContext.Encoding);
102                                 Tokenizer lexer = new Tokenizer (reader, file, ctx);
103                                 int token, tokens = 0, errors = 0;
104
105                                 while ((token = lexer.token ()) != Token.EOF){
106                                         tokens++;
107                                         if (token == Token.ERROR)
108                                                 errors++;
109                                 }
110                                 Console.WriteLine ("Tokenized: " + tokens + " found " + errors + " errors");
111                         }
112                         
113                         return;
114                 }
115
116                 void Parse (CompilationUnit file, ModuleContainer module)
117                 {
118                         Stream input;
119
120                         try {
121                                 input = File.OpenRead (file.Name);
122                         } catch {
123                                 Report.Error (2001, "Source file `{0}' could not be found", file.Name);
124                                 return;
125                         }
126
127                         // Check 'MZ' header
128                         if (input.ReadByte () == 77 && input.ReadByte () == 90) {
129                                 Report.Error (2015, "Source file `{0}' is a binary file and not a text file", file.Name);
130                                 input.Close ();
131                                 return;
132                         }
133
134                         input.Position = 0;
135                         SeekableStreamReader reader = new SeekableStreamReader (input, RootContext.Encoding);
136
137                         Parse (reader, file, module);
138                         reader.Dispose ();
139                         input.Close ();
140                 }       
141                 
142                 void Parse (SeekableStreamReader reader, CompilationUnit file, ModuleContainer module)
143                 {
144                         CSharpParser parser = new CSharpParser (reader, file, module);
145                         parser.parse ();
146                 }
147
148                 static void OtherFlags ()
149                 {
150                         Console.WriteLine (
151                                 "Other flags in the compiler\n" +
152                                 "   --fatal[=COUNT]    Makes errors after COUNT fatal\n" +
153                                 "   --lint             Enhanced warnings\n" +
154                                 "   --parse            Only parses the source file\n" +
155                                 "   --runtime:VERSION  Sets mscorlib.dll metadata version: v1, v2, v4\n" +
156                                 "   --stacktrace       Shows stack trace at error location\n" +
157                                 "   --timestamp        Displays time stamps of various compiler events\n" +
158                                 "   -v                 Verbose parsing (for debugging the parser)\n" + 
159                                 "   --mcs-debug X      Sets MCS debugging level to X\n");
160                 }
161                 
162                 static void Usage ()
163                 {
164                         Console.WriteLine (
165                                 "Mono C# compiler, Copyright 2001 - 2008 Novell, Inc.\n" +
166                                 "mcs [options] source-files\n" +
167                                 "   --about              About the Mono C# compiler\n" +
168                                 "   -addmodule:M1[,Mn]   Adds the module to the generated assembly\n" + 
169                                 "   -checked[+|-]        Sets default aritmetic overflow context\n" +
170                                 "   -codepage:ID         Sets code page to the one in ID (number, utf8, reset)\n" +
171                                 "   -clscheck[+|-]       Disables CLS Compliance verifications\n" +
172                                 "   -define:S1[;S2]      Defines one or more conditional symbols (short: -d)\n" +
173                                 "   -debug[+|-], -g      Generate debugging information\n" + 
174                                 "   -delaysign[+|-]      Only insert the public key into the assembly (no signing)\n" +
175                                 "   -doc:FILE            Process documentation comments to XML file\n" + 
176                                 "   -help                Lists all compiler options (short: -?)\n" + 
177                                 "   -keycontainer:NAME   The key pair container used to sign the output assembly\n" +
178                                 "   -keyfile:FILE        The key file used to strongname the ouput assembly\n" +
179                                 "   -langversion:TEXT    Specifies language version: ISO-1, ISO-2, 3, Default, or Future\n" + 
180                                 "   -lib:PATH1[,PATHn]   Specifies the location of referenced assemblies\n" +
181                                 "   -main:CLASS          Specifies the class with the Main method (short: -m)\n" +
182                                 "   -noconfig            Disables implicitly referenced assemblies\n" +
183                                 "   -nostdlib[+|-]       Does not reference mscorlib.dll library\n" +
184                                 "   -nowarn:W1[,Wn]      Suppress one or more compiler warnings\n" + 
185                                 "   -optimize[+|-]       Enables advanced compiler optimizations (short: -o)\n" + 
186                                 "   -out:FILE            Specifies output assembly name\n" +
187 #if !SMCS_SOURCE
188                                 "   -pkg:P1[,Pn]         References packages P1..Pn\n" + 
189 #endif
190                                 "   -platform:ARCH       Specifies the target platform of the output assembly\n" +
191                                 "                        ARCH can be one of: anycpu, x86, x64 or itanium\n" +
192                                 "   -recurse:SPEC        Recursively compiles files according to SPEC pattern\n" + 
193                                 "   -reference:A1[,An]   Imports metadata from the specified assembly (short: -r)\n" +
194                                 "   -reference:ALIAS=A   Imports metadata using specified extern alias (short: -r)\n" +                         
195                                 "   -target:KIND         Specifies the format of the output assembly (short: -t)\n" +
196                                 "                        KIND can be one of: exe, winexe, library, module\n" +
197                                 "   -unsafe[+|-]         Allows to compile code which uses unsafe keyword\n" +
198                                 "   -warnaserror[+|-]    Treats all warnings as errors\n" +
199                                 "   -warnaserror[+|-]:W1[,Wn] Treats one or more compiler warnings as errors\n" +
200                                 "   -warn:0-4            Sets warning level, the default is 4 (short -w:)\n" +
201                                 "   -helpinternal        Shows internal and advanced compiler options\n" + 
202                                 "\n" +
203                                 "Resources:\n" +
204                                 "   -linkresource:FILE[,ID] Links FILE as a resource (short: -linkres)\n" +
205                                 "   -resource:FILE[,ID]     Embed FILE as a resource (short: -res)\n" +
206                                 "   -win32res:FILE          Specifies Win32 resource file (.res)\n" +
207                                 "   -win32icon:FILE         Use this icon for the output\n" +
208                                 "   @file                   Read response file for more options\n\n" +
209                                 "Options can be of the form -option or /option");
210                 }
211
212                 void TargetUsage ()
213                 {
214                         Report.Error (2019, "Invalid target type for -target. Valid options are `exe', `winexe', `library' or `module'");
215                 }
216                 
217                 static void About ()
218                 {
219                         Console.WriteLine (
220                                 "The Mono C# compiler is Copyright 2001-2008, Novell, Inc.\n\n" +
221                                 "The compiler source code is released under the terms of the \n"+
222                                 "MIT X11 or GNU GPL licenses\n\n" +
223
224                                 "For more information on Mono, visit the project Web site\n" +
225                                 "   http://www.mono-project.com\n\n" +
226
227                                 "The compiler was written by Miguel de Icaza, Ravi Pratap, Martin Baulig, Marek Safar, Raja R Harinath, Atushi Enomoto");
228                         Environment.Exit (0);
229                 }
230
231                 public static int Main (string[] args)
232                 {
233                         Location.InEmacs = Environment.GetEnvironmentVariable ("EMACS") == "t";
234                         var crp = new ConsoleReportPrinter ();
235                         Driver d = Driver.Create (args, true, crp);
236                         if (d == null)
237                                 return 1;
238
239                         crp.Fatal = d.fatal_errors;
240
241                         if (d.Compile () && d.Report.Errors == 0) {
242                                 if (d.Report.Warnings > 0) {
243                                         Console.WriteLine ("Compilation succeeded - {0} warning(s)", d.Report.Warnings);
244                                 }
245                                 Environment.Exit (0);
246                                 return 0;
247                         }
248                         
249                         
250                         Console.WriteLine("Compilation failed: {0} error(s), {1} warnings",
251                                 d.Report.Errors, d.Report.Warnings);
252                         Environment.Exit (1);
253                         return 1;
254                 }
255
256                 static string [] LoadArgs (string file)
257                 {
258                         StreamReader f;
259                         var args = new List<string> ();
260                         string line;
261                         try {
262                                 f = new StreamReader (file);
263                         } catch {
264                                 return null;
265                         }
266
267                         StringBuilder sb = new StringBuilder ();
268                         
269                         while ((line = f.ReadLine ()) != null){
270                                 int t = line.Length;
271
272                                 for (int i = 0; i < t; i++){
273                                         char c = line [i];
274                                         
275                                         if (c == '"' || c == '\''){
276                                                 char end = c;
277                                                 
278                                                 for (i++; i < t; i++){
279                                                         c = line [i];
280
281                                                         if (c == end)
282                                                                 break;
283                                                         sb.Append (c);
284                                                 }
285                                         } else if (c == ' '){
286                                                 if (sb.Length > 0){
287                                                         args.Add (sb.ToString ());
288                                                         sb.Length = 0;
289                                                 }
290                                         } else
291                                                 sb.Append (c);
292                                 }
293                                 if (sb.Length > 0){
294                                         args.Add (sb.ToString ());
295                                         sb.Length = 0;
296                                 }
297                         }
298
299                         return args.ToArray ();
300                 }
301
302                 //
303                 // Given a path specification, splits the path from the file/pattern
304                 //
305                 static void SplitPathAndPattern (string spec, out string path, out string pattern)
306                 {
307                         int p = spec.LastIndexOf ('/');
308                         if (p != -1){
309                                 //
310                                 // Windows does not like /file.cs, switch that to:
311                                 // "\", "file.cs"
312                                 //
313                                 if (p == 0){
314                                         path = "\\";
315                                         pattern = spec.Substring (1);
316                                 } else {
317                                         path = spec.Substring (0, p);
318                                         pattern = spec.Substring (p + 1);
319                                 }
320                                 return;
321                         }
322
323                         p = spec.LastIndexOf ('\\');
324                         if (p != -1){
325                                 path = spec.Substring (0, p);
326                                 pattern = spec.Substring (p + 1);
327                                 return;
328                         }
329
330                         path = ".";
331                         pattern = spec;
332                 }
333
334                 void AddSourceFile (string f)
335                 {
336                         if (first_source == null)
337                                 first_source = f;
338
339                         Location.AddFile (Report, f);
340                 }
341
342                 bool ParseArguments (string[] args, bool require_files)
343                 {
344                         List<string> response_file_list = null;
345                         bool parsing_options = true;
346
347                         for (int i = 0; i < args.Length; i++) {
348                                 string arg = args [i];
349                                 if (arg.Length == 0)
350                                         continue;
351
352                                 if (arg [0] == '@') {
353                                         string [] extra_args;
354                                         string response_file = arg.Substring (1);
355
356                                         if (response_file_list == null)
357                                                 response_file_list = new List<string> ();
358
359                                         if (response_file_list.Contains (response_file)) {
360                                                 Report.Error (
361                                                         1515, "Response file `" + response_file +
362                                                         "' specified multiple times");
363                                                 return false;
364                                         }
365
366                                         response_file_list.Add (response_file);
367
368                                         extra_args = LoadArgs (response_file);
369                                         if (extra_args == null) {
370                                                 Report.Error (2011, "Unable to open response file: " +
371                                                                   response_file);
372                                                 return false;
373                                         }
374
375                                         args = AddArgs (args, extra_args);
376                                         continue;
377                                 }
378
379                                 if (parsing_options) {
380                                         if (arg == "--") {
381                                                 parsing_options = false;
382                                                 continue;
383                                         }
384
385                                         if (arg [0] == '-') {
386                                                 if (UnixParseOption (arg, ref args, ref i))
387                                                         continue;
388
389                                                 // Try a -CSCOPTION
390                                                 string csc_opt = "/" + arg.Substring (1);
391                                                 if (CSCParseOption (csc_opt, ref args))
392                                                         continue;
393
394                                                 Error_WrongOption (arg);
395                                                 return false;
396                                         }
397                                         if (arg [0] == '/') {
398                                                 if (CSCParseOption (arg, ref args))
399                                                         continue;
400
401                                                 // Need to skip `/home/test.cs' however /test.cs is considered as error
402                                                 if (arg.Length < 2 || arg.IndexOf ('/', 2) == -1) {
403                                                         Error_WrongOption (arg);
404                                                         return false;
405                                                 }
406                                         }
407                                 }
408
409                                 ProcessSourceFiles (arg, false);
410                         }
411
412                         if (require_files == false)
413                                 return true;
414                                         
415                         //
416                         // If we are an exe, require a source file for the entry point
417                         //
418                         if (RootContext.Target == Target.Exe || RootContext.Target == Target.WinExe || RootContext.Target == Target.Module) {
419                                 if (first_source == null) {
420                                         Report.Error (2008, "No files to compile were specified");
421                                         return false;
422                                 }
423
424                         }
425
426                         //
427                         // If there is nothing to put in the assembly, and we are not a library
428                         //
429                         if (first_source == null && RootContext.Resources == null) {
430                                 Report.Error (2008, "No files to compile were specified");
431                                 return false;
432                         }
433
434                         return true;
435                 }
436
437                 public void Parse (ModuleContainer module)
438                 {
439                         Location.Initialize ();
440
441                         var cu = Location.SourceFiles;
442                         for (int i = 0; i < cu.Count; ++i) {
443                                 if (RootContext.TokenizeOnly) {
444                                         tokenize_file (cu [i], ctx);
445                                 } else {
446                                         Parse (cu [i], module);
447                                 }
448                         }
449                 }
450
451                 void ProcessSourceFiles (string spec, bool recurse)
452                 {
453                         string path, pattern;
454
455                         SplitPathAndPattern (spec, out path, out pattern);
456                         if (pattern.IndexOf ('*') == -1){
457                                 AddSourceFile (spec);
458                                 return;
459                         }
460
461                         string [] files = null;
462                         try {
463                                 files = Directory.GetFiles (path, pattern);
464                         } catch (System.IO.DirectoryNotFoundException) {
465                                 Report.Error (2001, "Source file `" + spec + "' could not be found");
466                                 return;
467                         } catch (System.IO.IOException){
468                                 Report.Error (2001, "Source file `" + spec + "' could not be found");
469                                 return;
470                         }
471                         foreach (string f in files) {
472                                 AddSourceFile (f);
473                         }
474
475                         if (!recurse)
476                                 return;
477                         
478                         string [] dirs = null;
479
480                         try {
481                                 dirs = Directory.GetDirectories (path);
482                         } catch {
483                         }
484                         
485                         foreach (string d in dirs) {
486                                         
487                                 // Don't include path in this string, as each
488                                 // directory entry already does
489                                 ProcessSourceFiles (d + "/" + pattern, true);
490                         }
491                 }
492
493                 void SetWarningLevel (string s)
494                 {
495                         int level = -1;
496
497                         try {
498                                 level = Int32.Parse (s);
499                         } catch {
500                         }
501                         if (level < 0 || level > 4){
502                                 Report.Error (1900, "Warning level must be in the range 0-4");
503                                 return;
504                         }
505                         Report.WarningLevel = level;
506                 }
507
508                 static void Version ()
509                 {
510                         string version = System.Reflection.Assembly.GetExecutingAssembly ().GetName ().Version.ToString ();
511                         Console.WriteLine ("Mono C# compiler version {0}", version);
512                         Environment.Exit (0);
513                 }
514                 
515                 //
516                 // Currently handles the Unix-like command line options, but will be
517                 // deprecated in favor of the CSCParseOption, which will also handle the
518                 // options that start with a dash in the future.
519                 //
520                 bool UnixParseOption (string arg, ref string [] args, ref int i)
521                 {
522                         switch (arg){
523                         case "-v":
524                                 CSharpParser.yacc_verbose_flag++;
525                                 return true;
526
527                         case "--version":
528                                 Version ();
529                                 return true;
530                                 
531                         case "--parse":
532                                 RootContext.ParseOnly = true;
533                                 return true;
534                                 
535                         case "--main": case "-m":
536                                 Report.Warning (-29, 1, "Compatibility: Use -main:CLASS instead of --main CLASS or -m CLASS");
537                                 if ((i + 1) >= args.Length){
538                                         Usage ();
539                                         Environment.Exit (1);
540                                 }
541                                 RootContext.MainClass = args [++i];
542                                 return true;
543                                 
544                         case "--unsafe":
545                                 Report.Warning (-29, 1, "Compatibility: Use -unsafe instead of --unsafe");
546                                 RootContext.Unsafe = true;
547                                 return true;
548                                 
549                         case "/?": case "/h": case "/help":
550                         case "--help":
551                                 Usage ();
552                                 Environment.Exit (0);
553                                 return true;
554
555                         case "--define":
556                                 Report.Warning (-29, 1, "Compatibility: Use -d:SYMBOL instead of --define SYMBOL");
557                                 if ((i + 1) >= args.Length){
558                                         Usage ();
559                                         Environment.Exit (1);
560                                 }
561                                 RootContext.AddConditional (args [++i]);
562                                 return true;
563
564                         case "--tokenize": 
565                                 RootContext.TokenizeOnly = true;
566                                 return true;
567                                 
568                         case "-o": 
569                         case "--output":
570                                 Report.Warning (-29, 1, "Compatibility: Use -out:FILE instead of --output FILE or -o FILE");
571                                 if ((i + 1) >= args.Length){
572                                         Usage ();
573                                         Environment.Exit (1);
574                                 }
575                                 RootContext.OutputFile = args [++i];
576                                 return true;
577
578                         case "--checked":
579                                 Report.Warning (-29, 1, "Compatibility: Use -checked instead of --checked");
580                                 RootContext.Checked = true;
581                                 return true;
582                                 
583                         case "--stacktrace":
584                                 Report.Printer.Stacktrace = true;
585                                 return true;
586                                 
587                         case "--linkresource":
588                         case "--linkres":
589                                 Report.Warning (-29, 1, "Compatibility: Use -linkres:VALUE instead of --linkres VALUE");
590                                 if ((i + 1) >= args.Length){
591                                         Usage ();
592                                         Report.Error (5, "Missing argument to --linkres"); 
593                                         Environment.Exit (1);
594                                 }
595
596                                 AddResource (new AssemblyResource (args[++i], args[i]));
597                                 return true;
598                                 
599                         case "--resource":
600                         case "--res":
601                                 Report.Warning (-29, 1, "Compatibility: Use -res:VALUE instead of --res VALUE");
602                                 if ((i + 1) >= args.Length){
603                                         Usage ();
604                                         Report.Error (5, "Missing argument to --resource"); 
605                                         Environment.Exit (1);
606                                 }
607
608                                 AddResource (new AssemblyResource (args[++i], args[i], true));
609                                 return true;
610                                 
611                         case "--target":
612                                 Report.Warning (-29, 1, "Compatibility: Use -target:KIND instead of --target KIND");
613                                 if ((i + 1) >= args.Length){
614                                         Environment.Exit (1);
615                                         return true;
616                                 }
617                                 
618                                 string type = args [++i];
619                                 switch (type){
620                                 case "library":
621                                         RootContext.Target = Target.Library;
622                                         RootContext.TargetExt = ".dll";
623                                         break;
624                                         
625                                 case "exe":
626                                         RootContext.Target = Target.Exe;
627                                         break;
628                                         
629                                 case "winexe":
630                                         RootContext.Target = Target.WinExe;
631                                         break;
632                                         
633                                 case "module":
634                                         RootContext.Target = Target.Module;
635                                         RootContext.TargetExt = ".dll";
636                                         break;
637                                 default:
638                                         TargetUsage ();
639                                         break;
640                                 }
641                                 return true;
642                                 
643                         case "-r":
644                                 Report.Warning (-29, 1, "Compatibility: Use -r:LIBRARY instead of -r library");
645                                 if ((i + 1) >= args.Length){
646                                         Usage ();
647                                         Environment.Exit (1);
648                                 }
649                                 
650                                 string val = args [++i];
651                                 int idx = val.IndexOf ('=');
652                                 if (idx > -1) {
653                                         string alias = val.Substring (0, idx);
654                                         string assembly = val.Substring (idx + 1);
655                                         AddAssemblyReference (alias, assembly);
656                                         return true;
657                                 }
658
659                                 AddAssemblyReference (val);
660                                 return true;
661                                 
662                         case "-L":
663                                 Report.Warning (-29, 1, "Compatibility: Use -lib:ARG instead of --L arg");
664                                 if ((i + 1) >= args.Length){
665                                         Usage ();       
666                                         Environment.Exit (1);
667                                 }
668                                 RootContext.ReferencesLookupPaths.Add (args [++i]);
669                                 return true;
670
671                         case "--lint":
672                                 RootContext.EnhancedWarnings = true;
673                                 return true;
674                                 
675                         case "--nostdlib":
676                                 Report.Warning (-29, 1, "Compatibility: Use -nostdlib instead of --nostdlib");
677                                 RootContext.StdLib = false;
678                                 return true;
679                                 
680                         case "--nowarn":
681                                 Report.Warning (-29, 1, "Compatibility: Use -nowarn instead of --nowarn");
682                                 if ((i + 1) >= args.Length){
683                                         Usage ();
684                                         Environment.Exit (1);
685                                 }
686                                 int warn = 0;
687                                 
688                                 try {
689                                         warn = Int32.Parse (args [++i]);
690                                 } catch {
691                                         Usage ();
692                                         Environment.Exit (1);
693                                 }
694                                 Report.SetIgnoreWarning (warn);
695                                 return true;
696
697                         case "--wlevel":
698                                 Report.Warning (-29, 1, "Compatibility: Use -warn:LEVEL instead of --wlevel LEVEL");
699                                 if ((i + 1) >= args.Length){
700                                         Report.Error (
701                                                 1900,
702                                                 "--wlevel requires a value from 0 to 4");
703                                         Environment.Exit (1);
704                                 }
705
706                                 SetWarningLevel (args [++i]);
707                                 return true;
708
709                         case "--mcs-debug":
710                                 if ((i + 1) >= args.Length){
711                                         Report.Error (5, "--mcs-debug requires an argument");
712                                         Environment.Exit (1);
713                                 }
714
715                                 try {
716                                         Report.DebugFlags = Int32.Parse (args [++i]);
717                                 } catch {
718                                         Report.Error (5, "Invalid argument to --mcs-debug");
719                                         Environment.Exit (1);
720                                 }
721                                 return true;
722                                 
723                         case "--about":
724                                 About ();
725                                 return true;
726                                 
727                         case "--recurse":
728                                 Report.Warning (-29, 1, "Compatibility: Use -recurse:PATTERN option instead --recurse PATTERN");
729                                 if ((i + 1) >= args.Length){
730                                         Report.Error (5, "--recurse requires an argument");
731                                         Environment.Exit (1);
732                                 }
733                                 ProcessSourceFiles (args [++i], true); 
734                                 return true;
735                                 
736                         case "--timestamp":
737                                 timestamps = true;
738                                 return true;
739
740                         case "--debug": case "-g":
741                                 Report.Warning (-29, 1, "Compatibility: Use -debug option instead of -g or --debug");
742                                 RootContext.GenerateDebugInfo = true;
743                                 return true;
744                                 
745                         case "--noconfig":
746                                 Report.Warning (-29, 1, "Compatibility: Use -noconfig option instead of --noconfig");
747                                 RootContext.LoadDefaultReferences = false;
748                                 return true;
749
750                         default:
751                                 if (arg.StartsWith ("--fatal")){
752                                         if (arg.StartsWith ("--fatal=")){
753                                                 if (!Int32.TryParse (arg.Substring (8), out fatal_errors))
754                                                         fatal_errors = 1;
755                                         } else
756                                                 fatal_errors = 1;
757                                         return true;
758                                 }
759                                 if (arg.StartsWith ("--runtime:", StringComparison.Ordinal)) {
760                                         string version = arg.Substring (10);
761
762                                         switch (version) {
763                                         case "v1":
764                                         case "V1":
765                                                 RootContext.StdLibRuntimeVersion = RuntimeVersion.v1;
766                                                 break;
767                                         case "v2":
768                                         case "V2":
769                                                 RootContext.StdLibRuntimeVersion = RuntimeVersion.v2;
770                                                 return true;
771                                         case "v4":
772                                         case "V4":
773                                                 RootContext.StdLibRuntimeVersion = RuntimeVersion.v4;
774                                                 return true;
775                                         }
776                                         return true;
777                                 }
778
779                                 break;
780                         }
781
782                         return false;
783                 }
784
785 #if !SMCS_SOURCE
786                 public static string GetPackageFlags (string packages, bool fatal, Report report)
787                 {
788                         ProcessStartInfo pi = new ProcessStartInfo ();
789                         pi.FileName = "pkg-config";
790                         pi.RedirectStandardOutput = true;
791                         pi.UseShellExecute = false;
792                         pi.Arguments = "--libs " + packages;
793                         Process p = null;
794                         try {
795                                 p = Process.Start (pi);
796                         } catch (Exception e) {
797                                 report.Error (-27, "Couldn't run pkg-config: " + e.Message);
798                                 if (fatal)
799                                         Environment.Exit (1);
800                                 p.Close ();
801                                 return null;
802                         }
803                         
804                         if (p.StandardOutput == null){
805                                 report.Warning (-27, 1, "Specified package did not return any information");
806                                 p.Close ();
807                                 return null;
808                         }
809                         string pkgout = p.StandardOutput.ReadToEnd ();
810                         p.WaitForExit ();
811                         if (p.ExitCode != 0) {
812                                 report.Error (-27, "Error running pkg-config. Check the above output.");
813                                 if (fatal)
814                                         Environment.Exit (1);
815                                 p.Close ();
816                                 return null;
817                         }
818                         p.Close ();
819
820                         return pkgout;
821                 }
822 #endif
823
824                 //
825                 // This parses the -arg and /arg options to the compiler, even if the strings
826                 // in the following text use "/arg" on the strings.
827                 //
828                 bool CSCParseOption (string option, ref string [] args)
829                 {
830                         int idx = option.IndexOf (':');
831                         string arg, value;
832
833                         if (idx == -1){
834                                 arg = option;
835                                 value = "";
836                         } else {
837                                 arg = option.Substring (0, idx);
838
839                                 value = option.Substring (idx + 1);
840                         }
841
842                         switch (arg.ToLowerInvariant ()){
843                         case "/nologo":
844                                 return true;
845
846                         case "/t":
847                         case "/target":
848                                 switch (value){
849                                 case "exe":
850                                         RootContext.Target = Target.Exe;
851                                         break;
852
853                                 case "winexe":
854                                         RootContext.Target = Target.WinExe;
855                                         break;
856
857                                 case "library":
858                                         RootContext.Target = Target.Library;
859                                         RootContext.TargetExt = ".dll";
860                                         break;
861
862                                 case "module":
863                                         RootContext.Target = Target.Module;
864                                         RootContext.TargetExt = ".netmodule";
865                                         break;
866
867                                 default:
868                                         TargetUsage ();
869                                         break;
870                                 }
871                                 return true;
872
873                         case "/out":
874                                 if (value.Length == 0) {
875                                         Error_RequiresFileName (option);
876                                         break;
877                                 }
878                                 RootContext.OutputFile = value;
879                                 return true;
880
881                         case "/o":
882                         case "/o+":
883                         case "/optimize":
884                         case "/optimize+":
885                                 RootContext.Optimize = true;
886                                 return true;
887
888                         case "/o-":
889                         case "/optimize-":
890                                 RootContext.Optimize = false;
891                                 return true;
892
893                         // TODO: Not supported by csc 3.5+
894                         case "/incremental":
895                         case "/incremental+":
896                         case "/incremental-":
897                                 // nothing.
898                                 return true;
899
900                         case "/d":
901                         case "/define": {
902                                 if (value.Length == 0){
903                                         Usage ();
904                                         Environment.Exit (1);
905                                 }
906
907                                 foreach (string d in value.Split (argument_value_separator)) {
908                                         string conditional = d.Trim ();
909                                         if (!Tokenizer.IsValidIdentifier (conditional)) {
910                                                 Report.Warning (2029, 1, "Invalid conditional define symbol `{0}'", conditional);
911                                                 continue;
912                                         }
913                                         RootContext.AddConditional (conditional);
914                                 }
915                                 return true;
916                         }
917
918                         case "/bugreport":
919                                 //
920                                 // We should collect data, runtime, etc and store in the file specified
921                                 //
922                                 Console.WriteLine ("To file bug reports, please visit: http://www.mono-project.com/Bugs");
923                                 return true;
924 #if !SMCS_SOURCE
925                         case "/pkg": {
926                                 string packages;
927
928                                 if (value.Length == 0){
929                                         Usage ();
930                                         Environment.Exit (1);
931                                 }
932                                 packages = String.Join (" ", value.Split (new Char [] { ';', ',', '\n', '\r'}));
933                                 string pkgout = GetPackageFlags (packages, true, Report);
934                                 
935                                 if (pkgout != null){
936                                         string [] xargs = pkgout.Trim (new Char [] {' ', '\n', '\r', '\t'}).
937                                                 Split (new Char [] { ' ', '\t'});
938                                         args = AddArgs (args, xargs);
939                                 }
940                                 
941                                 return true;
942                         }
943 #endif
944                         case "/linkres":
945                         case "/linkresource":
946                         case "/res":
947                         case "/resource":
948                                 AssemblyResource res = null;                    
949                                 string[] s = value.Split (argument_value_separator);
950                                 switch (s.Length) {
951                                 case 1:
952                                         if (s[0].Length == 0)
953                                                 goto default;
954                                         res = new AssemblyResource (s [0], Path.GetFileName (s[0]));
955                                         break;
956                                 case 2:
957                                         res = new AssemblyResource (s [0], s [1]);
958                                         break;
959                                 case 3:
960                                         if (s [2] != "public" && s [2] != "private") {
961                                                 Report.Error (1906, "Invalid resource visibility option `{0}'. Use either `public' or `private' instead", s [2]);
962                                                 return true;
963                                         }
964                                         res = new AssemblyResource (s[0], s[1], s[2] == "private");
965                                         break;
966                                 default:
967                                         Report.Error (-2005, "Wrong number of arguments for option `{0}'", option);
968                                         break;
969                                 }
970
971                                 if (res != null) {
972                                         res.IsEmbeded = arg [1] == 'r' || arg [1] == 'R';
973                                         AddResource (res);
974                                 }
975
976                                 return true;
977                                 
978                         case "/recurse":
979                                 if (value.Length == 0) {
980                                         Error_RequiresFileName (option);
981                                         break;
982                                 }
983                                 ProcessSourceFiles (value, true); 
984                                 return true;
985
986                         case "/r":
987                         case "/reference": {
988                                 if (value.Length == 0) {
989                                         Error_RequiresFileName (option);
990                                         break;
991                                 }
992
993                                 string[] refs = value.Split (argument_value_separator);
994                                 foreach (string r in refs){
995                                         if (r.Length == 0)
996                                                 continue;
997
998                                         string val = r;
999                                         int index = val.IndexOf ('=');
1000                                         if (index > -1) {
1001                                                 string alias = r.Substring (0, index);
1002                                                 string assembly = r.Substring (index + 1);
1003                                                 AddAssemblyReference (alias, assembly);
1004                                                 if (refs.Length != 1) {
1005                                                         Report.Error (2034, "Cannot specify multiple aliases using single /reference option");
1006                                                         break;
1007                                                 }
1008                                         } else {
1009                                                 AddAssemblyReference (val);
1010                                         }
1011                                 }
1012                                 return true;
1013                         }
1014                         case "/addmodule": {
1015                                 if (value.Length == 0) {
1016                                         Error_RequiresFileName (option);
1017                                         break;
1018                                 }
1019
1020                                 string[] refs = value.Split (argument_value_separator);
1021                                 foreach (string r in refs){
1022                                         RootContext.Modules.Add (r);
1023                                 }
1024                                 return true;
1025                         }
1026                         case "/win32res": {
1027                                 if (value.Length == 0) {
1028                                         Error_RequiresFileName (option);
1029                                         break;
1030                                 }
1031                                 
1032                                 if (RootContext.Win32IconFile != null)
1033                                         Report.Error (1565, "Cannot specify the `win32res' and the `win32ico' compiler option at the same time");
1034
1035                                 RootContext.Win32ResourceFile = value;
1036                                 return true;
1037                         }
1038                         case "/win32icon": {
1039                                 if (value.Length == 0) {
1040                                         Error_RequiresFileName (option);
1041                                         break;
1042                                 }
1043
1044                                 if (RootContext.Win32ResourceFile != null)
1045                                         Report.Error (1565, "Cannot specify the `win32res' and the `win32ico' compiler option at the same time");
1046
1047                                 RootContext.Win32IconFile = value;
1048                                 return true;
1049                         }
1050                         case "/doc": {
1051                                 if (value.Length == 0) {
1052                                         Error_RequiresFileName (option);
1053                                         break;
1054                                 }
1055
1056                                 RootContext.Documentation = new Documentation (value);
1057                                 return true;
1058                         }
1059                         case "/lib": {
1060                                 string [] libdirs;
1061                                 
1062                                 if (value.Length == 0) {
1063                                         Error_RequiresFileName (option);
1064                                         break;
1065                                 }
1066
1067                                 libdirs = value.Split (argument_value_separator);
1068                                 foreach (string dir in libdirs)
1069                                         RootContext.ReferencesLookupPaths.Add (dir);
1070                                 return true;
1071                         }
1072
1073                         case "/debug-":
1074                                 RootContext.GenerateDebugInfo = false;
1075                                 return true;
1076                                 
1077                         case "/debug":
1078                                 if (value == "full" || value == "")
1079                                         RootContext.GenerateDebugInfo = true;
1080
1081                                 return true;
1082                                 
1083                         case "/debug+":
1084                                 RootContext.GenerateDebugInfo = true;
1085                                 return true;
1086
1087                         case "/checked":
1088                         case "/checked+":
1089                                 RootContext.Checked = true;
1090                                 return true;
1091
1092                         case "/checked-":
1093                                 RootContext.Checked = false;
1094                                 return true;
1095
1096                         case "/clscheck":
1097                         case "/clscheck+":
1098                                 RootContext.VerifyClsCompliance = true;
1099                                 return true;
1100
1101                         case "/clscheck-":
1102                                 RootContext.VerifyClsCompliance = false;
1103                                 return true;
1104
1105                         case "/unsafe":
1106                         case "/unsafe+":
1107                                 RootContext.Unsafe = true;
1108                                 return true;
1109
1110                         case "/unsafe-":
1111                                 RootContext.Unsafe = false;
1112                                 return true;
1113
1114                         case "/warnaserror":
1115                         case "/warnaserror+":
1116                                 if (value.Length == 0) {
1117                                         Report.WarningsAreErrors = true;
1118                                 } else {
1119                                         foreach (string wid in value.Split (argument_value_separator))
1120                                                 Report.AddWarningAsError (wid);
1121                                 }
1122                                 return true;
1123
1124                         case "/warnaserror-":
1125                                 if (value.Length == 0) {
1126                                         Report.WarningsAreErrors = false;
1127                                 } else {
1128                                         foreach (string wid in value.Split (argument_value_separator))
1129                                                 Report.RemoveWarningAsError (wid);
1130                                 }
1131                                 return true;
1132
1133                         case "/warn":
1134                                 if (value.Length == 0) {
1135                                         Error_RequiresArgument (option);
1136                                         break;
1137                                 }
1138
1139                                 SetWarningLevel (value);
1140                                 return true;
1141
1142                         case "/nowarn": {
1143                                 if (value.Length == 0){
1144                                         Error_RequiresArgument (option);
1145                                         break;
1146                                 }
1147
1148                                 var warns = value.Split (argument_value_separator);
1149                                 foreach (string wc in warns){
1150                                         try {
1151                                                 if (wc.Trim ().Length == 0)
1152                                                         continue;
1153
1154                                                 int warn = Int32.Parse (wc);
1155                                                 if (warn < 1) {
1156                                                         throw new ArgumentOutOfRangeException("warn");
1157                                                 }
1158                                                 Report.SetIgnoreWarning (warn);
1159                                         } catch {
1160                                                 Report.Error (1904, "`{0}' is not a valid warning number", wc);
1161                                         }
1162                                 }
1163                                 return true;
1164                         }
1165
1166                         case "/noconfig":
1167                                 RootContext.LoadDefaultReferences = false;
1168                                 return true;
1169
1170                         case "/platform":
1171                                 if (value.Length == 0) {
1172                                         Error_RequiresArgument (option);
1173                                         break;
1174                                 }
1175
1176                                 switch (value.ToLower (CultureInfo.InvariantCulture)) {
1177                                 case "anycpu":
1178                                         RootContext.Platform = Platform.AnyCPU;
1179                                         break;
1180                                 case "x86":
1181                                         RootContext.Platform = Platform.X86;
1182                                         break;
1183                                 case "x64":
1184                                         RootContext.Platform = Platform.X64;
1185                                         break;
1186                                 case "itanium":
1187                                         RootContext.Platform = Platform.IA64;
1188                                         break;
1189                                 default:
1190                                         Report.Error (1672, "Invalid platform type for -platform. Valid options are `anycpu', `x86', `x64' or `itanium'");
1191                                         break;
1192                                 }
1193
1194                                 return true;
1195
1196                                 // We just ignore this.
1197                         case "/errorreport":
1198                         case "/filealign":
1199                                 if (value.Length == 0) {
1200                                         Error_RequiresArgument (option);
1201                                         break;
1202                                 }
1203
1204                                 return true;
1205                                 
1206                         case "/helpinternal":
1207                                 OtherFlags ();
1208                                 Environment.Exit(0);
1209                                 return true;
1210                                 
1211                         case "/help":
1212                         case "/?":
1213                                 Usage ();
1214                                 Environment.Exit (0);
1215                                 return true;
1216
1217                         case "/main":
1218                         case "/m":
1219                                 if (value.Length == 0){
1220                                         Error_RequiresArgument (option);
1221                                         break;
1222                                 }
1223                                 RootContext.MainClass = value;
1224                                 return true;
1225
1226                         case "/nostdlib":
1227                         case "/nostdlib+":
1228                                 RootContext.StdLib = false;
1229                                 return true;
1230
1231                         case "/nostdlib-":
1232                                 RootContext.StdLib = true;
1233                                 return true;
1234
1235                         case "/fullpaths":
1236                                 return true;
1237
1238                         case "/keyfile":
1239                                 if (value.Length == 0) {
1240                                         Error_RequiresFileName (option);
1241                                         break;
1242                                 }
1243
1244                                 RootContext.StrongNameKeyFile = value;
1245                                 return true;
1246
1247                         case "/keycontainer":
1248                                 if (value.Length == 0) {
1249                                         Error_RequiresArgument (option);
1250                                         break;
1251                                 }
1252
1253                                 RootContext.StrongNameKeyContainer = value;
1254                                 return true;
1255                         case "/delaysign+":
1256                         case "/delaysign":
1257                                 RootContext.StrongNameDelaySign = true;
1258                                 return true;
1259                         case "/delaysign-":
1260                                 RootContext.StrongNameDelaySign = false;
1261                                 return true;
1262
1263                         case "/langversion":
1264                                 if (value.Length == 0) {
1265                                         Error_RequiresArgument (option);
1266                                         break;
1267                                 }
1268
1269                                 switch (value.ToLowerInvariant ()) {
1270                                 case "iso-1":
1271                                         RootContext.Version = LanguageVersion.ISO_1;
1272                                         return true;    
1273                                 case "default":
1274                                         RootContext.Version = LanguageVersion.Default;
1275                                         RootContext.AddConditional ("__V2__");
1276                                         return true;
1277                                 case "iso-2":
1278                                         RootContext.Version = LanguageVersion.ISO_2;
1279                                         return true;
1280                                 case "3":
1281                                         RootContext.Version = LanguageVersion.V_3;
1282                                         return true;
1283                                 case "future":
1284                                         RootContext.Version = LanguageVersion.Future;
1285                                         return true;
1286                                 }
1287
1288                                 Report.Error (1617, "Invalid -langversion option `{0}'. It must be `ISO-1', `ISO-2', `3' or `Default'", value);
1289                                 return true;
1290
1291                         case "/codepage":
1292                                 if (value.Length == 0) {
1293                                         Error_RequiresArgument (option);
1294                                         break;
1295                                 }
1296
1297                                 switch (value) {
1298                                 case "utf8":
1299                                         RootContext.Encoding = new UTF8Encoding();
1300                                         break;
1301                                 case "reset":
1302                                         RootContext.Encoding = Encoding.Default;
1303                                         break;
1304                                 default:
1305                                         try {
1306                                                 RootContext.Encoding = Encoding.GetEncoding (Int32.Parse (value));
1307                                         } catch {
1308                                                 Report.Error (2016, "Code page `{0}' is invalid or not installed", value);
1309                                         }
1310                                         break;
1311                                 }
1312                                 return true;
1313
1314                         default:
1315                                 return false;
1316                         }
1317
1318                         return true;
1319                 }
1320
1321                 void Error_WrongOption (string option)
1322                 {
1323                         Report.Error (2007, "Unrecognized command-line option: `{0}'", option);
1324                 }
1325
1326                 void Error_RequiresFileName (string option)
1327                 {
1328                         Report.Error (2005, "Missing file specification for `{0}' option", option);
1329                 }
1330
1331                 void Error_RequiresArgument (string option)
1332                 {
1333                         Report.Error (2006, "Missing argument for `{0}' option", option);
1334                 }
1335
1336                 static string [] AddArgs (string [] args, string [] extra_args)
1337                 {
1338                         string [] new_args;
1339                         new_args = new string [extra_args.Length + args.Length];
1340
1341                         // if args contains '--' we have to take that into account
1342                         // split args into first half and second half based on '--'
1343                         // and add the extra_args before --
1344                         int split_position = Array.IndexOf (args, "--");
1345                         if (split_position != -1)
1346                         {
1347                                 Array.Copy (args, new_args, split_position);
1348                                 extra_args.CopyTo (new_args, split_position);
1349                                 Array.Copy (args, split_position, new_args, split_position + extra_args.Length, args.Length - split_position);
1350                         }
1351                         else
1352                         {
1353                                 args.CopyTo (new_args, 0);
1354                                 extra_args.CopyTo (new_args, args.Length);
1355                         }
1356
1357                         return new_args;
1358                 }
1359
1360                 void AddAssemblyReference (string assembly)
1361                 {
1362                         RootContext.AssemblyReferences.Add (assembly);
1363                 }
1364
1365                 void AddAssemblyReference (string alias, string assembly)
1366                 {
1367                         if (assembly.Length == 0) {
1368                                 Report.Error (1680, "Invalid reference alias `{0}='. Missing filename", alias);
1369                                 return;
1370                         }
1371
1372                         if (!IsExternAliasValid (alias)) {
1373                                 Report.Error (1679, "Invalid extern alias for -reference. Alias `{0}' is not a valid identifier", alias);
1374                                 return;
1375                         }
1376
1377                         RootContext.AssemblyReferencesAliases.Add (Tuple.Create (alias, assembly));
1378                 }
1379
1380                 void AddResource (AssemblyResource res)
1381                 {
1382                         if (RootContext.Resources == null) {
1383                                 RootContext.Resources = new List<AssemblyResource> ();
1384                                 RootContext.Resources.Add (res);
1385                                 return;
1386                         }
1387
1388                         if (RootContext.Resources.Contains (res)) {
1389                                 ctx.Report.Error (1508, "The resource identifier `{0}' has already been used in this assembly", res.Name);
1390                                 return;
1391                         }
1392
1393                         RootContext.Resources.Add (res);
1394                 }
1395                 
1396                 static bool IsExternAliasValid (string identifier)
1397                 {
1398                         if (identifier.Length == 0)
1399                                 return false;
1400                         if (identifier [0] != '_' && !Char.IsLetter (identifier [0]))
1401                                 return false;
1402
1403                         for (int i = 1; i < identifier.Length; i++) {
1404                                 char c = identifier [i];
1405                                 if (Char.IsLetter (c) || Char.IsDigit (c))
1406                                         continue;
1407
1408                                 UnicodeCategory category = Char.GetUnicodeCategory (c);
1409                                 if (category != UnicodeCategory.Format || category != UnicodeCategory.NonSpacingMark ||
1410                                                 category != UnicodeCategory.SpacingCombiningMark ||
1411                                                 category != UnicodeCategory.ConnectorPunctuation)
1412                                         return false;
1413                         }
1414                         
1415                         return true;
1416                 }
1417
1418                 //
1419                 // Main compilation method
1420                 //
1421                 public bool Compile ()
1422                 {
1423                         var module = new ModuleContainer (ctx);
1424                         RootContext.ToplevelTypes = module;
1425
1426                         if (timestamps) {
1427                                 stopwatch = Stopwatch.StartNew ();
1428                                 first_time = DateTime.Now;
1429                         }
1430
1431                         Parse (module);
1432                         ShowTime ("Parsing source files");
1433
1434                         if (Report.Errors > 0)
1435                                 return false;
1436
1437                         if (RootContext.TokenizeOnly || RootContext.ParseOnly)
1438                                 return true;
1439
1440                         if (RootContext.ToplevelTypes.NamespaceEntry != null)
1441                                 throw new InternalErrorException ("who set it?");
1442
1443                         //
1444                         // Quick hack
1445                         //
1446                         var output_file = RootContext.OutputFile;
1447                         string output_file_name;
1448                         if (output_file == null) {
1449                                 if (first_source == null) {
1450                                         Report.Error (1562, "If no source files are specified you must specify the output file with -out:");
1451                                         return false;
1452                                 }
1453
1454                                 int pos = first_source.LastIndexOf ('.');
1455
1456                                 if (pos > 0)
1457                                         output_file = first_source.Substring (0, pos) + RootContext.TargetExt;
1458                                 else
1459                                         output_file = first_source + RootContext.TargetExt;
1460
1461                                 output_file_name = output_file;
1462                         } else {
1463                                 output_file_name = Path.GetFileName (output_file);
1464                         }
1465
1466                         //
1467                         // Load assemblies required
1468                         //
1469                         if (timestamps)
1470                                 stopwatch = Stopwatch.StartNew ();
1471
1472 #if STATIC
1473                         var assembly = new AssemblyDefinitionStatic (module, output_file_name, output_file);
1474                         module.SetDeclaringAssembly (assembly);
1475
1476                         var importer = new StaticImporter ();
1477                         assembly.Importer = importer;
1478
1479                         var loader = new StaticLoader (importer, ctx);
1480                         loader.LoadReferences (module);
1481
1482                         ShowTime ("Imporing referenced assemblies");
1483
1484                         if (!ctx.BuildinTypes.CheckDefinitions (module))
1485                                 return false;
1486
1487                         ShowTime ("Initializing predefined types");
1488
1489                         if (!assembly.Create (loader.Domain))
1490                                 return false;
1491
1492                         // System.Object was not loaded, use compiled assembly as corlib
1493                         if (loader.Corlib == null)
1494                                 loader.Corlib = assembly.Builder;
1495
1496                         loader.LoadModules (assembly, module.GlobalRootNamespace);
1497 #else
1498                         var assembly = new AssemblyDefinitionDynamic (module, output_file_name, output_file);
1499                         module.SetDeclaringAssembly (assembly);
1500
1501                         var importer = new ReflectionImporter (ctx.BuildinTypes);
1502                         assembly.Importer = importer;
1503
1504                         var loader = new DynamicLoader (importer, ctx);
1505                         loader.LoadReferences (module);
1506
1507                         ShowTime ("Imporing referenced assemblies");
1508
1509                         if (!ctx.BuildinTypes.CheckDefinitions (module))
1510                                 return false;
1511
1512                         ShowTime ("Initializing predefined types");
1513
1514                         if (!assembly.Create (AppDomain.CurrentDomain, AssemblyBuilderAccess.Save))
1515                                 return false;
1516
1517                         loader.LoadModules (assembly, module.GlobalRootNamespace);
1518 #endif
1519                         module.Define ();
1520
1521                         ShowTime ("Types definition");
1522
1523                         if (Report.Errors > 0)
1524                                 return false;
1525
1526                         if (Report.Errors == 0 &&
1527                                 RootContext.Documentation != null &&
1528                                 !RootContext.Documentation.OutputDocComment (
1529                                         output_file, Report))
1530                                 return false;
1531
1532                         //
1533                         // Verify using aliases now
1534                         //
1535                         NamespaceEntry.VerifyAllUsing ();
1536                         
1537                         if (Report.Errors > 0){
1538                                 return false;
1539                         }
1540
1541                         assembly.Resolve ();
1542                         
1543                         if (Report.Errors > 0)
1544                                 return false;
1545                         
1546                         //
1547                         // The code generator
1548                         //
1549                         if (timestamps)
1550                                 stopwatch = Stopwatch.StartNew ();
1551
1552                         assembly.Emit ();
1553
1554                         ShowTime ("Resolving and emitting members blocks");
1555
1556                         if (Report.Errors > 0){
1557                                 return false;
1558                         }
1559
1560                         module.CloseType ();
1561
1562                         ShowTime ("Closing types");
1563
1564                         if (timestamps)
1565                                 stopwatch = Stopwatch.StartNew ();
1566
1567                         assembly.EmbedResources ();
1568                         ShowTime ("Embedding resources");
1569
1570                         if (Report.Errors > 0)
1571                                 return false;
1572
1573                         if (timestamps)
1574                                 stopwatch = Stopwatch.StartNew ();
1575                         
1576                         assembly.Save ();
1577
1578 #if STATIC
1579                         loader.Dispose ();
1580 #endif
1581
1582                         ShowTime ("Saving output assembly");
1583
1584                         ShowTotalTime ("Total");
1585
1586                         Timer.ShowTimers ();
1587
1588                         return (Report.Errors == 0);
1589                 }
1590         }
1591
1592         //
1593         // This is the only public entry point
1594         //
1595         public class CompilerCallableEntryPoint : MarshalByRefObject {
1596                 public static bool InvokeCompiler (string [] args, TextWriter error)
1597                 {
1598                         try {
1599                                 StreamReportPrinter srp = new StreamReportPrinter (error);
1600                                 Driver d = Driver.Create (args, true, srp);
1601                                 if (d == null)
1602                                         return false;
1603
1604                                 return d.Compile () && srp.ErrorsCount == 0;
1605                         } finally {
1606                                 Reset ();
1607                         }
1608                 }
1609
1610                 public static int[] AllWarningNumbers {
1611                         get {
1612                                 return Report.AllWarnings;
1613                         }
1614                 }
1615
1616                 public static void Reset ()
1617                 {
1618                         Reset (true);
1619                 }
1620
1621                 public static void PartialReset ()
1622                 {
1623                         Reset (false);
1624                 }
1625                 
1626                 public static void Reset (bool full_flag)
1627                 {
1628                         CSharpParser.yacc_verbose_flag = 0;
1629                         Location.Reset ();
1630
1631                         if (!full_flag)
1632                                 return;
1633
1634                         RootContext.Reset (full_flag);
1635                         TypeManager.Reset ();
1636                         ArrayContainer.Reset ();
1637                         ReferenceContainer.Reset ();
1638                         PointerContainer.Reset ();
1639                         Parameter.Reset ();
1640
1641                         Unary.Reset ();
1642                         UnaryMutator.Reset ();
1643                         Binary.Reset ();
1644                         ConstantFold.Reset ();
1645                         CastFromDecimal.Reset ();
1646                         StringConcat.Reset ();
1647                         
1648                         NamespaceEntry.Reset ();
1649                         Attribute.Reset ();
1650                         AnonymousTypeClass.Reset ();
1651                         AnonymousMethodBody.Reset ();
1652                         AnonymousMethodStorey.Reset ();
1653                         SymbolWriter.Reset ();
1654                         Switch.Reset ();
1655                         Linq.QueryBlock.TransparentParameter.Reset ();
1656                         Convert.Reset ();
1657                         TypeInfo.Reset ();
1658                 }
1659         }
1660 }