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