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