2005-03-25:2 Rafael Teixeira <rafaelteixeirabr@hotmail.com>
[mono.git] / mcs / mbas / driver.cs
1 //
2 // driver.cs: The compiler command line driver.
3 //
4 // Author: Rafael Teixeira (rafaelteixeirabr@hotmail.com)
5 // Based on mcs by : Miguel de Icaza (miguel@gnu.org)
6 //
7 // Licensed under the terms of the GNU GPL
8 //
9 // (C) 2002, 2003, 2004 Rafael Teixeira
10 //
11
12 namespace Mono.Languages {
13
14         using System;
15         using System.Collections;
16         using System.Diagnostics;
17         using System.IO;
18         using System.Text;
19         using System.Globalization;
20         using System.Reflection;
21         using System.Reflection.Emit;
22
23         using Mono.MonoBASIC;
24         using Mono.GetOptions;
25
26         enum Target {
27                 Library, Exe, Module, WinExe
28         };
29         
30         enum OptionCompare {
31                 Binary, Text
32         };
33         
34         struct FileToCompile {
35                 public string Filename;
36                 public Encoding Encoding;
37                 
38                 public FileToCompile(string filename, Encoding encoding)
39                 {
40                         this.Filename = filename;
41                         this.Encoding = encoding;       
42                 }
43                 
44                 public void Process()
45                 {
46                         GenericParser.Parse(this.Filename, this.Encoding);
47                 }
48         }
49         
50         /// <summary>
51         ///    The compiler driver.
52         /// </summary>
53         public class Driver : Options {
54                 // Temporary options
55                 //------------------------------------------------------------------
56                 [Option("[Mono] Only parses the source file (for debugging the tokenizer)", "parse", SecondLevelHelp = true)]
57                 public bool parse_only = false;
58
59                 [Option("[IGNORED] Only tokenizes source files", SecondLevelHelp = true)]
60                 public bool tokenize = false;
61
62                 [Option("[Mono] Shows stack trace at Error location", SecondLevelHelp = true)]
63                 public bool stacktrace { set { Report.Stacktrace = value; } }
64
65                 [Option("[Mono] Displays time stamps of various compiler events", SecondLevelHelp = true)]
66                 public bool timestamp {
67                         set
68                         {
69                                 timestamps = true;
70                                 last_time = DateTime.Now;
71                                 debug_arglist.Add("timestamp");
72                         }
73                 }
74                 
75                 [Option("[Mono] Makes errors fatal", "fatal", SecondLevelHelp = true)]
76                 public bool Fatal { set { Report.Fatal = value; } }
77
78
79                 // Mono-specific options
80                 //------------------------------------------------------------------
81                 [Option("About the MonoBASIC compiler", "about")]
82                 public override WhatToDoNext DoAbout()
83                 {
84                         return base.DoAbout();
85                 }
86
87                 [Option("Show usage syntax and exit", "usage", SecondLevelHelp = true)]
88                 public override WhatToDoNext DoUsage()
89                 {
90                         return base.DoUsage();
91                 }
92
93                 [Option(-1, "[Mono] References packages listed. {packagelist}=package,...", "pkg")]
94                 public WhatToDoNext ReferenceSomePackage(string packageName)
95                 {
96                         return ReferencePackage(packageName)?WhatToDoNext.GoAhead:WhatToDoNext.AbandonProgram;
97                 }
98
99                 private Encoding currentEncoding = null;
100                 
101                 [Option(-1, "Select codepage by {ID} (number, 'utf8' or 'reset') to process following source files", "codepage")]
102                 public string CurrentCodepage {
103                         set {
104                                 switch (value.ToLower()) {
105                                         case "reset": 
106                                                 currentEncoding = null; 
107                                                 break;
108                                         case "utf8": case "utf-8":
109                                                 currentEncoding = Encoding.UTF8;
110                                                 break;
111                                         default:
112                                                 try {
113                                                         currentEncoding = Encoding.GetEncoding(int.Parse(value));
114                                                 } catch (NotSupportedException) {
115                                                         Console.WriteLine("Ignoring unsupported codepage number {0}.", value);
116                                                 } catch (Exception) {
117                                                         Console.WriteLine("Ignoring unsupported codepage ID {0}.", value);
118                                                 }
119                                                 break;
120                                 }                                       
121                         }
122                 }
123
124
125
126                 [Option("[Mono] Don\'t assume the standard library", "nostdlib", SecondLevelHelp = true)]
127                 public bool NoStandardLibraries { set { RootContext.StdLib = !value; } }
128
129                 [Option("[Mono] Disables implicit references to assemblies", "noconfig", SecondLevelHelp = true)]
130                 public bool NoConfig { set { load_default_config = !value; } }
131
132                 [Option("[Mono] Allows unsafe code", "unsafe", SecondLevelHelp = true)]
133                 public bool AllowUnsafeCode { set { RootContext.Unsafe = value; } }
134
135                 [Option("[Mono] Debugger {arguments}", "debug-args", SecondLevelHelp = true)]
136                 public WhatToDoNext SetDebugArgs(string args)
137                 {
138                         debug_arglist.AddRange(args.Split(','));
139                         return WhatToDoNext.GoAhead;
140                 }
141
142                 [Option("[Mono] Ignores warning number {XXXX}", "ignorewarn", SecondLevelHelp = true)]
143                 public WhatToDoNext SetIgnoreWarning(int warn)
144                 {
145                         Report.SetIgnoreWarning(warn);
146                         return WhatToDoNext.GoAhead;
147                 }       
148
149                 [Option("[Mono] Sets warning {level} (the highest is 4, the default)", "wlevel", SecondLevelHelp = true)]
150                 public int WarningLevel { set { RootContext.WarningLevel = value; } }
151
152                 // Output file options
153                 //------------------------------------------------------------------
154                 [Option("Specifies the output {file} name", 'o', "out")]
155                 public string OutputFileName = null;
156
157                 [Option("Specifies the target {type} for the output file (exe [default], winexe, library, module)", 't', "target")]
158                 public WhatToDoNext SetTarget(string type)
159                 {
160                         switch (type.ToLower()) {
161                                 case "library":
162                                         target = Target.Library;
163                                         target_ext = ".dll";
164                                         break;
165                                                         
166                                 case "exe":
167                                         target = Target.Exe;
168                                         target_ext = ".exe";
169                                         break;
170                                                         
171                                 case "winexe":
172                                         target = Target.WinExe;
173                                         target_ext = ".exe";
174                                         break;
175                                                         
176                                 case "module":
177                                         target = Target.Module;
178                                         target_ext = ".netmodule";
179                                         break;
180                         }
181                         return WhatToDoNext.GoAhead;
182                 }
183
184                 [Option("Specifies the {name} of the Class or Module that contains Sub Main or inherits from System.Windows.Forms.Form.\tNeeded to select among many entry-points for a program (target=exe|winexe)",
185                         'm', "main")]
186                 public string main { set { RootContext.MainClass = value; } }
187
188                 // TODO: force option to accept number in hex format
189 //              [Option("[NOT IMPLEMENTED YET]The base {address} for a library or module (hex)", SecondLevelHelp = true)]
190                 public int baseaddress;
191
192                 // input file options
193                 //------------------------------------------------------------------
194                 [Option(-1, "Imports all type information from files in the {module-list}. {module-list}:module,...", "addmodule")]
195                 public string AddedModule { set { foreach(string module in value.Split(',')) addedNetModules.Add(module); } }
196
197 //              [Option("[NOT IMPLEMENTED YET]Include all files in the current directory and subdirectories according to the {wildcard}", "recurse")]
198                 public WhatToDoNext Recurse(string wildcard)
199                 {
200                         //AddFiles (DirName, true); // TODO wrong semantics
201                         return WhatToDoNext.GoAhead;
202                 }
203
204                 [Option(-1, "References metadata from the specified {assembly}", 'r', "reference")]
205                 public string AddedReference { set { references.Add(value); } }
206                 
207                 [Option("List of directories to search for metadata references. {path-list}:path,...", "libpath", "lib")]
208                 public string AddedLibPath { set { foreach(string path in value.Split(',')) libpath.Add(path); } }
209
210                 // support for the Compact Framework
211                 //------------------------------------------------------------------
212 //              [Option("[NOT IMPLEMENTED YET]Sets the compiler to target the Compact Framework", "netcf")]
213                 public bool CompileForCompactFramework = false;
214                 
215 //              [Option("[NOT IMPLEMENTED YET]Specifies the {path} to the location of mscorlib.dll and microsoft.visualbasic.dll", "sdkpath")]
216                 public string SDKPath = null;
217
218                 // resource options
219                 //------------------------------------------------------------------
220                 public ArrayList EmbeddedResources = new ArrayList();
221                 
222                 [Option(-1, "Adds the specified {file} as an embedded assembly resource", "resource", "res")]
223                 public string AddedResource { set { EmbeddedResources.Add(value); } }
224
225                 public ArrayList LinkedResources = new ArrayList();
226                 
227 //              [Option(-1, "[NOT IMPLEMENTED YET]Adds the specified {file} as a linked assembly resource", "linkresource", "linkres")]
228                 public string AddedLinkresource { set { LinkedResources.Add(value); } }
229
230                 public ArrayList Win32Resources = new ArrayList();
231                 
232 //              [Option(-1, "[NOT IMPLEMENTED YET]Specifies a Win32 resource {file} (.res)", "win32resource")]
233                 public string AddedWin32resource { set { Win32Resources.Add(value); } }
234
235                 public ArrayList Win32Icons = new ArrayList();
236                 
237 //              [Option(-1, "[NOT IMPLEMENTED YET]Specifies a Win32 icon {file} (.ico) for the default Win32 resources", "win32icon")]
238                 public string AddedWin32icon { set { Win32Icons.Add(value); } }
239
240                 // code generation options
241                 //------------------------------------------------------------------
242
243 //              [Option("[NOT IMPLEMENTED YET]Enable optimizations", "optimize", VBCStyleBoolean = true)]
244                 public bool optimize = false;
245
246                 [Option("Remove integer checks. Default off.", SecondLevelHelp = true, VBCStyleBoolean = true)]
247                 public bool removeintchecks { set { RootContext.Checked = !value; } }
248
249                 [Option("Emit debugging information", 'g', "debug", VBCStyleBoolean = true)]
250                 public bool want_debugging_support = false;
251
252                 [Option("Emit full debugging information (default)", "debug:full", SecondLevelHelp = true)]
253                 public bool fullDebugging = false;
254
255                 [Option("[IGNORED] Emit PDB file only", "debug:pdbonly", SecondLevelHelp = true)]
256                 public bool pdbOnly = false;
257
258                 // errors and warnings options
259                 //------------------------------------------------------------------
260
261                 [Option("Treat warnings as errors", "warnaserror", SecondLevelHelp = true)]
262                 public bool WarningsAreErrors { set { Report.WarningsAreErrors = value; } }
263
264                 [Option("Disable warnings", "nowarn", SecondLevelHelp = true)]
265                 public bool NoWarnings { set { if (value) RootContext.WarningLevel = 0; } }
266
267
268                 // defines
269                 //------------------------------------------------------------------
270                 public Hashtable Defines = new Hashtable();
271                 
272                 [Option(-1, "Declares global conditional compilation symbol(s). {symbol-list}:name=value,...", 'd', "define")]
273                 public string define { 
274                         set {
275                                 foreach(string item in value.Split(','))  {
276                                         string[] dados = item.Split('=');
277                                         try {
278                                                 if (dados.Length > 1)
279                                                         Defines.Add(dados[0], dados[1]); 
280                                                 else
281                                                         Defines.Add(dados[0], string.Empty);
282                                         }
283                                         catch  {
284                                                 Error ("Could not define symbol" + dados[0]);
285                                         }
286                                 }
287                         } 
288                 }
289                 
290                 // language options
291                 //------------------------------------------------------------------
292
293 //              [Option("[NOT IMPLEMENTED YET]Require explicit declaration of variables", VBCStyleBoolean = true)]
294                 public bool optionexplicit { set { Mono.MonoBASIC.Parser.InitialOptionExplicit = value; } }
295
296 //              [Option("[NOT IMPLEMENTED YET]Enforce strict language semantics", VBCStyleBoolean = true)]
297                 public bool optionstrict { set { Mono.MonoBASIC.Parser.InitialOptionStrict = value; } }
298                 
299 //              [Option("[NOT IMPLEMENTED YET]Specifies binary-style string comparisons. This is the default", "optioncompare:binary")]
300                 public bool optioncomparebinary { set { Mono.MonoBASIC.Parser.InitialOptionCompareBinary = true; } }
301
302 //              [Option("[NOT IMPLEMENTED YET]Specifies text-style string comparisons.", "optioncompare:text")]
303                 public bool optioncomparetext { set { Mono.MonoBASIC.Parser.InitialOptionCompareBinary = false; } }
304
305                 [Option(-1, "Declare global Imports for listed namespaces. {import-list}:namespace,...", "imports")]
306                 public string imports
307                 {
308                         set {
309                                 foreach(string importedNamespace in value.Split(','))
310                                         Mono.MonoBASIC.Parser.ImportsList.Add(importedNamespace);
311                         }
312                 }
313
314                 [Option("Specifies the root {namespace} for all type declarations", SecondLevelHelp = true)]
315                 public string rootnamespace { set { RootContext.RootNamespace = value; } }
316                 
317                 // Signing options      
318                 //------------------------------------------------------------------
319 //              [Option("[NOT IMPLEMENTED YET]Delay-sign the assembly using only the public portion of the strong name key", VBCStyleBoolean = true)]
320                 public bool delaysign;
321                 
322 //              [Option("[NOT IMPLEMENTED YET]Specifies a strong name key {container}")]
323                 public string keycontainer;
324                 
325 //              [Option("[NOT IMPLEMENTED YET]Specifies a strong name key {file}")]
326                 public string keyfile;
327
328                 // Compiler output options      
329                 //------------------------------------------------------------------
330                 
331                 [Option("Do not display compiler copyright banner")]
332                 public bool nologo = false;
333                 
334                 //TODO: Correct semantics
335                 [Option("Commands the compiler to show only error messages for syntax-related errors and warnings", 'q', "quiet", SecondLevelHelp = true)]
336                 public bool SuccintErrorDisplay = false;
337                 
338                 // TODO: semantics are different and should be adjusted
339                 [Option("Display verbose messages", 'v', SecondLevelHelp = true)] 
340                 public bool verbose     { set { GenericParser.yacc_verbose_flag = value ? 1 : 0; } }
341
342                 [Option("[IGNORED] Emit compiler output in UTF8 character encoding", SecondLevelHelp = true, VBCStyleBoolean = true)]
343                 public bool utf8output;
344
345 //              [Option("[NOT IMPLEMENTED YET]Create bug report {file}")]
346                 public string bugreport;
347
348                 [ArgumentProcessor]
349                 public void AddFile(string fileName)
350                 {
351                         string f = fileName;
352                         if (firstSourceFile == null)
353                                 firstSourceFile = f;
354
355                         if (source_files.Contains(f))
356                                 Report.Error(1516, "Source file '" + f + "' specified multiple times");
357                         else
358                                 source_files.Add(f, new FileToCompile(fileName, currentEncoding));
359                 }
360
361                 ArrayList defines = new ArrayList();
362                 ArrayList references = new ArrayList();
363                 ArrayList soft_references = new ArrayList();
364                 ArrayList addedNetModules = new ArrayList();
365                 ArrayList libpath = new ArrayList();
366                 
367                 string firstSourceFile = null;
368                 Target target = Target.Exe;
369                 string target_ext = ".exe";
370                 ArrayList debug_arglist = new ArrayList ();
371                 bool timestamps = false;
372                 Hashtable source_files = new Hashtable ();
373                 bool load_default_config = true;
374
375                 //
376                 // Last time we took the time
377                 //
378                 DateTime last_time;
379                 void ShowTime (string msg)
380                 {
381                         DateTime now = DateTime.Now;
382                         TimeSpan span = now - last_time;
383                         last_time = now;
384
385                         Console.WriteLine (
386                                 "[{0:00}:{1:000}] {2}",
387                                 (int) span.TotalSeconds, span.Milliseconds, msg);
388                 }
389                         
390                 public int LoadAssembly (string assembly, bool soft)
391                 {
392                         Assembly a;
393                         string total_log = "";
394
395                         try  {
396                                 char[] path_chars = { '/', '\\' };
397
398                                 if (assembly.IndexOfAny (path_chars) != -1)
399                                         a = Assembly.LoadFrom(assembly);
400                                 else {
401                                         string ass = assembly;
402                                         if (ass.EndsWith (".dll"))
403                                                 ass = assembly.Substring (0, assembly.Length - 4);
404                                         a = Assembly.Load (ass);
405                                 }
406                                 TypeManager.AddAssembly (a);
407                                 return 0;
408                         }
409                         catch (FileNotFoundException) {
410                                 if (libpath != null) {
411                                         foreach (string dir in libpath) {
412                                                 string full_path = dir + "/" + assembly + ".dll";
413
414                                                 try  {
415                                                         a = Assembly.LoadFrom (full_path);
416                                                         TypeManager.AddAssembly (a);
417                                                         return 0;
418                                                 } 
419                                                 catch (FileNotFoundException ff)  {
420                                                         total_log += ff.FusionLog;
421                                                         continue;
422                                                 }
423                                         }
424                                 }
425                                 if (soft)
426                                         return 0;
427                         }
428                         catch (BadImageFormatException f)  {
429                                 Error ("// Bad file format while loading assembly");
430                                 Error ("Log: " + f.FusionLog);
431                                 return 1;
432                         } catch (FileLoadException f){
433                                 Error ("File Load Exception: " + assembly);
434                                 Error ("Log: " + f.FusionLog);
435                                 return 1;
436                         } catch (ArgumentNullException){
437                                 Error ("// Argument Null exception ");
438                                 return 1;
439                         }
440                         
441                         Report.Error (6, "Can not find assembly `" + assembly + "'" );
442                         Console.WriteLine ("Log: \n" + total_log);
443
444                         return 0;
445                 }
446
447                 public bool ReferencePackage(string packageName)
448                 {
449                         if (packageName == ""){
450                                 DoAbout ();
451                                 return false;
452                         }
453                                 
454                         ProcessStartInfo pi = new ProcessStartInfo ();
455                         pi.FileName = "pkg-config";
456                         pi.RedirectStandardOutput = true;
457                         pi.UseShellExecute = false;
458                         pi.Arguments = "--libs " + packageName;
459                         Process p = null;
460                         try {
461                                 p = Process.Start (pi);
462                         } catch (Exception e) {
463                                 Report.Error (-27, "Couldn't run pkg-config: " + e.Message);
464                                 return false;
465                         }
466
467                         if (p.StandardOutput == null){
468                                 Report.Warning (-27, "Specified package did not return any information");
469                         }
470                         string pkgout = p.StandardOutput.ReadToEnd ();
471                         p.WaitForExit ();
472                         if (p.ExitCode != 0) {
473                                 Report.Error (-27, "Error running pkg-config. Check the above output.");
474                                 return false;
475                         }
476                         p.Close ();
477                         
478                         if (pkgout != null) {
479                                 string [] xargs = pkgout.Trim (new Char [] {' ', '\n', '\r', '\t'}).
480                                         Split (new Char [] { ' ', '\t'});
481                                 foreach(string arg in xargs) {
482                                         string[] zargs = arg.Split(':', '=');
483                                         try {
484                                                 if (zargs.Length > 1)
485                                                         AddedReference = zargs[1];
486                                                 else
487                                                         AddedReference = arg;
488                                         } catch (Exception e) {
489                                                 Report.Error (-27, "Something wrong with argument (" + arg + ") in 'pkg-config --libs' output: " + e.Message);
490                                                 return false;
491                                         }
492                                 }
493                         }
494
495                         return true;
496                 }
497
498                 public void LoadModule (MethodInfo adder_method, string module)
499                 {
500                         System.Reflection.Module m;
501                         string total_log = "";
502
503                         try {
504                                 try {
505                                         m = (System.Reflection.Module)adder_method.Invoke (CodeGen.AssemblyBuilder, new object [] { module });
506                                 }
507                                 catch (TargetInvocationException ex) {
508                                         throw ex.InnerException;
509                                 }
510                                 TypeManager.AddModule (m);
511
512                         } 
513                         catch (FileNotFoundException) {
514                                 foreach (string dir in libpath) {
515                                         string full_path = Path.Combine (dir, module);
516                                         if (!module.EndsWith (".netmodule"))
517                                                 full_path += ".netmodule";
518
519                                         try {
520                                                 try {
521                                                         m = (System.Reflection.Module) adder_method.Invoke (CodeGen.AssemblyBuilder, new object [] { full_path });
522                                                 }
523                                                 catch (TargetInvocationException ex) {
524                                                         throw ex.InnerException;
525                                                 }
526                                                 TypeManager.AddModule (m);
527                                                 return;
528                                         }
529                                         catch (FileNotFoundException ff) {
530                                                 total_log += ff.FusionLog;
531                                                 continue;
532                                         }
533                                 }
534                                 Report.Error (6, "Cannot find module `" + module + "'" );
535                                 Console.WriteLine ("Log: \n" + total_log);
536                         }
537                         catch (BadImageFormatException f) {
538                                 Report.Error(6, "Cannot load module (bad file format)" + f.FusionLog);
539                         }
540                         catch (FileLoadException f)     {
541                                 Report.Error(6, "Cannot load module " + f.FusionLog);
542                         }
543                         catch (ArgumentNullException) {
544                                 Report.Error(6, "Cannot load module (null argument)");
545                         }
546                 }
547
548                 void Error(string message)
549                 {
550                         Console.WriteLine(message);
551                 }
552
553                 /// <summary>
554                 ///   Loads all assemblies referenced on the command line
555                 /// </summary>
556                 public int LoadReferences ()
557                 {
558                         int errors = 0;
559
560                         foreach (string r in references)
561                                 errors += LoadAssembly (r, false);
562
563                         foreach (string r in soft_references)
564                                 errors += LoadAssembly (r, true);
565                         
566                         return errors;
567                 }
568
569                 void SetupDefaultDefines ()
570                 {
571                         defines = new ArrayList ();
572                         defines.Add ("__MonoBASIC__");
573                 }
574                 
575                 void SetupDefaultImports()
576                 {
577                         Mono.MonoBASIC.Parser.ImportsList = new ArrayList();
578                         Mono.MonoBASIC.Parser.ImportsList.Add("Microsoft.VisualBasic");
579                 }
580
581                 //
582                 // Given a path specification, splits the path from the file/pattern
583                 //
584                 void SplitPathAndPattern (string spec, out string path, out string pattern)
585                 {
586                         int p = spec.LastIndexOf ("/");
587                         if (p != -1){
588                                 //
589                                 // Windows does not like /file.cs, switch that to:
590                                 // "\", "file.cs"
591                                 //
592                                 if (p == 0){
593                                         path = "\\";
594                                         pattern = spec.Substring (1);
595                                 } else {
596                                         path = spec.Substring (0, p);
597                                         pattern = spec.Substring (p + 1);
598                                 }
599                                 return;
600                         }
601
602                         p = spec.LastIndexOf ("\\");
603                         if (p != -1){
604                                 path = spec.Substring (0, p);
605                                 pattern = spec.Substring (p + 1);
606                                 return;
607                         }
608
609                         path = ".";
610                         pattern = spec;
611                 }
612
613                 bool AddFiles (string spec, bool recurse)
614                 {
615                         string path, pattern;
616
617                         SplitPathAndPattern(spec, out path, out pattern);
618                         if (pattern.IndexOf("*") == -1) {
619                                 AddFile(spec);
620                                 return true;
621                         }
622
623                         string [] files = null;
624                         try {
625                                 files = Directory.GetFiles(path, pattern);
626                         } catch (System.IO.DirectoryNotFoundException) {
627                                 Report.Error (2001, "Source file `" + spec + "' could not be found");
628                                 return false;
629                         } catch (System.IO.IOException){
630                                 Report.Error (2001, "Source file `" + spec + "' could not be found");
631                                 return false;
632                         }
633                         foreach (string f in files)
634                                 AddFile (f);
635
636                         if (!recurse)
637                                 return true;
638                         
639                         string [] dirs = null;
640
641                         try {
642                                 dirs = Directory.GetDirectories(path);
643                         } catch {
644                         }
645                         
646                         foreach (string d in dirs) {
647                                         
648                                 // Don't include path in this string, as each
649                                 // directory entry already does
650                                 AddFiles (d + "/" + pattern, true);
651                         }
652
653                         return true;
654                 }
655
656                 void DefineDefaultConfig ()
657                 {
658                         //
659                         // For now the "default config" is harcoded into the compiler
660                         // we can move this outside later
661                         //
662                         string [] default_config = 
663                         {
664                                 "System",
665                                 "System.Data",
666                                 "System.Xml",
667                                 "Microsoft.VisualBasic" , 
668 #if EXTRA_DEFAULT_REFS
669                                 //
670                                 // Is it worth pre-loading all this stuff?
671                                 //
672                                 "Accessibility",
673                                 "System.Configuration.Install",
674                                 "System.Design",
675                                 "System.DirectoryServices",
676                                 "System.Drawing.Design",
677                                 "System.Drawing",
678                                 "System.EnterpriseServices",
679                                 "System.Management",
680                                 "System.Messaging",
681                                 "System.Runtime.Remoting",
682                                 "System.Runtime.Serialization.Formatters.Soap",
683                                 "System.Security",
684                                 "System.ServiceProcess",
685                                 "System.Web",
686                                 "System.Web.RegularExpressions",
687                                 "System.Web.Services" ,
688                                 "System.Windows.Forms"
689 #endif
690                         };
691                         
692                         foreach (string def in default_config)
693                                 if (!(references.Contains(def) || references.Contains (def + ".dll")))
694                                         soft_references.Add(def);
695                 }
696
697                 string outputFile_Name = null;
698
699                 string outputFileName {
700                         get 
701                         {
702                                 if (outputFile_Name == null) {
703                                         if (OutputFileName == null) {
704                                                 int pos = firstSourceFile.LastIndexOf(".");
705
706                                                 if (pos > 0)
707                                                         OutputFileName = firstSourceFile.Substring(0, pos);
708                                                 else
709                                                         OutputFileName = firstSourceFile;
710                                         }
711                                         string bname = CodeGen.Basename(OutputFileName);
712                                         if (bname.IndexOf(".") == -1)
713                                                 OutputFileName +=  target_ext;
714                                         outputFile_Name = OutputFileName;
715                                 }
716                                 return outputFile_Name;
717                         }
718                 }
719
720                 bool ParseAll() // Phase 1
721                 {
722                         if (tokenize)
723                                 return false;
724                                 
725                         foreach(FileToCompile file in source_files.Values)
726                                 file.Process();
727
728                         if (parse_only || (Report.Errors > 0))
729                                 return false;           
730
731                         return true; // everything went well go ahead
732                 }
733
734                 void InitializeDebuggingSupport()
735                 {
736                         string[] debug_args = new string [debug_arglist.Count];
737                         debug_arglist.CopyTo(debug_args);
738                         CodeGen.Init(outputFileName, outputFileName, want_debugging_support, debug_args);
739                         TypeManager.AddModule(CodeGen.ModuleBuilder);
740                 }
741
742                 public bool ResolveAllTypes() // Phase 2
743                 {
744                         // Load Core Library for default compilation
745                         if (RootContext.StdLib)
746                                 references.Insert(0, "mscorlib");
747
748                         if (load_default_config)
749                                 DefineDefaultConfig();
750
751                         if (timestamps)
752                                 ShowTime("Loading references");
753
754                         // Load assemblies required
755                         if (LoadReferences() > 0) {
756                                 Error ("Could not load one or more assemblies");
757                                 return false;
758                         }
759
760                         if (timestamps)
761                                 ShowTime("References loaded");
762
763                         InitializeDebuggingSupport();
764
765                         // target is Module 
766                         if (target == Target.Module) {
767                                 PropertyInfo module_only = typeof (AssemblyBuilder).GetProperty ("IsModuleOnly", BindingFlags.Instance|BindingFlags.Public|BindingFlags.NonPublic);
768                                 if (module_only == null) {
769                                         Report.Error (0, new Location (-1, -1), "Cannot use /target:module on this runtime: try the Mono runtime instead.");
770                                         Environment.Exit (1);
771                                 }
772
773                                 MethodInfo set_method = module_only.GetSetMethod (true);
774                                 set_method.Invoke (CodeGen.AssemblyBuilder, BindingFlags.Default, null, new object[]{true}, null);
775
776                                 TypeManager.AddModule (CodeGen.ModuleBuilder);
777                         }
778
779                         if (addedNetModules.Count > 0) {
780                                 MethodInfo adder_method = typeof (AssemblyBuilder).GetMethod ("AddModule", BindingFlags.Instance|BindingFlags.NonPublic);
781                                 if (adder_method == null) {
782                                         Report.Error (0, new Location (-1, -1), "Cannot use /addmodule on this runtime: Try the Mono runtime instead.");
783                                         Environment.Exit (1);
784                                 }
785
786                                 foreach (string module in addedNetModules)
787                                         LoadModule (adder_method, module);
788                         }
789
790
791                         //
792                         // Before emitting, we need to get the core
793                         // types emitted from the user defined types
794                         // or from the system ones.
795                         //
796                         if (timestamps)
797                                 ShowTime ("Initializing Core Types");
798
799                         if (!RootContext.StdLib)
800                                 RootContext.ResolveCore ();
801                         if (Report.Errors > 0)
802                                 return false;
803                         
804                         TypeManager.InitCoreTypes();
805                         if (Report.Errors > 0)
806                                 return false;
807
808                         if (timestamps)
809                                 ShowTime ("   Core Types done");
810
811                         if (timestamps)
812                                 ShowTime ("Resolving tree");
813
814                         // The second pass of the compiler
815                         RootContext.ResolveTree ();
816                         if (Report.Errors > 0)
817                                 return false;
818                         
819                         if (timestamps)
820                                 ShowTime ("Populate tree");
821
822                         if (!RootContext.StdLib)
823                                 RootContext.BootCorlib_PopulateCoreTypes();
824                         if (Report.Errors > 0)
825                                 return false;
826
827                         RootContext.PopulateTypes();
828                         if (Report.Errors > 0)
829                                 return false;
830                         
831                         TypeManager.InitCodeHelpers();
832                         if (Report.Errors > 0)
833                                 return false;
834
835                         return true;
836                 }
837                 
838                 bool IsSWFApp()
839                 {
840                         string mainclass = GetFQMainClass();
841                         
842                         if (mainclass != null) {
843                                 foreach (string r in references) {
844                                         if (r.IndexOf ("System.Windows.Forms") >= 0) {
845                                                 Type t = TypeManager.LookupType(mainclass);
846                                                 if (t != null) 
847                                                         return t.IsSubclassOf (TypeManager.LookupType("System.Windows.Forms.Form"));
848                                                 break;  
849                                         }       
850                                 }
851                         }
852                         return false;
853                 }
854                 
855                 string GetFQMainClass()
856                 {       
857                         if (RootContext.RootNamespace != "")
858                                 return RootContext.RootNamespace + "." + RootContext.MainClass;
859                         else
860                                 return RootContext.MainClass;                   
861                 }
862                 
863                 void FixEntryPoint()
864                 {
865                         if (target == Target.Exe || target == Target.WinExe) {
866                                 MethodInfo ep = RootContext.EntryPoint;
867                         
868                                 if (ep == null) {
869                                         // If we don't have a valid entry point yet
870                                         // AND if System.Windows.Forms is included
871                                         // among the dependencies, we have to build
872                                         // a new entry point on-the-fly. Otherwise we
873                                         // won't be able to compile SWF code out of the box.
874
875                                         if (IsSWFApp())  {
876                                                 Type t = TypeManager.LookupType(GetFQMainClass());
877                                                 if (t != null) 
878                                                 {                                                       
879                                                         TypeBuilder tb = t as TypeBuilder;
880                                                         MethodBuilder mb = tb.DefineMethod ("Main", MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard, 
881                                                                 typeof(void), new Type[0]);
882
883                                                         Type SWFA = TypeManager.LookupType("System.Windows.Forms.Application");
884                                                         Type SWFF = TypeManager.LookupType("System.Windows.Forms.Form");
885                                                         Type[] args = new Type[1];
886                                                         args[0] = SWFF;
887                                                         MethodInfo mi = SWFA.GetMethod("Run", args);
888                                                         ILGenerator ig = mb.GetILGenerator();
889                                                         ConstructorInfo ci = TypeManager.GetConstructor (TypeManager.LookupType(t.FullName), new Type[0]);
890                                                         
891                                                         ig.Emit (OpCodes.Newobj, ci);
892                                                         ig.Emit (OpCodes.Call, mi);
893                                                         ig.Emit (OpCodes.Ret);
894
895                                                         RootContext.EntryPoint = mb as MethodInfo;
896                                                 }
897                                         }
898                                 }
899                         }
900                 }
901
902                 bool GenerateAssembly()
903                 {
904                         //
905                         // The code generator
906                         //
907                         if (timestamps)
908                                 ShowTime ("Emitting code");
909                         
910                         
911
912                         RootContext.EmitCode();
913                         FixEntryPoint();
914                         if (Report.Errors > 0)
915                                 return false;
916
917                         if (timestamps)
918                                 ShowTime ("   done");
919
920
921                         if (timestamps)
922                                 ShowTime ("Closing types");
923
924                         RootContext.CloseTypes ();
925                         if (Report.Errors > 0)
926                                 return false;
927
928                         if (timestamps)
929                                 ShowTime ("   done");
930
931                         PEFileKinds k = PEFileKinds.ConsoleApplication;
932                                                         
933                         if (target == Target.Library || target == Target.Module)
934                                 k = PEFileKinds.Dll;
935                         else if (target == Target.Exe)
936                                 k = PEFileKinds.ConsoleApplication;
937                         else if (target == Target.WinExe)
938                                 k = PEFileKinds.WindowApplication;
939                         
940                         if (target == Target.Exe || target == Target.WinExe) {
941                                 MethodInfo ep = RootContext.EntryPoint;
942                         
943                                 if (ep == null) {
944                                         Report.Error (30737, "Program " + outputFileName +
945                                                 " does not have an entry point defined");
946                                         return false;
947                                 }
948                                                         
949                                 CodeGen.AssemblyBuilder.SetEntryPoint (ep, k);
950                         }
951
952                         // Add the resources
953                         if (EmbeddedResources != null)
954                                 foreach (string file in EmbeddedResources)
955                                         CodeGen.AssemblyBuilder.AddResourceFile (file, file);
956                         
957                         CodeGen.Save(outputFileName);
958
959                         if (timestamps)
960                                 ShowTime ("Saved output");
961
962                         
963                         if (want_debugging_support)  {
964                                 CodeGen.SaveSymbols ();
965                                 if (timestamps)
966                                         ShowTime ("Saved symbols");
967                         }
968
969                         return true;
970                 }
971
972                 public void CompileAll()
973                 {
974                         try {
975 /* 
976                     VB.NET expects the default namespace to be "" (empty string)                
977                     
978                     if (RootContext.RootNamespace == "") {
979                       RootContext.RootNamespace = System.IO.Path.GetFileNameWithoutExtension(outputFileName);
980                     }
981 */
982                                 if (!ParseAll()) // Phase 1
983                                         return;
984
985                                 if (!ResolveAllTypes()) // Phase 2
986                                         return;
987
988                                 GenerateAssembly(); // Phase 3 
989                                 
990                         } catch (Exception ex) {
991                                 Error("Exception: " + ex.ToString());
992                         }
993                 }
994                 
995                 private bool quiet { get { return nologo || SuccintErrorDisplay; } } 
996                 
997                 private void Banner()
998                 {
999                         if (!quiet) {
1000                                 ShowBanner();
1001                                 // TODO: remove next lines when the compiler has matured enough
1002                                 Console.WriteLine ("--------");
1003                                 Console.WriteLine ("THIS IS AN ALPHA SOFTWARE.");
1004                                 Console.WriteLine ("--------");
1005                         }               
1006                 }
1007                 
1008                 protected void SetupDefaults()
1009                 {
1010                         SetupDefaultDefines();  
1011                         SetupDefaultImports();
1012                         Report.Stacktrace = false;
1013                         RootContext.Checked = true;
1014                 }               
1015
1016                 /// <summary>
1017                 ///    Parses the arguments, and calls the compilation process.
1018                 /// </summary>
1019                 int MainDriver(string [] args)
1020                 {
1021                         SetupDefaults();
1022                         ProcessArgs(args);
1023                         
1024                         if (firstSourceFile == null) {
1025                                 if (!quiet) 
1026                                         DoHelp();
1027                                 return 2;
1028                         }
1029
1030                         Banner();                       
1031                         CompileAll();
1032                         return Report.ProcessResults(quiet);
1033                 }
1034
1035                 public static int Main (string[] args)
1036                 {
1037                         Driver Exec = new Driver();
1038                         
1039                         return Exec.MainDriver(args);
1040                 }
1041
1042         }
1043 }