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