2003-07-16 Gonzalo Paniagua Javier <gonzalo@ximian.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 Rafael Teixeira
10 //
11
12 namespace Mono.Languages
13 {
14         using System;
15         using System.Reflection;
16         using System.Reflection.Emit;
17         using System.Collections;
18         using System.IO;
19         using System.Globalization;
20         using Mono.CSharp;
21         using Mono.GetOptions;
22
23         enum Target 
24         {
25                 Library, Exe, Module, WinExe
26         };
27         
28         enum OptionCompare
29         {
30                 Binary, Text
31         };
32         
33         /// <summary>
34         ///    The compiler driver.
35         /// </summary>
36         public class Driver : Options
37         {
38                 // Temporary options
39                 //------------------------------------------------------------------
40                 [Option("[Mono] Only parses the source file (for debugging the tokenizer)", "parse")]
41                 public bool parse_only = false;
42
43                 [Option("[Mono] Only tokenizes source files")]
44                 public bool tokenize = false;
45
46                 [Option("[Mono] Shows stack trace at Error location")]
47                 public bool stacktrace { set { Report.Stacktrace = value; } }
48
49                 [Option("[Mono] Displays time stamps of various compiler events")]
50                 public bool timestamp
51                 {
52                         set
53                         {
54                                 timestamps = true;
55                                 last_time = DateTime.Now;
56                                 debug_arglist.Add("timestamp");
57                         }
58                 }
59
60                 // Mono-specific options
61                 //------------------------------------------------------------------
62                 [Option("About the MonoBASIC compiler", "about")]
63                 public override WhatToDoNext DoAbout()
64                 {
65                         return base.DoAbout();
66                 }
67
68                 [Option("[Mono] Don\'t assume the standard library", "nostdlib")]
69                 public bool nostdlib { set { RootContext.StdLib = !value; } }
70
71                 [Option("[Mono] Disables implicit references to assemblies", "noconfig")]
72                 public bool NoConfig { set { load_default_config = !value; } }
73
74                 [Option("[Mono] Allows unsafe code", "unsafe")]
75                 public bool AllowUnsafeCode { set { RootContext.Unsafe = value; } }
76
77                 [Option("[Mono] Set default context to checked", "checked")]
78                 public bool Checked { set { RootContext.Checked = value; } }
79
80                 [Option("[Mono] Debugger arguments", "debug-args")]
81                 public WhatToDoNext SetDebugArgs(string args)
82                 {
83                         char[] sep = { ',' };
84                         debug_arglist.AddRange (args.Split (sep));
85                         return WhatToDoNext.GoAhead;
86                 }
87
88                 [Option("[Mono] Ignores warning number PARAM", "ignorewarn")]
89                 public WhatToDoNext SetIgnoreWarning(int warn)
90                 {
91                         Report.SetIgnoreWarning(warn);
92                         return WhatToDoNext.GoAhead;
93                 }       
94
95                 [Option("[Mono] Sets warning level (the highest is 4, the default)", "wlevel")]
96                 public int wlevel { set { RootContext.WarningLevel = value; } }
97
98                 [Option("[Mono] Makes errors fatal", "fatal")]
99                 public bool Fatal { set { Report.Fatal = value; } }
100
101                 [Option("[Mono] Adds path to the assembly link path")]
102                 public string[] linkpaths = null;
103
104                 // Output file options
105                 //------------------------------------------------------------------
106                 [Option("Specifies the output file name", 'o', "out")]
107                 public string output_file = null;
108
109                 [Option("Specifies the target type for the output file (exe [default], winexe, library, module)", "target")]
110                 public WhatToDoNext SetTarget(string type)
111                 {
112                         switch (type.ToLower())
113                         {
114                                 case "library":
115                                         target = Target.Library;
116                                         target_ext = ".dll";
117                                         break;
118                                                         
119                                 case "exe":
120                                         target = Target.Exe;
121                                         break;
122                                                         
123                                 case "winexe":
124                                         target = Target.WinExe;
125                                         break;
126                                                         
127                                 case "module":
128                                         target = Target.Module;
129                                         target_ext = ".dll";
130                                         break;
131                         }
132                         return WhatToDoNext.GoAhead;
133                 }
134
135                 // input file options
136                 //------------------------------------------------------------------
137                 [Option("[NOT IMPLEMENTED YET]Reference metadata from specified module", "addmodule")]
138                 public string[] addedModules = null;
139
140                 [Option("[NOT IMPLEMENTED YET]Include all files in the current directory and subdirectories according to the wildcard", "recurse")]
141                 public WhatToDoNext recurse(string wildcard)
142                 {
143                         //AddFiles (DirName, true); // TODO wrong semantics
144                         return WhatToDoNext.GoAhead;
145                 }
146
147                 [Option(-1, "References metadata from the specified assembly", 'r', "reference")]
148                 public string reference { set { references.Add(value); } }
149
150                 // resource options
151                 //------------------------------------------------------------------
152                 public ArrayList EmbeddedResources = new ArrayList();
153                 
154                 // TODO : accept a multi-letter short form: 'res'
155                 [Option(-1, "Adds the specified file as an embedded assembly resource", "resource")]
156                 public string resource { set { EmbeddedResources.Add(value); } }
157
158                 public ArrayList LinkedResources = new ArrayList();
159                 
160                 // TODO : accept a multi-letter short form: 'linkres'
161                 [Option(-1, "[NOT IMPLEMENTED YET]Adds the specified file as an embedded assembly resource", "linkresource")]
162                 public string linkresource { set { LinkedResources.Add(value); } }
163
164                 public ArrayList Win32Resources = new ArrayList();
165                 
166                 [Option(-1, "[NOT IMPLEMENTED YET]Specifies a Win32 resource file (.res)", "win32resource")]
167                 public string win32resource { set { Win32Resources.Add(value); } }
168
169                 public ArrayList Win32Icons = new ArrayList();
170                 
171                 // TODO : accept a multi-letter short form: 'res'
172                 [Option(-1, "[NOT IMPLEMENTED YET]Specifies a Win32 icon file (.ico) for the default Win32 resources", "win32icon")]
173                 public string win32icon { set { Win32Icons.Add(value); } }
174
175
176                 // code generation options
177                 //------------------------------------------------------------------
178                 [Option("[NOT IMPLEMENTED YET]Enable optimizations")]
179                 public bool optimize = false;
180
181                 [Option("[NOT IMPLEMENTED YET]Remove integer checks. Default off.")]
182                 public bool removeintchecks = false;
183
184                 // TODO: handle VB.NET [+|-] boolean syntax
185                 [Option("Emit debugging information", "debug")]
186                 public bool want_debugging_support = false;
187
188                 [Option("Emit full debugging information (default)", "debug:full")]
189                 public bool fullDebugging = false;
190
191                 [Option("[IGNORED]Emit PDB file only", "debug:pdbonly")]
192                 public bool pdbOnly = false;
193
194                 // errors and warnings options
195                 //------------------------------------------------------------------
196                 [Option("Treat warnings as errors", "warnaserror")]
197                 public bool WarningsAreErrors { set { Report.WarningsAreErrors = value; } }
198
199                 [Option("Disable warnings")]
200                 public bool nowarn { set { if (value) RootContext.WarningLevel = 0; } }
201
202
203                 // language options
204                 //------------------------------------------------------------------
205                 public Hashtable Defines = new Hashtable();
206                 
207                 // TODO: Symbol-List parsing
208                 [Option(-1, "[NOT IMPLEMENTED YET]Declares global conditional compilation symbol(s). symbol list:name=value,...", 'd', "define")]
209                 public string define { 
210                         set {
211                                 foreach(string item in value.Split(',')) {      
212                                         string[] dados = item.Split('=');
213                                         if (dados.Length > 1)
214                                                 Defines.Add(dados[0], dados[1]); 
215                                         else
216                                                 Defines.Add(dados[0], string.Empty);
217                                 }
218                         } 
219                 }
220                 
221                 private string[] importsList = null;
222                 
223                 [Option("[NOT IMPLEMENTED YET]Declare global Imports for namespaces in referenced metadata files. import list:namespace,...", "imports")]
224                 public WhatToDoNext imports(string importslist)
225                 {
226                         importsList = importslist.Split(';');
227                         return WhatToDoNext.GoAhead;
228                 }
229
230                 // TODO: handle VB.NET [+|-] boolean syntax
231                 [Option("[NOT IMPLEMENTED YET]Require explicit declaration of variables")]
232                 public bool optionexplicit { set { Mono.MonoBASIC.Parser.InitialOptionExplicit = value; } }
233
234                 // TODO: handle VB.NET [+|-] boolean syntax
235                 [Option("[NOT IMPLEMENTED YET]Enforce strict language semantics")]
236                 public bool optionstrict { set { Mono.MonoBASIC.Parser.InitialOptionStrict = value; } }
237                 
238                 [Option("[NOT IMPLEMENTED YET]Specifies binary-style string comparisons. This is the default", "optioncompare:binary")]
239                 public bool optioncomparebinary { set { Mono.MonoBASIC.Parser.InitialOptionCompareBinary = true; } }
240
241                 [Option("[NOT IMPLEMENTED YET]Specifies text-style string comparisons.", "optioncompare:text")]
242                 public bool optioncomparetext { set { Mono.MonoBASIC.Parser.InitialOptionCompareBinary = false; } }
243
244                 [Option("Specifies de root namespace for all type declarations")]
245                 public string rootnamespace { set { RootContext.RootNamespace = value; } }
246                 
247                 // Miscellaneous options        
248                 //------------------------------------------------------------------
249                 
250                 [Option("[NOT IMPLEMENTED YET]Do not display compiler copyright banner")]
251                 public bool nologo = false;
252                 
253                 [Option("[NOT IMPLEMENTED YET]Quiet output mode")]
254                 public bool quiet = false;
255                 
256                 // TODO: semantics are different and should be adjusted
257                 [Option("Display verbose messages", 'v')] 
258                 public bool verbose     { set { GenericParser.yacc_verbose_flag = value; } }
259
260                 // Advanced options     
261                 //------------------------------------------------------------------
262                 // TODO: force option to accept number in hex format
263                 [Option("[NOT IMPLEMENTED YET]The base address for a library or module (hex)")]
264                 public int baseaddress;
265                 
266                 [Option("[NOT IMPLEMENTED YET]Create bug report file")]
267                 public string bugreport;
268                 
269                 // TODO: handle VB.NET [+|-] boolean syntax
270                 [Option("[NOT IMPLEMENTED YET]Delay-sign the assembly using only the public portion of the strong name key")]
271                 public bool delaysign;
272                 
273                 [Option("[NOT IMPLEMENTED YET]Specifies a strong name key container")]
274                 public string keycontainer;
275                 
276                 [Option("[NOT IMPLEMENTED YET]Specifies a strong name key file")]
277                 public string keyfile;
278
279                 public string[] libpath = null;
280                 
281                 [Option("[NOT IMPLEMENTED YET]List of directories to search for metada references (semi-colon delimited)", "libpath")]
282                 public WhatToDoNext setlibpath(string pathlist)
283                 {
284                         libpath = pathlist.Split(';');
285                         return WhatToDoNext.GoAhead;
286                 }
287
288                 [Option(@"Specifies the Class or Module that contains Sub Main.
289                         It can also be a Class that inherits from System.Windows.Forms.Form.",
290                         'm', "main")]
291                 public string main { set { RootContext.MainClass = value; } }
292
293                 // TODO: handle VB.NET [+|-] boolean syntax
294                 [Option("[NOT IMPLEMENTED YET]Emit compiler output in UTF8 character encoding")]
295                 public bool utf8output;
296
297                 // TODO : response file support
298                 
299                 ArrayList defines = new ArrayList();
300                 ArrayList references = new ArrayList();
301                 ArrayList soft_references = new ArrayList();
302                 string first_source = null;
303                 Target target = Target.Exe;
304                 string target_ext = ".exe";
305                 ArrayList debug_arglist = new ArrayList ();
306                 bool timestamps = false;
307                 Hashtable source_files = new Hashtable ();
308                 bool load_default_config = true;
309
310                 //
311                 // Last time we took the time
312                 //
313                 DateTime last_time;
314                 void ShowTime (string msg)
315                 {
316                         DateTime now = DateTime.Now;
317                         TimeSpan span = now - last_time;
318                         last_time = now;
319
320                         Console.WriteLine (
321                                 "[{0:00}:{1:000}] {2}",
322                                 (int) span.TotalSeconds, span.Milliseconds, msg);
323                 }
324                         
325                 public static int Main (string[] args)
326                 {
327                         Driver Exec = new Driver();
328
329                         return Exec.MainDriver(args);
330                 }
331
332                 public int LoadAssembly (string assembly, bool soft)
333                 {
334                         Assembly a;
335                         string total_log = "";
336
337                         try {
338                                 char[] path_chars = { '/', '\\' };
339
340                                 if (assembly.IndexOfAny (path_chars) != -1)
341                                         a = Assembly.LoadFrom(assembly);
342                                 else
343                                         a = Assembly.Load(assembly);
344                                 TypeManager.AddAssembly (a);
345                                 return 0;
346                         } catch (FileNotFoundException){
347                                 foreach (string dir in linkpaths){
348                                         string full_path = dir + "/" + assembly + ".dll";
349
350                                         try {
351                                                 a = Assembly.LoadFrom (full_path);
352                                                 TypeManager.AddAssembly (a);
353                                                 return 0;
354                                         } catch (FileNotFoundException ff) {
355                                                 total_log += ff.FusionLog;
356                                                 continue;
357                                         }
358                                 }
359                                 if (soft)
360                                         return 0;
361                         } catch (BadImageFormatException f) {
362                                 Error ("// Bad file format while loading assembly");
363                                 Error ("Log: " + f.FusionLog);
364                                 return 1;
365                         } catch (FileLoadException f){
366                                 Error ("File Load Exception: " + assembly);
367                                 Error ("Log: " + f.FusionLog);
368                                 return 1;
369                         } catch (ArgumentNullException){
370                                 Error ("// Argument Null exception ");
371                                 return 1;
372                         }
373                         
374                         Report.Error (6, "Can not find assembly `" + assembly + "'" );
375                         Console.WriteLine ("Log: \n" + total_log);
376
377                         return 0;
378                 }
379
380                 void Error(string message)
381                 {
382                         Console.WriteLine(message);
383                 }
384
385                 /// <summary>
386                 ///   Loads all assemblies referenced on the command line
387                 /// </summary>
388                 public int LoadReferences ()
389                 {
390                         int errors = 0;
391
392                         foreach (string r in references)
393                                 errors += LoadAssembly (r, false);
394
395                         foreach (string r in soft_references)
396                                 errors += LoadAssembly (r, true);
397                         
398                         return errors;
399                 }
400
401                 void SetupDefaultDefines ()
402                 {
403                         defines = new ArrayList ();
404                         defines.Add ("__MonoBASIC__");
405                 }
406
407
408                 //
409                 // Returns the directory where the system assemblies are installed
410                 //
411                 string GetSystemDir ()
412                 {
413                         Assembly [] assemblies = AppDomain.CurrentDomain.GetAssemblies ();
414
415                         foreach (Assembly a in assemblies){
416                                 string codebase = a.CodeBase;
417                                 if (codebase.EndsWith ("corlib.dll")){
418                                         return codebase.Substring (0, codebase.LastIndexOf ("/"));
419                                 }
420                         }
421
422                         Report.Error (-15, "Can not compute my system path");
423                         return "";
424                 }
425
426                 //
427                 // Given a path specification, splits the path from the file/pattern
428                 //
429                 void SplitPathAndPattern (string spec, out string path, out string pattern)
430                 {
431                         int p = spec.LastIndexOf ("/");
432                         if (p != -1){
433                                 //
434                                 // Windows does not like /file.cs, switch that to:
435                                 // "\", "file.cs"
436                                 //
437                                 if (p == 0){
438                                         path = "\\";
439                                         pattern = spec.Substring (1);
440                                 } else {
441                                         path = spec.Substring (0, p);
442                                         pattern = spec.Substring (p + 1);
443                                 }
444                                 return;
445                         }
446
447                         p = spec.LastIndexOf ("\\");
448                         if (p != -1){
449                                 path = spec.Substring (0, p);
450                                 pattern = spec.Substring (p + 1);
451                                 return;
452                         }
453
454                         path = ".";
455                         pattern = spec;
456                 }
457
458                 bool AddFiles (string spec, bool recurse)
459                 {
460                         string path, pattern;
461
462                         SplitPathAndPattern(spec, out path, out pattern);
463                         if (pattern.IndexOf("*") == -1)
464                         {
465                                 AddFile(spec);
466                                 return true;
467                         }
468
469                         string [] files = null;
470                         try {
471                                 files = Directory.GetFiles(path, pattern);
472                         } catch (System.IO.DirectoryNotFoundException) {
473                                 Report.Error (2001, "Source file `" + spec + "' could not be found");
474                                 return false;
475                         } catch (System.IO.IOException){
476                                 Report.Error (2001, "Source file `" + spec + "' could not be found");
477                                 return false;
478                         }
479                         foreach (string f in files)
480                                 AddFile (f);
481
482                         if (!recurse)
483                                 return true;
484                         
485                         string [] dirs = null;
486
487                         try {
488                                 dirs = Directory.GetDirectories(path);
489                         } catch {
490                         }
491                         
492                         foreach (string d in dirs) {
493                                         
494                                 // Don't include path in this string, as each
495                                 // directory entry already does
496                                 AddFiles (d + "/" + pattern, true);
497                         }
498
499                         return true;
500                 }
501
502                 void DefineDefaultConfig ()
503                 {
504                         //
505                         // For now the "default config" is harcoded into the compiler
506                         // we can move this outside later
507                         //
508                         string [] default_config = 
509                         {
510                                 "System",
511                                 "System.Data",
512                                 "System.Xml",
513                                 "Microsoft.VisualBasic" , 
514 #if EXTRA_DEFAULT_REFS
515                                 //
516                                 // Is it worth pre-loading all this stuff?
517                                 //
518                                 "Accessibility",
519                                 "System.Configuration.Install",
520                                 "System.Design",
521                                 "System.DirectoryServices",
522                                 "System.Drawing.Design",
523                                 "System.Drawing",
524                                 "System.EnterpriseServices",
525                                 "System.Management",
526                                 "System.Messaging",
527                                 "System.Runtime.Remoting",
528                                 "System.Runtime.Serialization.Formatters.Soap",
529                                 "System.Security",
530                                 "System.ServiceProcess",
531                                 "System.Web",
532                                 "System.Web.RegularExpressions",
533                                 "System.Web.Services" ,
534                                 "System.Windows.Forms"
535 #endif
536                         };
537                         
538                         foreach (string def in default_config)
539                                 soft_references.Add(def);
540                 }
541
542                 [ArgumentProcessor]
543                 public void AddFile(string fileName)
544                 {
545                         string f = fileName;
546                         if (first_source == null)
547                                 first_source = f;
548
549                         if (source_files.Contains(f))
550                                 Report.Error(1516, "Source file '" + f + "' specified multiple times");
551                         else
552                                 source_files.Add(f, f);
553                 }
554
555                 void ProcessSourceFile(string filename)
556                 {
557                         if (tokenize)
558                                 GenericParser.Tokenize(filename);
559                         else
560                                 GenericParser.Parse(filename);
561                 }
562
563                 string outputFile_Name = null;
564
565                 string outputFileName
566                 {
567                         get 
568                         {
569                                 if (outputFile_Name == null)
570                                 {
571                                         if (output_file == null)
572                                         {
573                                                 int pos = first_source.LastIndexOf(".");
574
575                                                 if (pos > 0)
576                                                         output_file = first_source.Substring(0, pos);
577                                                 else
578                                                         output_file = first_source;
579                                         }
580                                         string bname = CodeGen.Basename(output_file);
581                                         if (bname.IndexOf(".") == -1)
582                                                 output_file +=  target_ext;
583                                         outputFile_Name = output_file;
584                                 }
585                                 return outputFile_Name;
586                         }
587                 }
588
589                 /// <summary>
590                 ///    Parses the arguments, and calls the compilation process.
591                 /// </summary>
592                 int MainDriver(string [] args)
593                 {
594                         ProcessArgs(args);
595                         if (first_source == null)
596                         {
597                                 DoHelp();
598                                 return 2;
599                         }
600
601                         CompileAll();
602
603                         if (Report.Errors == 0) 
604                         {
605                                 Console.Write("Compilation succeeded");
606                                 if (Report.Warnings > 0) 
607                                 {
608                                         Console.Write(" - {0} warning(s)", Report.Warnings);
609                                 } 
610                                 Console.WriteLine();
611                                 return 0;
612                         } 
613                         Console.WriteLine("Compilation failed: {0} Error(s), {1} warnings",
614                                 Report.Errors, Report.Warnings);
615                         return 1;
616                 }
617
618                 public Driver()
619                 {
620                         SetupDefaultDefines();  
621                 }
622
623                 bool ParseAll() // Phase 1
624                 {
625                         if (first_source == null)
626                         {
627                                 Report.Error(2008, "No files to compile were specified");
628                                 return false;
629                         }
630
631                         foreach(string filename in source_files.Values)
632                                 ProcessSourceFile(filename);
633
634                         if (tokenize || parse_only || (Report.Errors > 0))
635                                 return false;           
636
637                         return true; // everything went well go ahead
638                 }
639
640                 void InitializeDebuggingSupport()
641                 {
642                         string[] debug_args = new string [debug_arglist.Count];
643                         debug_arglist.CopyTo(debug_args);
644                         CodeGen.Init(outputFileName, outputFileName, want_debugging_support, debug_args);
645                         TypeManager.AddModule(CodeGen.ModuleBuilder);
646                 }
647
648                 public bool ResolveAllTypes() // Phase 2
649                 {
650                         // Load Core Library for default compilation
651                         if (RootContext.StdLib)
652                                 references.Insert(0, "mscorlib");
653
654                         if (load_default_config)
655                                 DefineDefaultConfig();
656
657                         if (timestamps)
658                                 ShowTime("Loading references");
659
660                         // Load assemblies required
661                         if (LoadReferences() > 0)
662                         {
663                                 Error ("Could not load one or more assemblies");
664                                 return false;
665                         }
666
667                         if (timestamps)
668                                 ShowTime("References loaded");
669
670                         InitializeDebuggingSupport();
671
672                         //
673                         // Before emitting, we need to get the core
674                         // types emitted from the user defined types
675                         // or from the system ones.
676                         //
677                         if (timestamps)
678                                 ShowTime ("Initializing Core Types");
679
680                         if (!RootContext.StdLib)
681                                 RootContext.ResolveCore ();
682                         if (Report.Errors > 0)
683                                 return false;
684                         
685                         TypeManager.InitCoreTypes();
686                         if (Report.Errors > 0)
687                                 return false;
688
689                         if (timestamps)
690                                 ShowTime ("   Core Types done");
691
692                         if (timestamps)
693                                 ShowTime ("Resolving tree");
694
695                         // The second pass of the compiler
696                         RootContext.ResolveTree ();
697                         if (Report.Errors > 0)
698                                 return false;
699                         
700                         if (timestamps)
701                                 ShowTime ("Populate tree");
702
703                         if (!RootContext.StdLib)
704                                 RootContext.BootCorlib_PopulateCoreTypes();
705                         if (Report.Errors > 0)
706                                 return false;
707
708                         RootContext.PopulateTypes();
709                         if (Report.Errors > 0)
710                                 return false;
711                         
712                         TypeManager.InitCodeHelpers();
713                         if (Report.Errors > 0)
714                                 return false;
715
716                         return true;
717                 }
718                 
719                 bool IsSWFApp()
720                 {
721                         bool hasSWF = false, isForm = false;
722                         string mainclass = GetFQMainClass();
723                         
724                         foreach (string r in references) {
725                                 if (r.IndexOf ("System.Windows.Forms") >= 0) {
726                                         hasSWF = true;
727                                         break;  
728                                 }       
729                         }       
730                         if (mainclass != ".") {
731                                 Type t = TypeManager.LookupType(mainclass);
732                                 if (t != null) 
733                                         isForm = t.IsSubclassOf (TypeManager.LookupType("System.Windows.Forms.Form"));
734                         }
735                         return (hasSWF && isForm);
736                 }
737                 
738                 string GetFQMainClass()
739                 {       
740                         if (RootContext.RootNamespace != "")
741                                 return RootContext.RootNamespace + "." + RootContext.MainClass;
742                         else
743                                 return RootContext.MainClass;                   
744                 }
745                 
746                 void FixEntryPoint()
747                 {
748                         if (target == Target.Exe || target == Target.WinExe)
749                         {
750                                 MethodInfo ep = RootContext.EntryPoint;
751                         
752                                 if (ep == null)
753                                 {
754                                         // If we don't have a valid entry point yet
755                                         // AND if System.Windows.Forms is included
756                                         // among the dependencies, we have to build
757                                         // a new entry point on-the-fly. Otherwise we
758                                         // won't be able to compile SWF code out of the box.
759
760                                         if (IsSWFApp()) 
761                                         {                                                                                               
762                                                 Type t = TypeManager.LookupType(GetFQMainClass());
763                                                 if (t != null) 
764                                                 {                                                       
765                                                         TypeBuilder tb = t as TypeBuilder;
766                                                         MethodBuilder mb = tb.DefineMethod ("Main", MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard, 
767                                                                 typeof(void), new Type[0]);
768
769                                                         Type SWFA = TypeManager.LookupType("System.Windows.Forms.Application");
770                                                         Type SWFF = TypeManager.LookupType("System.Windows.Forms.Form");
771                                                         Type[] args = new Type[1];
772                                                         args[0] = SWFF;
773                                                         MethodInfo mi = SWFA.GetMethod("Run", args);
774                                                         ILGenerator ig = mb.GetILGenerator();
775                                                         ConstructorInfo ci = TypeManager.GetConstructor (TypeManager.LookupType(t.FullName), new Type[0]);
776                                                         
777                                                         ig.Emit (OpCodes.Newobj, ci);
778                                                         ig.Emit (OpCodes.Call, mi);
779                                                         ig.Emit (OpCodes.Ret);
780
781                                                         RootContext.EntryPoint = mb as MethodInfo;
782                                                 }
783                                         }
784                                 }
785                         }
786                 }
787
788                 bool GenerateAssembly()
789                 {
790                         //
791                         // The code generator
792                         //
793                         if (timestamps)
794                                 ShowTime ("Emitting code");
795                         
796                         
797
798                         RootContext.EmitCode();
799                         FixEntryPoint();
800                         if (Report.Errors > 0)
801                                 return false;
802
803                         if (timestamps)
804                                 ShowTime ("   done");
805
806
807                         if (timestamps)
808                                 ShowTime ("Closing types");
809
810                         RootContext.CloseTypes ();
811                         if (Report.Errors > 0)
812                                 return false;
813
814                         if (timestamps)
815                                 ShowTime ("   done");
816
817                         PEFileKinds k = PEFileKinds.ConsoleApplication;
818                                                         
819                         if (target == Target.Library || target == Target.Module)
820                                 k = PEFileKinds.Dll;
821                         else if (target == Target.Exe)
822                                 k = PEFileKinds.ConsoleApplication;
823                         else if (target == Target.WinExe)
824                                 k = PEFileKinds.WindowApplication;
825                         
826                         if (target == Target.Exe || target == Target.WinExe)
827                         {
828                                 MethodInfo ep = RootContext.EntryPoint;
829                         
830                                 if (ep == null)
831                                 {
832                                         Report.Error (5001, "Program " + outputFileName +
833                                                 " does not have an entry point defined");
834                                         return false;
835                                 }
836                                                         
837                                 CodeGen.AssemblyBuilder.SetEntryPoint (ep, k);
838                         }
839
840                         // Add the resources
841                         if (EmbeddedResources != null)
842                                 foreach (string file in EmbeddedResources)
843                                         CodeGen.AssemblyBuilder.AddResourceFile (file, file);
844                         
845                         CodeGen.Save(outputFileName);
846
847                         if (timestamps)
848                                 ShowTime ("Saved output");
849
850                         
851                         if (want_debugging_support) 
852                         {
853                                 CodeGen.SaveSymbols ();
854                                 if (timestamps)
855                                         ShowTime ("Saved symbols");
856                         }
857
858                         return true;
859                 }
860
861                 public void CompileAll()
862                 {
863 /* 
864                     VB.NET expects the default namespace to be "" (empty string)                
865                     
866                     if (RootContext.RootNamespace == "")
867                     {
868                       RootContext.RootNamespace = System.IO.Path.GetFileNameWithoutExtension(outputFileName);
869                     }
870 */
871                         if (!ParseAll()) // Phase 1
872                                 return;
873
874                         if (!ResolveAllTypes()) // Phase 2
875                                 return;
876
877                         if (!GenerateAssembly()) // Phase 3 
878                                 return;
879
880                         if (Report.ExpectedError != 0)
881                                 Error("Failed to report expected Error " + Report.ExpectedError);
882                 }
883
884         }
885 }