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