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