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