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