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