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