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