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