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