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