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