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