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