2004-03-25 Sebastien Pouliot <sebastien@ximian.com>
[mono.git] / mcs / mcs / driver.cs
1 //
2 // driver.cs: The compiler command line driver.
3 //
4 // Author: Miguel de Icaza (miguel@gnu.org)
5 //
6 // Licensed under the terms of the GNU GPL
7 //
8 // (C) 2001, 2002, 2003 Ximian, Inc (http://www.ximian.com)
9 //
10
11 namespace Mono.CSharp
12 {
13         using System;
14         using System.Reflection;
15         using System.Reflection.Emit;
16         using System.Collections;
17         using System.IO;
18         using System.Text;
19         using System.Globalization;
20         using Mono.Languages;
21
22         public enum Target {
23                 Library, Exe, Module, WinExe
24         };
25         
26         /// <summary>
27         ///    The compiler driver.
28         /// </summary>
29         public class Driver
30         {
31                 
32                 //
33                 // Assemblies references to be linked.   Initialized with
34                 // mscorlib.dll here.
35                 static ArrayList references;
36
37                 //
38                 // If any of these fail, we ignore the problem.  This is so
39                 // that we can list all the assemblies in Windows and not fail
40                 // if they are missing on Linux.
41                 //
42                 static ArrayList soft_references;
43
44                 //
45                 // Modules to be linked
46                 //
47                 static ArrayList modules;
48
49                 // Lookup paths
50                 static ArrayList link_paths;
51
52                 // Whether we want Yacc to output its progress
53                 static bool yacc_verbose = false;
54
55                 // Whether we want to only run the tokenizer
56                 static bool tokenize = false;
57                 
58                 static string first_source;
59
60                 static bool want_debugging_support = false;
61
62                 static bool parse_only = false;
63                 static bool timestamps = false;
64                 static bool pause = false;
65                 static bool show_counters = false;
66                 public static bool parser_verbose = false;
67                 
68                 //
69                 // Whether to load the initial config file (what CSC.RSP has by default)
70                 // 
71                 static bool load_default_config = true;
72
73                 static Hashtable response_file_list;
74
75                 //
76                 // A list of resource files
77                 //
78                 static ArrayList resources;
79                 static ArrayList embedded_resources;
80                 static string win32ResourceFile;
81                 static string win32IconFile;
82
83                 //
84                 // An array of the defines from the command line
85                 //
86                 static ArrayList defines;
87
88                 //
89                 // Output file
90                 //
91                 static string output_file = null;
92
93                 //
94                 // Last time we took the time
95                 //
96                 static DateTime last_time, first_time;
97
98                 //
99                 // Encoding: ISO-Latin1 is 28591
100                 //
101                 static Encoding encoding;
102
103                 //
104                 // Whether the user has specified a different encoder manually
105                 //
106                 static bool using_default_encoder = true;
107                 
108                 public static void ShowTime (string msg)
109                 {
110                         if (!timestamps)
111                                 return;
112
113                         DateTime now = DateTime.Now;
114                         TimeSpan span = now - last_time;
115                         last_time = now;
116
117                         Console.WriteLine (
118                                 "[{0:00}:{1:000}] {2}",
119                                 (int) span.TotalSeconds, span.Milliseconds, msg);
120                 }
121
122                 public static void ShowTotalTime (string msg)
123                 {
124                         if (!timestamps)
125                                 return;
126
127                         DateTime now = DateTime.Now;
128                         TimeSpan span = now - first_time;
129                         last_time = now;
130
131                         Console.WriteLine (
132                                 "[{0:00}:{1:000}] {2}",
133                                 (int) span.TotalSeconds, span.Milliseconds, msg);
134                 }              
135                
136                 static void tokenize_file (SourceFile file)
137                 {
138                         Stream input;
139
140                         try {
141                                 input = File.OpenRead (file.Name);
142                         } catch {
143                                 Report.Error (2001, "Source file '" + file.Name + "' could not be opened");
144                                 return;
145                         }
146
147                         using (input){
148                                 SeekableStreamReader reader = new SeekableStreamReader (input, encoding, using_default_encoder);
149                                 Tokenizer lexer = new Tokenizer (reader, file, defines);
150                                 int token, tokens = 0, errors = 0;
151
152                                 while ((token = lexer.token ()) != Token.EOF){
153                                         tokens++;
154                                         if (token == Token.ERROR)
155                                                 errors++;
156                                 }
157                                 Console.WriteLine ("Tokenized: " + tokens + " found " + errors + " errors");
158                         }
159                         
160                         return;
161                 }
162
163                 // MonoTODO("Change error code for aborted compilation to something reasonable")]               
164                 static void parse (SourceFile file)
165                 {
166                         CSharpParser parser;
167                         Stream input;
168
169                         try {
170                                 input = File.OpenRead (file.Name);
171                         } catch {
172                                 Report.Error (2001, "Source file '" + file.Name + "' could not be opened");
173                                 return;
174                         }
175
176                         SeekableStreamReader reader = new SeekableStreamReader (input, encoding, using_default_encoder);
177                                 
178                         parser = new CSharpParser (reader, file, defines);
179                         parser.yacc_verbose = yacc_verbose;
180                         try {
181                                 parser.parse ();
182                         } catch (Exception ex) {
183                                 Report.Error(666, "Compilation aborted: " + ex);
184                         } finally {
185                                 input.Close ();
186                         }
187                 }
188                 
189                 static void Usage ()
190                 {
191                         Console.WriteLine (
192                                 "Mono C# compiler, (C) 2001 - 2003 Ximian, Inc.\n" +
193                                 "mcs [options] source-files\n" +
194                                 "   --about            About the Mono C# compiler\n" +
195                                 "   -checked[+|-]      Set default context to checked\n" +
196                                 "   -codepage:ID       Sets code page to the one in ID\n" +
197                                 "                      (number, `utf8' or `reset')\n" +
198                                 "   -define:S1[;S2]    Defines one or more symbols (short: /d:)\n" +
199                                 "   -debug[+|-]        Generate debugging information\n" + 
200                                 "   -delaysign[+|-]    Only insert the public key into the assembly (no signing)\n" +
201                                 "   -doc:FILE          XML Documentation file to generate\n" + 
202                                 "   -g                 Generate debugging information\n" +
203                                 "   --fatal            Makes errors fatal\n" +
204                                 "   -keycontainer:NAME The key pair container used to strongname the assembly\n" +
205                                 "   -keyfile:FILE      The strongname key file used to strongname the assembly\n" +
206                                 "   -lib:PATH1,PATH2   Adds the paths to the assembly link path\n" +
207                                 "   -main:class        Specified the class that contains the entry point\n" +
208                                 "   -noconfig[+|-]     Disables implicit references to assemblies\n" +
209                                 "   -nostdlib[+|-]     Does not load core libraries\n" +
210                                 "   -nowarn:W1[,W2]    Disables one or more warnings\n" + 
211                                 "   -out:FNAME         Specifies output file\n" +
212                                 "   --parse            Only parses the source file\n" +
213                                 "   --expect-error X   Expect that error X will be encountered\n" +
214                                 "   -recurse:SPEC      Recursively compiles the files in SPEC ([dir]/file)\n" + 
215                                 "   -reference:ASS     References the specified assembly (-r:ASS)\n" +
216                                 "   --stacktrace       Shows stack trace at error location\n" +
217                                 "   -target:KIND       Specifies the target (KIND is one of: exe, winexe,\n" +
218                                 "                      library, module), (short: /t:)\n" +
219                                 "   --timestamp        Displays time stamps of various compiler events\n" +
220                                 "   -unsafe[+|-]       Allows unsafe code\n" +
221                                 "   -warnaserror[+|-]  Treat warnings as errors\n" +
222                                 "   -warn:LEVEL        Sets warning level (the highest is 4, the default is 2)\n" +
223                                 "   -v                 Verbose parsing (for debugging the parser)\n" +
224                                 "   -2                 Enables experimental C# features\n" +
225                                 "\n" +
226                                 "Resources:\n" +
227                                 "   -linkresource:FILE[,ID] Links FILE as a resource\n" +
228                                 "   -resource:FILE[,ID]     Embed FILE as a resource\n" +
229                                 "   -win32res:FILE          Specifies Win32 resource file (.res)\n" +
230                                 "   -win32icon:FILE         Use this icon for the output\n" +
231                                 "   --mcs-debug X      Sets MCS debugging level to X\n" +
232                                 "   @file              Read response file for more options\n\n" +
233                                 "Options can be of the form -option or /option");
234                 }
235
236                 static void TargetUsage ()
237                 {
238                         Report.Error (2019, "Valid options for -target: are exe, winexe, library or module");
239                 }
240                 
241                 static void About ()
242                 {
243                         Console.WriteLine (
244                                 "The Mono C# compiler is (C) 2001, 2002, 2003 Ximian, Inc.\n\n" +
245                                 "The compiler source code is released under the terms of the GNU GPL\n\n" +
246
247                                 "For more information on Mono, visit the project Web site\n" +
248                                 "   http://www.go-mono.com\n\n" +
249
250                                 "The compiler was written by Miguel de Icaza, Ravi Pratap and Martin Baulig");
251                         Environment.Exit (0);
252                 }
253
254                 public static int counter1, counter2;
255                 
256                 public static int Main (string[] args)
257                 {
258                         bool ok = MainDriver (args);
259                         
260                         if (ok && Report.Errors == 0) {
261                                 Console.Write("Compilation succeeded");
262                                 if (Report.Warnings > 0) {
263                                         Console.Write(" - {0} warning(s)", Report.Warnings);
264                                 }
265                                 Console.WriteLine();
266                                 if (show_counters){
267                                         Console.WriteLine ("Counter1: " + counter1);
268                                         Console.WriteLine ("Counter2: " + counter2);
269                                 }
270                                 if (pause)
271                                         Console.ReadLine ();
272                                 return 0;
273                         } else {
274                                 Console.WriteLine("Compilation failed: {0} error(s), {1} warnings",
275                                         Report.Errors, Report.Warnings);
276                                 return 1;
277                         }
278                 }
279
280                 static public void LoadAssembly (string assembly, bool soft)
281                 {
282                         Assembly a;
283                         string total_log = "";
284
285                         try {
286                                 char[] path_chars = { '/', '\\', '.' };
287
288                                 if (assembly.IndexOfAny (path_chars) != -1) {
289                                         a = Assembly.LoadFrom (assembly);
290                                 } else {
291                                         a = Assembly.Load (assembly);
292                                 }
293                                 TypeManager.AddAssembly (a);
294
295                         } catch (FileNotFoundException){
296                                 foreach (string dir in link_paths){
297                                         string full_path = Path.Combine (dir, assembly);
298                                         if (!assembly.EndsWith (".dll"))
299                                                 full_path += ".dll";
300
301                                         try {
302                                                 a = Assembly.LoadFrom (full_path);
303                                                 TypeManager.AddAssembly (a);
304                                                 return;
305                                         } catch (FileNotFoundException ff) {
306                                                 total_log += ff.FusionLog;
307                                                 continue;
308                                         }
309                                 }
310                                 if (!soft) {
311                                         Report.Error (6, "Cannot find assembly `" + assembly + "'" );
312                                         Console.WriteLine ("Log: \n" + total_log);
313                                 }
314                         } catch (BadImageFormatException f) {
315                                 Report.Error(6, "Cannot load assembly (bad file format)" + f.FusionLog);
316                         } catch (FileLoadException f){
317                                 Report.Error(6, "Cannot load assembly " + f.FusionLog);
318                         } catch (ArgumentNullException){
319                                 Report.Error(6, "Cannot load assembly (null argument)");
320                         }
321                 }
322
323                 static public void LoadModule (MethodInfo adder_method, string module)
324                 {
325                         Module m;
326                         string total_log = "";
327
328                         try {
329                                 try {
330                                         m = (Module)adder_method.Invoke (CodeGen.Assembly.Builder, new object [] { module });
331                                 }
332                                 catch (TargetInvocationException ex) {
333                                         throw ex.InnerException;
334                                 }
335                                 TypeManager.AddModule (m);
336
337                         } 
338                         catch (FileNotFoundException){
339                                 foreach (string dir in link_paths){
340                                         string full_path = Path.Combine (dir, module);
341                                         if (!module.EndsWith (".netmodule"))
342                                                 full_path += ".netmodule";
343
344                                         try {
345                                                 try {
346                                                         m = (Module)adder_method.Invoke (CodeGen.Assembly.Builder, new object [] { full_path });
347                                                 }
348                                                 catch (TargetInvocationException ex) {
349                                                         throw ex.InnerException;
350                                                 }
351                                                 TypeManager.AddModule (m);
352                                                 return;
353                                         } catch (FileNotFoundException ff) {
354                                                 total_log += ff.FusionLog;
355                                                 continue;
356                                         }
357                                 }
358                                 Report.Error (6, "Cannot find module `" + module + "'" );
359                                 Console.WriteLine ("Log: \n" + total_log);
360                         } catch (BadImageFormatException f) {
361                                 Report.Error(6, "Cannot load module (bad file format)" + f.FusionLog);
362                         } catch (FileLoadException f){
363                                 Report.Error(6, "Cannot load module " + f.FusionLog);
364                         } catch (ArgumentNullException){
365                                 Report.Error(6, "Cannot load module (null argument)");
366                         }
367                 }
368
369                 /// <summary>
370                 ///   Loads all assemblies referenced on the command line
371                 /// </summary>
372                 static public void LoadReferences ()
373                 {
374                         foreach (string r in references)
375                                 LoadAssembly (r, false);
376
377                         foreach (string r in soft_references)
378                                 LoadAssembly (r, true);
379                         
380                         return;
381                 }
382
383                 static void SetupDefaultDefines ()
384                 {
385                         defines = new ArrayList ();
386                         defines.Add ("__MonoCS__");
387                 }
388
389                 static string [] LoadArgs (string file)
390                 {
391                         StreamReader f;
392                         ArrayList args = new ArrayList ();
393                         string line;
394                         try {
395                                 f = new StreamReader (file);
396                         } catch {
397                                 return null;
398                         }
399
400                         StringBuilder sb = new StringBuilder ();
401                         
402                         while ((line = f.ReadLine ()) != null){
403                                 int t = line.Length;
404
405                                 for (int i = 0; i < t; i++){
406                                         char c = line [i];
407                                         
408                                         if (c == '"' || c == '\''){
409                                                 char end = c;
410                                                 
411                                                 for (i++; i < t; i++){
412                                                         c = line [i];
413
414                                                         if (c == end)
415                                                                 break;
416                                                         sb.Append (c);
417                                                 }
418                                         } else if (c == ' '){
419                                                 if (sb.Length > 0){
420                                                         args.Add (sb.ToString ());
421                                                         sb.Length = 0;
422                                                 }
423                                         } else
424                                                 sb.Append (c);
425                                 }
426                                 if (sb.Length > 0){
427                                         args.Add (sb.ToString ());
428                                         sb.Length = 0;
429                                 }
430                         }
431
432                         string [] ret_value = new string [args.Count];
433                         args.CopyTo (ret_value, 0);
434
435                         return ret_value;
436                 }
437
438                 //
439                 // Returns the directory where the system assemblies are installed
440                 //
441                 static string GetSystemDir ()
442                 {
443                         Assembly [] assemblies = AppDomain.CurrentDomain.GetAssemblies ();
444
445                         foreach (Assembly a in assemblies){
446                                 string codebase = a.Location;
447                                 string fn = System.IO.Path.GetFileName (codebase);
448                                 if (fn == "corlib.dll" || fn == "mscorlib.dll"){
449                                         return codebase.Substring (0, codebase.LastIndexOf (System.IO.Path.DirectorySeparatorChar));
450                                 }
451                         }
452
453                         Report.Error (-15, "Can not compute my system path");
454                         return "";
455                 }
456
457                 //
458                 // Given a path specification, splits the path from the file/pattern
459                 //
460                 static void SplitPathAndPattern (string spec, out string path, out string pattern)
461                 {
462                         int p = spec.LastIndexOf ('/');
463                         if (p != -1){
464                                 //
465                                 // Windows does not like /file.cs, switch that to:
466                                 // "\", "file.cs"
467                                 //
468                                 if (p == 0){
469                                         path = "\\";
470                                         pattern = spec.Substring (1);
471                                 } else {
472                                         path = spec.Substring (0, p);
473                                         pattern = spec.Substring (p + 1);
474                                 }
475                                 return;
476                         }
477
478                         p = spec.LastIndexOf ('\\');
479                         if (p != -1){
480                                 path = spec.Substring (0, p);
481                                 pattern = spec.Substring (p + 1);
482                                 return;
483                         }
484
485                         path = ".";
486                         pattern = spec;
487                 }
488
489                 static void ProcessFile (string f)
490                 {
491                         if (first_source == null)
492                                 first_source = f;
493
494                         Location.AddFile (f);
495                 }
496
497                 static void ProcessFiles ()
498                 {
499                         Location.Initialize ();
500
501                         foreach (SourceFile file in Location.SourceFiles) {
502                                 if (tokenize) {
503                                         tokenize_file (file);
504                                 } else {
505                                         parse (file);
506                                 }
507                         }
508                 }
509
510                 static void CompileFiles (string spec, bool recurse)
511                 {
512                         string path, pattern;
513
514                         SplitPathAndPattern (spec, out path, out pattern);
515                         if (pattern.IndexOf ('*') == -1){
516                                 ProcessFile (spec);
517                                 return;
518                         }
519
520                         string [] files = null;
521                         try {
522                                 files = Directory.GetFiles (path, pattern);
523                         } catch (System.IO.DirectoryNotFoundException) {
524                                 Report.Error (2001, "Source file `" + spec + "' could not be found");
525                                 return;
526                         } catch (System.IO.IOException){
527                                 Report.Error (2001, "Source file `" + spec + "' could not be found");
528                                 return;
529                         }
530                         foreach (string f in files) {
531                                 ProcessFile (f);
532                         }
533
534                         if (!recurse)
535                                 return;
536                         
537                         string [] dirs = null;
538
539                         try {
540                                 dirs = Directory.GetDirectories (path);
541                         } catch {
542                         }
543                         
544                         foreach (string d in dirs) {
545                                         
546                                 // Don't include path in this string, as each
547                                 // directory entry already does
548                                 CompileFiles (d + "/" + pattern, true);
549                         }
550                 }
551
552                 static void DefineDefaultConfig ()
553                 {
554                         //
555                         // For now the "default config" is harcoded into the compiler
556                         // we can move this outside later
557                         //
558                         string [] default_config = {
559                                 "System",
560                                 "System.Xml",
561 #if false
562                                 //
563                                 // Is it worth pre-loading all this stuff?
564                                 //
565                                 "Accessibility",
566                                 "System.Configuration.Install",
567                                 "System.Data",
568                                 "System.Design",
569                                 "System.DirectoryServices",
570                                 "System.Drawing.Design",
571                                 "System.Drawing",
572                                 "System.EnterpriseServices",
573                                 "System.Management",
574                                 "System.Messaging",
575                                 "System.Runtime.Remoting",
576                                 "System.Runtime.Serialization.Formatters.Soap",
577                                 "System.Security",
578                                 "System.ServiceProcess",
579                                 "System.Web",
580                                 "System.Web.RegularExpressions",
581                                 "System.Web.Services",
582                                 "System.Windows.Forms"
583 #endif
584                         };
585                         
586                         int p = 0;
587                         foreach (string def in default_config)
588                                 soft_references.Insert (p++, def);
589                 }
590
591                 static void SetOutputFile (string name)
592                 {
593                         output_file = name;
594                 }
595
596                 static void SetWarningLevel (string s)
597                 {
598                         int level = 0;
599
600                         try {
601                                 level = Int32.Parse (s);
602                         } catch {
603                                 Report.Error (
604                                         1900,
605                                         "--wlevel requires a value from 0 to 4");
606                                 Environment.Exit (1);
607                         }
608                         if (level < 0 || level > 4){
609                                 Report.Error (1900, "Warning level must be 0 to 4");
610                                 Environment.Exit (1);
611                         }
612                         RootContext.WarningLevel = level;
613                         TestWarningConflict ();
614                 }
615
616                 static void TestWarningConflict ()
617                 {
618                         if (RootContext.WarningLevel == 0 && Report.WarningsAreErrors) {
619                                 Report.Error (1901, "Conflicting options specified: Warning level 0; Treat warnings as errors");
620                                 Environment.Exit (1);
621                         }
622                 }
623
624                 static void SetupV2 ()
625                 {
626                         RootContext.V2 = true;
627                         defines.Add ("__V2__");
628                 }
629                 
630                 static void Version ()
631                 {
632                         string version = Assembly.GetExecutingAssembly ().GetName ().Version.ToString ();
633                         Console.WriteLine ("Mono C# compiler version {0}", version);
634                         Environment.Exit (0);
635                 }
636                 
637                 //
638                 // Currently handles the Unix-like command line options, but will be
639                 // deprecated in favor of the CSCParseOption, which will also handle the
640                 // options that start with a dash in the future.
641                 //
642                 static bool UnixParseOption (string arg, ref string [] args, ref int i)
643                 {
644                         switch (arg){
645                         case "-vv":
646                                 parser_verbose = true;
647                                 return true;
648                                 
649                         case "-v":
650                                 yacc_verbose = true;
651                                 return true;
652
653                         case "--version":
654                                 Version ();
655                                 return true;
656                                 
657                         case "--parse":
658                                 parse_only = true;
659                                 return true;
660                                 
661                         case "--main": case "-m":
662                                 if ((i + 1) >= args.Length){
663                                         Usage ();
664                                         Environment.Exit (1);
665                                 }
666                                 RootContext.MainClass = args [++i];
667                                 return true;
668                                 
669                         case "--unsafe":
670                                 RootContext.Unsafe = true;
671                                 return true;
672                                 
673                         case "/?": case "/h": case "/help":
674                         case "--help":
675                                 Usage ();
676                                 Environment.Exit (0);
677                                 return true;
678                                 
679                         case "--define":
680                                 if ((i + 1) >= args.Length){
681                                         Usage ();
682                                         Environment.Exit (1);
683                                 }
684                                 defines.Add (args [++i]);
685                                 return true;
686
687                         case "--show-counters":
688                                 show_counters = true;
689                                 return true;
690                                 
691                         case "--expect-error": {
692                                 int code = 0;
693                                 
694                                 try {
695                                         code = Int32.Parse (
696                                                 args [++i], NumberStyles.AllowLeadingSign);
697                                         Report.ExpectedError = code;
698                                 } catch {
699                                         Report.Error (-14, "Invalid number specified");
700                                 } 
701                                 return true;
702                         }
703                                 
704                         case "--tokenize": 
705                                 tokenize = true;
706                                 return true;
707                                 
708                         case "-o": 
709                         case "--output":
710                                 if ((i + 1) >= args.Length){
711                                         Usage ();
712                                         Environment.Exit (1);
713                                 }
714                                 SetOutputFile (args [++i]);
715                                 return true;
716                                 
717                         case "--checked":
718                                 RootContext.Checked = true;
719                                 return true;
720                                 
721                         case "--stacktrace":
722                                 Report.Stacktrace = true;
723                                 return true;
724                                 
725                         case "--linkresource":
726                         case "--linkres":
727                                 if ((i + 1) >= args.Length){
728                                         Usage ();
729                                         Report.Error (5, "Missing argument to --linkres"); 
730                                         Environment.Exit (1);
731                                 }
732                                 if (resources == null)
733                                         resources = new ArrayList ();
734                                 
735                                 resources.Add (args [++i]);
736                                 return true;
737                                 
738                         case "--resource":
739                         case "--res":
740                                 if ((i + 1) >= args.Length){
741                                         Usage ();
742                                         Report.Error (5, "Missing argument to --resource"); 
743                                         Environment.Exit (1);
744                                 }
745                                 if (embedded_resources == null)
746                                         embedded_resources = new ArrayList ();
747                                 
748                                 embedded_resources.Add (args [++i]);
749                                 return true;
750                                 
751                         case "--target":
752                                 if ((i + 1) >= args.Length){
753                                         Environment.Exit (1);
754                                         return true;
755                                 }
756                                 
757                                 string type = args [++i];
758                                 switch (type){
759                                 case "library":
760                                         RootContext.Target = Target.Library;
761                                         RootContext.TargetExt = ".dll";
762                                         break;
763                                         
764                                 case "exe":
765                                         RootContext.Target = Target.Exe;
766                                         break;
767                                         
768                                 case "winexe":
769                                         RootContext.Target = Target.WinExe;
770                                         break;
771                                         
772                                 case "module":
773                                         RootContext.Target = Target.Module;
774                                         RootContext.TargetExt = ".dll";
775                                         break;
776                                 default:
777                                         TargetUsage ();
778                                         Environment.Exit (1);
779                                         break;
780                                 }
781                                 return true;
782                                 
783                         case "-r":
784                                 if ((i + 1) >= args.Length){
785                                         Usage ();
786                                         Environment.Exit (1);
787                                 }
788                                 
789                                 references.Add (args [++i]);
790                                 return true;
791                                 
792                         case "-L":
793                                 if ((i + 1) >= args.Length){
794                                         Usage ();       
795                                         Environment.Exit (1);
796                                 }
797                                 link_paths.Add (args [++i]);
798                                 return true;
799                                 
800                         case "--nostdlib":
801                                 RootContext.StdLib = false;
802                                 return true;
803                                 
804                         case "--fatal":
805                                 Report.Fatal = true;
806                                 return true;
807                                 
808                         case "--werror":
809                                 Report.WarningsAreErrors = true;
810                                 TestWarningConflict();
811                                 return true;
812                                 
813                         case "--nowarn":
814                                 if ((i + 1) >= args.Length){
815                                         Usage ();
816                                         Environment.Exit (1);
817                                 }
818                                 int warn = 0;
819                                 
820                                 try {
821                                         warn = Int32.Parse (args [++i]);
822                                 } catch {
823                                         Usage ();
824                                         Environment.Exit (1);
825                                 }
826                                 Report.SetIgnoreWarning (warn);
827                                 return true;
828                                 
829                         case "--wlevel":
830                                 if ((i + 1) >= args.Length){
831                                         Report.Error (
832                                                 1900,
833                                                 "--wlevel requires a value from 0 to 4");
834                                         Environment.Exit (1);
835                                 }
836
837                                 SetWarningLevel (args [++i]);
838                                 return true;
839
840                         case "--mcs-debug":
841                                 if ((i + 1) >= args.Length){
842                                         Report.Error (5, "--mcs-debug requires an argument");
843                                         Environment.Exit (1);
844                                 }
845
846                                 try {
847                                         Report.DebugFlags = Int32.Parse (args [++i]);
848                                 } catch {
849                                         Report.Error (5, "Invalid argument to --mcs-debug");
850                                         Environment.Exit (1);
851                                 }
852                                 return true;
853                                 
854                         case "--about":
855                                 About ();
856                                 return true;
857                                 
858                         case "--recurse":
859                                 if ((i + 1) >= args.Length){
860                                         Report.Error (5, "--recurse requires an argument");
861                                         Environment.Exit (1);
862                                 }
863                                 CompileFiles (args [++i], true); 
864                                 return true;
865                                 
866                         case "--timestamp":
867                                 timestamps = true;
868                                 last_time = first_time = DateTime.Now;
869                                 return true;
870
871                         case "--pause":
872                                 pause = true;
873                                 return true;
874                                 
875                         case "--debug": case "-g":
876                                 want_debugging_support = true;
877                                 return true;
878                                 
879                         case "--noconfig":
880                                 load_default_config = false;
881                                 return true;
882                         }
883
884                         return false;
885                 }
886
887                 //
888                 // Currently it is very basic option parsing, but eventually, this will
889                 // be the complete option parser
890                 //
891                 static bool CSCParseOption (string option, ref string [] args, ref int i)
892                 {
893                         int idx = option.IndexOf (':');
894                         string arg, value;
895
896                         if (idx == -1){
897                                 arg = option;
898                                 value = "";
899                         } else {
900                                 arg = option.Substring (0, idx);
901
902                                 value = option.Substring (idx + 1);
903                         }
904
905                         switch (arg){
906                         case "/nologo":
907                                 return true;
908
909                         case "/t":
910                         case "/target":
911                                 switch (value){
912                                 case "exe":
913                                         RootContext.Target = Target.Exe;
914                                         break;
915
916                                 case "winexe":
917                                         RootContext.Target = Target.WinExe;
918                                         break;
919
920                                 case "library":
921                                         RootContext.Target = Target.Library;
922                                         RootContext.TargetExt = ".dll";
923                                         break;
924
925                                 case "module":
926                                         RootContext.Target = Target.Module;
927                                         RootContext.TargetExt = ".netmodule";
928                                         break;
929
930                                 default:
931                                         TargetUsage ();
932                                         Environment.Exit (1);
933                                         break;
934                                 }
935                                 return true;
936
937                         case "/out":
938                                 if (value == ""){
939                                         Usage ();
940                                         Environment.Exit (1);
941                                 }
942                                 SetOutputFile (value);
943                                 return true;
944
945                         case "/optimize":
946                         case "/optimize+":
947                         case "/optimize-":
948                         case "/incremental":
949                         case "/incremental+":
950                         case "/incremental-":
951                                 // nothing.
952                                 return true;
953
954                         case "/d":
955                         case "/define": {
956                                 string [] defs;
957
958                                 if (value == ""){
959                                         Usage ();
960                                         Environment.Exit (1);
961                                 }
962
963                                 defs = value.Split (new Char [] {';', ','});
964                                 foreach (string d in defs){
965                                         defines.Add (d);
966                                 }
967                                 return true;
968                         }
969
970                         case "/linkres":
971                         case "/linkresource":
972                                 if (value == ""){
973                                         Report.Error (5, arg + " requires an argument");
974                                         Environment.Exit (1);
975                                 }
976                                 if (resources == null)
977                                         resources = new ArrayList ();
978                                 
979                                 resources.Add (value);
980                                 return true;
981                                 
982                         case "/res":
983                         case "/resource":
984                                 if (value == ""){
985                                         Report.Error (5, arg + " requires an argument");
986                                         Environment.Exit (1);
987                                 }
988                                 if (embedded_resources == null)
989                                         embedded_resources = new ArrayList ();
990                                 
991                                 embedded_resources.Add (value);
992                                 return true;
993                                 
994                         case "/recurse":
995                                 if (value == ""){
996                                         Report.Error (5, "/recurse requires an argument");
997                                         Environment.Exit (1);
998                                 }
999                                 CompileFiles (value, true); 
1000                                 return true;
1001
1002                         case "/r":
1003                         case "/reference": {
1004                                 if (value == ""){
1005                                         Report.Error (5, arg + " requires an argument");
1006                                         Environment.Exit (1);
1007                                 }
1008
1009                                 string [] refs = value.Split (new char [] { ';', ',' });
1010                                 foreach (string r in refs){
1011                                         references.Add (r);
1012                                 }
1013                                 return true;
1014                         }
1015                         case "/addmodule": {
1016                                 if (value == ""){
1017                                         Report.Error (5, arg + " requires an argument");
1018                                         Environment.Exit (1);
1019                                 }
1020
1021                                 string [] refs = value.Split (new char [] { ';', ',' });
1022                                 foreach (string r in refs){
1023                                         modules.Add (r);
1024                                 }
1025                                 return true;
1026                         }
1027                         case "/win32res": {
1028                                 if (value == "") {
1029                                         Report.Error (5, arg + " requires an argument");
1030                                         Environment.Exit (1);
1031                                 }
1032
1033                                 win32ResourceFile = value;
1034                                 return true;
1035                         }
1036                         case "/win32icon": {
1037                                 if (value == "") {
1038                                         Report.Error (5, arg + " requires an argument");
1039                                         Environment.Exit (1);
1040                                 }
1041
1042                                 win32IconFile = value;
1043                                 return true;
1044                         }
1045                         case "/doc": {
1046                                 if (value == ""){
1047                                         Report.Error (5, arg + " requires an argument");
1048                                         Environment.Exit (1);
1049                                 }
1050                                 // TODO handle the /doc argument to generate xml doc
1051                                 return true;
1052                         }
1053                         case "/lib": {
1054                                 string [] libdirs;
1055                                 
1056                                 if (value == ""){
1057                                         Report.Error (5, "/lib requires an argument");
1058                                         Environment.Exit (1);
1059                                 }
1060
1061                                 libdirs = value.Split (new Char [] { ',' });
1062                                 foreach (string dir in libdirs)
1063                                         link_paths.Add (dir);
1064                                 return true;
1065                         }
1066                                 
1067                         case "/debug":
1068                         case "/debug+":
1069                                 want_debugging_support = true;
1070                                 return true;
1071
1072                         case "/checked":
1073                         case "/checked+":
1074                                 RootContext.Checked = true;
1075                                 return true;
1076
1077                         case "/checked-":
1078                                 RootContext.Checked = false;
1079                                 return true;
1080
1081                         case "/unsafe":
1082                         case "/unsafe+":
1083                                 RootContext.Unsafe = true;
1084                                 return true;
1085
1086                         case "/unsafe-":
1087                                 RootContext.Unsafe = false;
1088                                 return true;
1089
1090                         case "/warnaserror":
1091                         case "/warnaserror+":
1092                                 Report.WarningsAreErrors = true;
1093                                 TestWarningConflict();
1094                                 return true;
1095
1096                         case "/warnaserror-":
1097                                 Report.WarningsAreErrors = false;
1098                                 return true;
1099
1100                         case "/warn":
1101                                 SetWarningLevel (value);
1102                                 return true;
1103
1104                         case "/nowarn": {
1105                                 string [] warns;
1106
1107                                 if (value == ""){
1108                                         Report.Error (5, "/nowarn requires an argument");
1109                                         Environment.Exit (1);
1110                                 }
1111                                 
1112                                 warns = value.Split (new Char [] {','});
1113                                 foreach (string wc in warns){
1114                                         try {
1115                                                 int warn = Int32.Parse (wc);
1116                                                 if (warn < 1) {
1117                                                         throw new ArgumentOutOfRangeException("warn");
1118                                                 }
1119                                                 Report.SetIgnoreWarning (warn);
1120                                         } catch {
1121                                                 Report.Error (1904, String.Format("'{0}' is not a valid warning number", wc));
1122                                                 Environment.Exit (1);
1123                                         }
1124                                 }
1125                                 return true;
1126                         }
1127
1128                         case "/noconfig-":
1129                                 load_default_config = true;
1130                                 return true;
1131                                 
1132                         case "/noconfig":
1133                         case "/noconfig+":
1134                                 load_default_config = false;
1135                                 return true;
1136
1137                         case "/help":
1138                         case "/?":
1139                                 Usage ();
1140                                 Environment.Exit (0);
1141                                 return true;
1142
1143                         case "/main":
1144                         case "/m":
1145                                 if (value == ""){
1146                                         Report.Error (5, arg + " requires an argument");                                        
1147                                         Environment.Exit (1);
1148                                 }
1149                                 RootContext.MainClass = value;
1150                                 return true;
1151
1152                         case "/nostdlib":
1153                         case "/nostdlib+":
1154                                 RootContext.StdLib = false;
1155                                 return true;
1156
1157                         case "/nostdlib-":
1158                                 RootContext.StdLib = true;
1159                                 return true;
1160
1161                         case "/fullpaths":
1162                                 return true;
1163
1164                         case "/keyfile":
1165                                 if (value == String.Empty) {
1166                                         Report.Error (5, arg + " requires an argument");
1167                                         Environment.Exit (1);
1168                                 }
1169                                 RootContext.StrongNameKeyFile = value;
1170                                 return true;
1171                         case "/keycontainer":
1172                                 if (value == String.Empty) {
1173                                         Report.Error (5, arg + " requires an argument");
1174                                         Environment.Exit (1);
1175                                 }
1176                                 RootContext.StrongNameKeyContainer = value;
1177                                 return true;
1178                         case "/delaysign+":
1179                                 RootContext.StrongNameDelaySign = true;
1180                                 return true;
1181                         case "/delaysign-":
1182                                 RootContext.StrongNameDelaySign = false;
1183                                 return true;
1184
1185                         case "/v2":
1186                         case "/2":
1187                                 SetupV2 ();
1188                                 return true;
1189                                 
1190                         case "/codepage":
1191                                 int cp = -1;
1192
1193                                 if (value == "utf8"){
1194                                         encoding = new UTF8Encoding();
1195                                         using_default_encoder = false;
1196                                         return true;
1197                                 }
1198                                 if (value == "reset"){
1199                                         //
1200                                         // 28591 is the code page for ISO-8859-1 encoding.
1201                                         //
1202                                         cp = 28591;
1203                                         using_default_encoder = true;
1204                                 }
1205                                 
1206                                 try {
1207                                         cp = Int32.Parse (value);
1208                                         encoding = Encoding.GetEncoding (cp);
1209                                         using_default_encoder = false;
1210                                 } catch {
1211                                         Report.Error (2016, String.Format("Code page '{0}' is invalid or not installed", cp));
1212                                         Environment.Exit (1);
1213                                 }
1214                                 return true;
1215                         }
1216                         //Report.Error (2007, String.Format ("Unrecognized command-line option: '{0}'", option));
1217                         //Environment.Exit (1);
1218                         return false;
1219                 }
1220                 
1221                 /// <summary>
1222                 ///    Parses the arguments, and drives the compilation
1223                 ///    process.
1224                 /// </summary>
1225                 ///
1226                 /// <remarks>
1227                 ///    TODO: Mostly structured to debug the compiler
1228                 ///    now, needs to be turned into a real driver soon.
1229                 /// </remarks>
1230                 // [MonoTODO("Change error code for unknown argument to something reasonable")]
1231                 internal static bool MainDriver (string [] args)
1232                 {
1233                         int i;
1234                         bool parsing_options = true;
1235
1236                         try {
1237                                 encoding = Encoding.GetEncoding (28591);
1238                         } catch {
1239                                 Console.WriteLine ("Error: could not load encoding 28591, trying 1252");
1240                                 encoding = Encoding.GetEncoding (1252);
1241                         }
1242                         
1243                         references = new ArrayList ();
1244                         soft_references = new ArrayList ();
1245                         modules = new ArrayList ();
1246                         link_paths = new ArrayList ();
1247
1248                         SetupDefaultDefines ();
1249                         
1250                         //
1251                         // Setup defaults
1252                         //
1253                         // This is not required because Assembly.Load knows about this
1254                         // path.
1255                         //
1256
1257                         int argc = args.Length;
1258                         for (i = 0; i < argc; i++){
1259                                 string arg = args [i];
1260
1261                                 if (arg.StartsWith ("@")){
1262                                         string [] new_args, extra_args;
1263                                         string response_file = arg.Substring (1);
1264
1265                                         if (response_file_list == null)
1266                                                 response_file_list = new Hashtable ();
1267                                         
1268                                         if (response_file_list.Contains (response_file)){
1269                                                 Report.Error (
1270                                                         1515, "Response file `" + response_file +
1271                                                         "' specified multiple times");
1272                                                 Environment.Exit (1);
1273                                         }
1274                                         
1275                                         response_file_list.Add (response_file, response_file);
1276                                                     
1277                                         extra_args = LoadArgs (response_file);
1278                                         if (extra_args == null){
1279                                                 Report.Error (2011, "Unable to open response file: " +
1280                                                               response_file);
1281                                                 return false;
1282                                         }
1283
1284                                         new_args = new string [extra_args.Length + argc];
1285                                         args.CopyTo (new_args, 0);
1286                                         extra_args.CopyTo (new_args, argc);
1287                                         args = new_args;
1288                                         argc = new_args.Length;
1289                                         continue;
1290                                 }
1291
1292                                 if (parsing_options){
1293                                         if (arg == "--"){
1294                                                 parsing_options = false;
1295                                                 continue;
1296                                         }
1297                                         
1298                                         if (arg.StartsWith ("-")){
1299                                                 if (UnixParseOption (arg, ref args, ref i))
1300                                                         continue;
1301
1302                                                 // Try a -CSCOPTION
1303                                                 string csc_opt = "/" + arg.Substring (1);
1304                                                 if (CSCParseOption (csc_opt, ref args, ref i))
1305                                                         continue;
1306                                         } else {
1307                                                 if (arg.StartsWith ("/")){
1308                                                         if (CSCParseOption (arg, ref args, ref i))
1309                                                                 continue;
1310                                                 }
1311                                         }
1312                                 }
1313
1314                                 CompileFiles (arg, false); 
1315                         }
1316
1317                         ProcessFiles ();
1318
1319                         if (tokenize)
1320                                 return true;
1321
1322                         //
1323                         // If we are an exe, require a source file for the entry point
1324                         //
1325                         if (RootContext.Target == Target.Exe || RootContext.Target == Target.WinExe){
1326                                 if (first_source == null){
1327                                         Report.Error (2008, "No files to compile were specified");
1328                                         return false;
1329                                 }
1330
1331                         }
1332
1333                         //
1334                         // If there is nothing to put in the assembly, and we are not a library
1335                         //
1336                         if (first_source == null && embedded_resources == null && resources == null){
1337                                 Report.Error (2008, "No files to compile were specified");
1338                                 return false;
1339                         }
1340
1341                         if (Report.Errors > 0)
1342                                 return false;
1343                         
1344                         if (parse_only)
1345                                 return true;
1346
1347                         Tokenizer.Cleanup ();
1348                         
1349                         //
1350                         // Load Core Library for default compilation
1351                         //
1352                         if (RootContext.StdLib)
1353                                 references.Insert (0, "mscorlib");
1354
1355                         if (load_default_config)
1356                                 DefineDefaultConfig ();
1357
1358                         if (Report.Errors > 0){
1359                                 return false;
1360                         }
1361
1362                         //
1363                         // Load assemblies required
1364                         //
1365                         if (timestamps)
1366                                 ShowTime ("Loading references");
1367                         link_paths.Add (GetSystemDir ());
1368                         LoadReferences ();
1369                         
1370                         if (timestamps)
1371                                 ShowTime ("   References loaded");
1372                         
1373                         if (Report.Errors > 0){
1374                                 return false;
1375                         }
1376
1377                         //
1378                         // Quick hack
1379                         //
1380                         if (output_file == null){
1381                                 int pos = first_source.LastIndexOf ('.');
1382
1383                                 if (pos > 0)
1384                                         output_file = first_source.Substring (0, pos) + RootContext.TargetExt;
1385                                 else
1386                                         output_file = first_source + RootContext.TargetExt;
1387                         }
1388
1389                         CodeGen.Init (output_file, output_file, want_debugging_support);
1390
1391                         if (RootContext.Target == Target.Module) {
1392                                 PropertyInfo module_only = typeof (AssemblyBuilder).GetProperty ("IsModuleOnly", BindingFlags.Instance|BindingFlags.Public|BindingFlags.NonPublic);
1393                                 if (module_only == null) {
1394                                         Report.Error (0, new Location (-1), "Cannot use /target:module on this runtime: try the Mono runtime instead.");
1395                                         Environment.Exit (1);
1396                                 }
1397
1398                                 module_only.SetValue (CodeGen.Assembly.Builder, true, null);
1399                         }
1400
1401                         TypeManager.AddModule (CodeGen.Module.Builder);
1402
1403                         if (modules.Count > 0) {
1404                                 MethodInfo adder_method = typeof (AssemblyBuilder).GetMethod ("AddModule", BindingFlags.Instance|BindingFlags.NonPublic);
1405                                 if (adder_method == null) {
1406                                         Report.Error (0, new Location (-1), "Cannot use /addmodule on this runtime: Try the Mono runtime instead.");
1407                                         Environment.Exit (1);
1408                                 }
1409
1410                                 foreach (string module in modules)
1411                                         LoadModule (adder_method, module);
1412                         }
1413
1414                         TypeManager.ComputeNamespaces ();
1415                         
1416                         //
1417                         // Before emitting, we need to get the core
1418                         // types emitted from the user defined types
1419                         // or from the system ones.
1420                         //
1421                         if (timestamps)
1422                                 ShowTime ("Initializing Core Types");
1423                         if (!RootContext.StdLib){
1424                                 RootContext.ResolveCore ();
1425                                 if (Report.Errors > 0)
1426                                         return false;
1427                         }
1428                         
1429                         TypeManager.InitCoreTypes ();
1430                         if (timestamps)
1431                                 ShowTime ("   Core Types done");
1432
1433                         //
1434                         // The second pass of the compiler
1435                         //
1436                         if (timestamps)
1437                                 ShowTime ("Resolving tree");
1438                         RootContext.ResolveTree ();
1439                         if (Report.Errors > 0)
1440                                 return false;
1441                         if (timestamps)
1442                                 ShowTime ("Populate tree");
1443                         if (!RootContext.StdLib)
1444                                 RootContext.BootCorlib_PopulateCoreTypes ();
1445                         RootContext.PopulateTypes ();
1446                         RootContext.DefineTypes ();
1447                         
1448                         TypeManager.InitCodeHelpers ();
1449
1450                         //
1451                         // Verify using aliases now
1452                         //
1453                         Namespace.VerifyUsing ();
1454                         
1455                         if (Report.Errors > 0){
1456                                 return false;
1457                         }
1458                         
1459                         //
1460                         // The code generator
1461                         //
1462                         if (timestamps)
1463                                 ShowTime ("Emitting code");
1464                         ShowTotalTime ("Total so far");
1465                         RootContext.EmitCode ();
1466                         if (timestamps)
1467                                 ShowTime ("   done");
1468
1469                         if (Report.Errors > 0){
1470                                 return false;
1471                         }
1472
1473                         if (timestamps)
1474                                 ShowTime ("Closing types");
1475
1476                         RootContext.CloseTypes ();
1477
1478                         PEFileKinds k = PEFileKinds.ConsoleApplication;
1479                         
1480                         switch (RootContext.Target) {
1481                         case Target.Library:
1482                         case Target.Module:
1483                                 k = PEFileKinds.Dll; break;
1484                         case Target.Exe:
1485                                 k = PEFileKinds.ConsoleApplication; break;
1486                         case Target.WinExe:
1487                                 k = PEFileKinds.WindowApplication; break;
1488                         }
1489
1490                         if (RootContext.NeedsEntryPoint) {
1491                                 MethodInfo ep = RootContext.EntryPoint;
1492
1493                                 if (ep == null) {
1494                                         if (Report.Errors == 0)
1495                                                 Report.Error (5001, "Program " + output_file +
1496                                                               " does not have an entry point defined");
1497                                         return false;
1498                                 }
1499
1500                                 CodeGen.Assembly.Builder.SetEntryPoint (ep, k);
1501                         } else if (RootContext.MainClass != null) {
1502                                 Report.Error (2017, "Can not specify -main: when building module or library");
1503                         }
1504
1505                         //
1506                         // Add the resources
1507                         //
1508                         if (resources != null){
1509                                 foreach (string spec in resources){
1510                                         string file, res;
1511                                         int cp;
1512                                         
1513                                         cp = spec.IndexOf (',');
1514                                         if (cp != -1){
1515                                                 file = spec.Substring (0, cp);
1516                                                 res = spec.Substring (cp + 1);
1517                                         } else
1518                                                 file = res = spec;
1519
1520                                         CodeGen.Assembly.Builder.AddResourceFile (res, file);
1521                                 }
1522                         }
1523                         
1524                         if (embedded_resources != null){
1525                                 object[] margs = new object [2];
1526                                 Type[] argst = new Type [2];
1527                                 argst [0] = argst [1] = typeof (string);
1528
1529                                 MethodInfo embed_res = typeof (AssemblyBuilder).GetMethod (
1530                                         "EmbedResourceFile", BindingFlags.Instance|BindingFlags.Public|BindingFlags.NonPublic,
1531                                         null, CallingConventions.Any, argst, null);
1532                                 
1533                                 if (embed_res == null) {
1534                                         Report.Warning (0, new Location (-1),
1535                                                         "Cannot embed resources on this runtime: try the Mono runtime instead.");
1536                                 } else {
1537                                         foreach (string spec in embedded_resources) {
1538                                                 int cp;
1539
1540                                                 cp = spec.IndexOf (',');
1541                                                 if (cp != -1){
1542                                                         margs [0] = spec.Substring (cp + 1);
1543                                                         margs [1] = spec.Substring (0, cp);
1544                                                 } else {
1545                                                         margs [1] = spec;
1546                                                         margs [0] = spec.Replace ('/','.').Replace ('\\', '.');
1547                                                 }
1548
1549                                                 if (File.Exists ((string) margs [1]))
1550                                                         embed_res.Invoke (CodeGen.Assembly.Builder, margs);
1551                                                 else {
1552                                                         Report.Error (1566, "Can not find the resource " + margs [1]);
1553                                                 }
1554                                         }
1555                                 }
1556                         }
1557
1558                         //
1559                         // Add Win32 resources
1560                         //
1561
1562                         CodeGen.Assembly.Builder.DefineVersionInfoResource ();
1563
1564                         if (win32ResourceFile != null) {
1565                                 try {
1566                                         CodeGen.Assembly.Builder.DefineUnmanagedResource (win32ResourceFile);
1567                                 }
1568                                 catch (ArgumentException) {
1569                                         Report.Warning (0, new Location (-1), "Cannot embed win32 resources on this runtime: try the Mono runtime instead.");
1570                                 }
1571                         }
1572
1573                         if (win32IconFile != null) {
1574                                 MethodInfo define_icon = typeof (AssemblyBuilder).GetMethod ("DefineIconResource", BindingFlags.Instance|BindingFlags.Public|BindingFlags.NonPublic);
1575                                 if (define_icon == null) {
1576                                         Report.Warning (0, new Location (-1), "Cannot embed icon resource on this runtime: try the Mono runtime instead.");
1577                                 }
1578                                 define_icon.Invoke (CodeGen.Assembly.Builder, new object [] { win32IconFile });
1579                         }
1580
1581                         if (Report.Errors > 0)
1582                                 return false;
1583                         
1584                         CodeGen.Save (output_file);
1585                         if (timestamps) {
1586                                 ShowTime ("Saved output");
1587                                 ShowTotalTime ("Total");
1588                         }
1589
1590                         Timer.ShowTimers ();
1591                         
1592                         if (Report.ExpectedError != 0) {
1593                                 if (Report.Errors == 0) {
1594                                         Console.WriteLine ("Failed to report expected error " + Report.ExpectedError + ".\n" +
1595                                                 "No other errors reported.");
1596                                         
1597                                         Environment.Exit (2);
1598                                 } else {
1599                                         Console.WriteLine ("Failed to report expected error " + Report.ExpectedError + ".\n" +
1600                                                 "However, other errors were reported.");
1601                                         
1602                                         Environment.Exit (1);
1603                                 }
1604                                 
1605                                 
1606                                 return false;
1607                         }
1608
1609 #if DEBUGME
1610                         Console.WriteLine ("Size of strings held: " + DeclSpace.length);
1611                         Console.WriteLine ("Size of strings short: " + DeclSpace.small);
1612 #endif
1613                         return (Report.Errors == 0);
1614                 }
1615
1616         }
1617
1618         //
1619         // This is the only public entry point
1620         //
1621         public class CompilerCallableEntryPoint : MarshalByRefObject {
1622                 static bool used = false;
1623                 
1624                 public bool InvokeCompiler (string [] args)
1625                 {
1626                         if (used)
1627                                 Reset ();
1628                         bool ok = Driver.MainDriver (args);
1629                         return ok && Report.Errors == 0;
1630                 }
1631
1632                 public void Reset ()
1633                 {
1634                 }
1635         }
1636 }