**** Merged from MCS ****
[mono-project.git] / mcs / mbas / driver.cs
blob9dbbdf69a3d8aeba247d2f9f55937993054df43a
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
12 namespace Mono.Languages
14 using System;
15 using System.Collections;
16 using System.Diagnostics;
17 using System.IO;
18 using System.Globalization;
19 using System.Reflection;
20 using System.Reflection.Emit;
22 using Mono.MonoBASIC;
23 using Mono.GetOptions;
25 enum Target
27 Library, Exe, Module, WinExe
30 enum OptionCompare
32 Binary, Text
35 /// <summary>
36 /// The compiler driver.
37 /// </summary>
38 public class Driver : Options
40 // Temporary options
41 //------------------------------------------------------------------
42 [Option("[Mono] Only parses the source file (for debugging the tokenizer)", "parse")]
43 public bool parse_only = false;
45 [Option("[Mono] Only tokenizes source files")]
46 public bool tokenize = false;
48 [Option("[Mono] Shows stack trace at Error location")]
49 public bool stacktrace { set { Report.Stacktrace = value; } }
51 [Option("[Mono] Displays time stamps of various compiler events")]
52 public bool timestamp
54 set
56 timestamps = true;
57 last_time = DateTime.Now;
58 debug_arglist.Add("timestamp");
62 // Mono-specific options
63 //------------------------------------------------------------------
64 [Option("About the MonoBASIC compiler", "about")]
65 public override WhatToDoNext DoAbout()
67 return base.DoAbout();
70 [Option(-1, "[Mono] References packages listed. {packagelist}=package,...", "pkg")]
71 public WhatToDoNext ReferenceSomePackage(string packageName)
73 return ReferencePackage(packageName)?WhatToDoNext.GoAhead:WhatToDoNext.AbandonProgram;
76 [Option("[Mono] Don\'t assume the standard library", "nostdlib")]
77 public bool NoStandardLibraries { set { RootContext.StdLib = !value; } }
79 [Option("[Mono] Disables implicit references to assemblies", "noconfig")]
80 public bool NoConfig { set { load_default_config = !value; } }
82 [Option("[Mono] Allows unsafe code", "unsafe")]
83 public bool AllowUnsafeCode { set { RootContext.Unsafe = value; } }
85 [Option("[Mono] Debugger {arguments}", "debug-args")]
86 public WhatToDoNext SetDebugArgs(string args)
88 debug_arglist.AddRange (args.Split(','));
89 return WhatToDoNext.GoAhead;
92 [Option("[Mono] Ignores warning number {XXXX}", "ignorewarn")]
93 public WhatToDoNext SetIgnoreWarning(int warn)
95 Report.SetIgnoreWarning(warn);
96 return WhatToDoNext.GoAhead;
99 [Option("[Mono] Sets warning {level} (the highest is 4, the default)", "wlevel")]
100 public int WarningLevel { set { RootContext.WarningLevel = value; } }
102 [Option("[Mono] Makes errors fatal", "fatal")]
103 public bool Fatal { set { Report.Fatal = value; } }
105 // Output file options
106 //------------------------------------------------------------------
107 [Option("Specifies the output {file} name", 'o', "out")]
108 public string OutputFileName = null;
110 [Option("Specifies the target {type} for the output file (exe [default], winexe, library, module)", 't', "target")]
111 public WhatToDoNext SetTarget(string type)
113 switch (type.ToLower())
115 case "library":
116 target = Target.Library;
117 target_ext = ".dll";
118 break;
120 case "exe":
121 target = Target.Exe;
122 break;
124 case "winexe":
125 target = Target.WinExe;
126 break;
128 case "module":
129 target = Target.Module;
130 target_ext = ".netmodule";
131 break;
133 return WhatToDoNext.GoAhead;
136 // input file options
137 //------------------------------------------------------------------
138 public ArrayList AddedModules = new ArrayList();
140 [Option(-1, "References metadata from specified {module}", "addmodule")]
141 public string AddedModule { set { AddedModules.Add(value); } }
143 // [Option("[NOT IMPLEMENTED YET]Include all files in the current directory and subdirectories according to the {wildcard}", "recurse")]
144 public WhatToDoNext Recurse(string wildcard)
146 //AddFiles (DirName, true); // TODO wrong semantics
147 return WhatToDoNext.GoAhead;
150 [Option(-1, "References metadata from the specified {assembly}", 'r', "reference")]
151 public string AddedReference { set { references.Add(value); } }
153 // support for the Compact Framework
154 //------------------------------------------------------------------
155 // [Option("[NOT IMPLEMENTED YET]Sets the compiler to target the Compact Framework","netcf")]
156 public bool CompileForCompactFramework = false;
158 // [Option("[NOT IMPLEMENTED YET]Specifies the {path} to the location of mscorlib.dll and microsoft.visualbasic.dll", "sdkpath")]
159 public string SDKPath = null;
161 // resource options
162 //------------------------------------------------------------------
163 public ArrayList EmbeddedResources = new ArrayList();
165 [Option(-1, "Adds the specified {file} as an embedded assembly resource", "resource", "res")]
166 public string AddedResource { set { EmbeddedResources.Add(value); } }
168 public ArrayList LinkedResources = new ArrayList();
170 // [Option(-1, "[NOT IMPLEMENTED YET]Adds the specified {file} as a linked assembly resource", "linkresource", "linkres")]
171 public string AddedLinkresource { set { LinkedResources.Add(value); } }
173 public ArrayList Win32Resources = new ArrayList();
175 // [Option(-1, "[NOT IMPLEMENTED YET]Specifies a Win32 resource {file} (.res)", "win32resource")]
176 public string AddedWin32resource { set { Win32Resources.Add(value); } }
178 public ArrayList Win32Icons = new ArrayList();
180 // [Option(-1, "[NOT IMPLEMENTED YET]Specifies a Win32 icon {file} (.ico) for the default Win32 resources", "win32icon")]
181 public string AddedWin32icon { set { Win32Icons.Add(value); } }
183 // code generation options
184 //------------------------------------------------------------------
185 // [Option("[NOT IMPLEMENTED YET]Enable optimizations", "optimize")]
186 public bool optimize = false;
188 // TODO: handle VB.NET [+|-] boolean syntax
189 [Option("Remove integer checks. Default off.")]
190 public bool removeintchecks { set { RootContext.Checked = !value; } }
192 // TODO: handle VB.NET [+|-] boolean syntax
193 [Option("Emit debugging information", 'g', "debug")]
194 public bool want_debugging_support = false;
196 [Option("Emit full debugging information (default)", "debug:full")]
197 public bool fullDebugging = false;
199 [Option("[IGNORED]Emit PDB file only", "debug:pdbonly")]
200 public bool pdbOnly = false;
202 // errors and warnings options
203 //------------------------------------------------------------------
204 [Option("Treat warnings as errors", "warnaserror")]
205 public bool WarningsAreErrors { set { Report.WarningsAreErrors = value; } }
207 [Option("Disable warnings", "nowarn")]
208 public bool NoWarnings { set { if (value) RootContext.WarningLevel = 0; } }
211 // language options
212 //------------------------------------------------------------------
213 public Hashtable Defines = new Hashtable();
215 [Option(-1, "Declares global conditional compilation symbol(s). {symbol-list}:name=value,...", 'd', "define")]
216 public string define {
217 set
219 foreach(string item in value.Split(','))
221 string[] dados = item.Split('=');
224 if (dados.Length > 1)
225 Defines.Add(dados[0], dados[1]);
226 else
227 Defines.Add(dados[0], string.Empty);
229 catch
231 Error ("Could not define symbol" + dados[0]);
237 [Option("Declare global Imports for namespaces in referenced metadata files. {import-list}:namespace,...", "imports")]
238 public WhatToDoNext imports(string importslist)
240 Mono.MonoBASIC.Parser.ImportsList.AddRange(importslist.Split(','));
241 return WhatToDoNext.GoAhead;
244 // TODO: handle VB.NET [+|-] boolean syntax
245 // [Option("[NOT IMPLEMENTED YET]Require explicit declaration of variables")]
246 public bool optionexplicit { set { Mono.MonoBASIC.Parser.InitialOptionExplicit = value; } }
248 // TODO: handle VB.NET [+|-] boolean syntax
249 // [Option("[NOT IMPLEMENTED YET]Enforce strict language semantics")]
250 public bool optionstrict { set { Mono.MonoBASIC.Parser.InitialOptionStrict = value; } }
252 // [Option("[NOT IMPLEMENTED YET]Specifies binary-style string comparisons. This is the default", "optioncompare:binary")]
253 public bool optioncomparebinary { set { Mono.MonoBASIC.Parser.InitialOptionCompareBinary = true; } }
255 // [Option("[NOT IMPLEMENTED YET]Specifies text-style string comparisons.", "optioncompare:text")]
256 public bool optioncomparetext { set { Mono.MonoBASIC.Parser.InitialOptionCompareBinary = false; } }
258 [Option("Specifies de root {namespace} for all type declarations")]
259 public string rootnamespace { set { RootContext.RootNamespace = value; } }
261 // Miscellaneous options
262 //------------------------------------------------------------------
264 [Option("[IGNORED]Do not display compiler copyright banner")]
265 public bool nologo = false;
267 // [Option("[NOT IMPLEMENTED YET]Quiet output mode")]
268 public bool quiet = false;
270 // TODO: semantics are different and should be adjusted
271 [Option("Display verbose messages", 'v')]
272 public bool verbose { set { GenericParser.yacc_verbose_flag = value; } }
274 // Advanced options
275 //------------------------------------------------------------------
276 // TODO: force option to accept number in hex format
277 // [Option("[NOT IMPLEMENTED YET]The base {address} for a library or module (hex)")]
278 public int baseaddress;
280 // [Option("[NOT IMPLEMENTED YET]Create bug report {file}")]
281 public string bugreport;
283 // TODO: handle VB.NET [+|-] boolean syntax
284 // [Option("[NOT IMPLEMENTED YET]Delay-sign the assembly using only the public portion of the strong name key")]
285 public bool delaysign;
287 // [Option("[NOT IMPLEMENTED YET]Specifies a strong name key {container}")]
288 public string keycontainer;
290 // [Option("[NOT IMPLEMENTED YET]Specifies a strong name key {file}")]
291 public string keyfile;
293 public string[] libpath = null;
295 [Option("List of directories to search for metadata references {path-list}:path;...", "libpath")]
296 public WhatToDoNext setlibpath(string pathlist)
298 libpath = pathlist.Split(';');
299 return WhatToDoNext.GoAhead;
302 [Option(@"Specifies the Class or Module that contains Sub Main.
303 It can also be a {class} that inherits from System.Windows.Forms.Form.",
304 'm', "main")]
305 public string main { set { RootContext.MainClass = value; } }
307 // TODO: handle VB.NET [+|-] boolean syntax
308 [Option("[IGNORED]Emit compiler output in UTF8 character encoding")]
309 public bool utf8output;
311 ArrayList defines = new ArrayList();
312 ArrayList references = new ArrayList();
313 ArrayList soft_references = new ArrayList();
315 string first_source = null;
316 Target target = Target.Exe;
317 string target_ext = ".exe";
318 ArrayList debug_arglist = new ArrayList ();
319 bool timestamps = false;
320 Hashtable source_files = new Hashtable ();
321 bool load_default_config = true;
324 // Last time we took the time
326 DateTime last_time;
327 void ShowTime (string msg)
329 DateTime now = DateTime.Now;
330 TimeSpan span = now - last_time;
331 last_time = now;
333 Console.WriteLine (
334 "[{0:00}:{1:000}] {2}",
335 (int) span.TotalSeconds, span.Milliseconds, msg);
338 public int LoadAssembly (string assembly, bool soft)
340 Assembly a;
341 string total_log = "";
343 try
345 char[] path_chars = { '/', '\\' };
347 if (assembly.IndexOfAny (path_chars) != -1)
348 a = Assembly.LoadFrom(assembly);
349 else {
350 string ass = assembly;
351 if (ass.EndsWith (".dll"))
352 ass = assembly.Substring (0, assembly.Length - 4);
353 a = Assembly.Load (ass);
355 TypeManager.AddAssembly (a);
356 return 0;
358 catch (FileNotFoundException)
360 if (libpath != null)
362 foreach (string dir in libpath)
364 string full_path = dir + "/" + assembly + ".dll";
366 try
368 a = Assembly.LoadFrom (full_path);
369 TypeManager.AddAssembly (a);
370 return 0;
372 catch (FileNotFoundException ff)
374 total_log += ff.FusionLog;
375 continue;
379 if (soft)
380 return 0;
382 catch (BadImageFormatException f)
384 Error ("// Bad file format while loading assembly");
385 Error ("Log: " + f.FusionLog);
386 return 1;
387 } catch (FileLoadException f){
388 Error ("File Load Exception: " + assembly);
389 Error ("Log: " + f.FusionLog);
390 return 1;
391 } catch (ArgumentNullException){
392 Error ("// Argument Null exception ");
393 return 1;
396 Report.Error (6, "Can not find assembly `" + assembly + "'" );
397 Console.WriteLine ("Log: \n" + total_log);
399 return 0;
402 public bool ReferencePackage(string packageName)
404 if (packageName == ""){
405 DoAbout ();
406 return false;
409 ProcessStartInfo pi = new ProcessStartInfo ();
410 pi.FileName = "pkg-config";
411 pi.RedirectStandardOutput = true;
412 pi.UseShellExecute = false;
413 pi.Arguments = "--libs " + packageName;
414 Process p = null;
415 try {
416 p = Process.Start (pi);
417 } catch (Exception e) {
418 Report.Error (-27, "Couldn't run pkg-config: " + e.Message);
419 return false;
422 if (p.StandardOutput == null){
423 Report.Warning (-27, "Specified package did not return any information");
425 string pkgout = p.StandardOutput.ReadToEnd ();
426 p.WaitForExit ();
427 if (p.ExitCode != 0) {
428 Report.Error (-27, "Error running pkg-config. Check the above output.");
429 return false;
431 p.Close ();
433 if (pkgout != null) {
434 string [] xargs = pkgout.Trim (new Char [] {' ', '\n', '\r', '\t'}).
435 Split (new Char [] { ' ', '\t'});
436 foreach(string arg in xargs) {
437 string[] zargs = arg.Split(':', '=');
438 try {
439 if (zargs.Length > 1)
440 AddedReference = zargs[1];
441 else
442 AddedReference = arg;
443 } catch (Exception e) {
444 Report.Error (-27, "Something wrong with argument (" + arg + ") in 'pkg-config --libs' output: " + e.Message);
445 return false;
450 return true;
453 public void LoadModule (MethodInfo adder_method, string module)
455 System.Reflection.Module m;
456 string total_log = "";
458 try {
459 try {
460 m = (System.Reflection.Module)adder_method.Invoke (CodeGen.AssemblyBuilder, new object [] { module });
462 catch (TargetInvocationException ex) {
463 throw ex.InnerException;
465 TypeManager.AddModule (m);
468 catch (FileNotFoundException) {
469 foreach (string dir in libpath) {
470 string full_path = Path.Combine (dir, module);
471 if (!module.EndsWith (".netmodule"))
472 full_path += ".netmodule";
474 try {
475 try {
476 m = (System.Reflection.Module) adder_method.Invoke (CodeGen.AssemblyBuilder, new object [] { full_path });
478 catch (TargetInvocationException ex) {
479 throw ex.InnerException;
481 TypeManager.AddModule (m);
482 return;
484 catch (FileNotFoundException ff) {
485 total_log += ff.FusionLog;
486 continue;
489 Report.Error (6, "Cannot find module `" + module + "'" );
490 Console.WriteLine ("Log: \n" + total_log);
492 catch (BadImageFormatException f) {
493 Report.Error(6, "Cannot load module (bad file format)" + f.FusionLog);
495 catch (FileLoadException f) {
496 Report.Error(6, "Cannot load module " + f.FusionLog);
498 catch (ArgumentNullException) {
499 Report.Error(6, "Cannot load module (null argument)");
503 void Error(string message)
505 Console.WriteLine(message);
508 /// <summary>
509 /// Loads all assemblies referenced on the command line
510 /// </summary>
511 public int LoadReferences ()
513 int errors = 0;
515 foreach (string r in references)
516 errors += LoadAssembly (r, false);
518 foreach (string r in soft_references)
519 errors += LoadAssembly (r, true);
521 return errors;
524 void SetupDefaultDefines ()
526 defines = new ArrayList ();
527 defines.Add ("__MonoBASIC__");
530 void SetupDefaultImports()
532 Mono.MonoBASIC.Parser.ImportsList = new ArrayList();
533 Mono.MonoBASIC.Parser.ImportsList.Add("Microsoft.VisualBasic");
537 // Given a path specification, splits the path from the file/pattern
539 void SplitPathAndPattern (string spec, out string path, out string pattern)
541 int p = spec.LastIndexOf ("/");
542 if (p != -1){
544 // Windows does not like /file.cs, switch that to:
545 // "\", "file.cs"
547 if (p == 0){
548 path = "\\";
549 pattern = spec.Substring (1);
550 } else {
551 path = spec.Substring (0, p);
552 pattern = spec.Substring (p + 1);
554 return;
557 p = spec.LastIndexOf ("\\");
558 if (p != -1){
559 path = spec.Substring (0, p);
560 pattern = spec.Substring (p + 1);
561 return;
564 path = ".";
565 pattern = spec;
568 bool AddFiles (string spec, bool recurse)
570 string path, pattern;
572 SplitPathAndPattern(spec, out path, out pattern);
573 if (pattern.IndexOf("*") == -1)
575 AddFile(spec);
576 return true;
579 string [] files = null;
580 try {
581 files = Directory.GetFiles(path, pattern);
582 } catch (System.IO.DirectoryNotFoundException) {
583 Report.Error (2001, "Source file `" + spec + "' could not be found");
584 return false;
585 } catch (System.IO.IOException){
586 Report.Error (2001, "Source file `" + spec + "' could not be found");
587 return false;
589 foreach (string f in files)
590 AddFile (f);
592 if (!recurse)
593 return true;
595 string [] dirs = null;
597 try {
598 dirs = Directory.GetDirectories(path);
599 } catch {
602 foreach (string d in dirs) {
604 // Don't include path in this string, as each
605 // directory entry already does
606 AddFiles (d + "/" + pattern, true);
609 return true;
612 void DefineDefaultConfig ()
615 // For now the "default config" is harcoded into the compiler
616 // we can move this outside later
618 string [] default_config =
620 "System",
621 "System.Data",
622 "System.Xml",
623 "Microsoft.VisualBasic" ,
624 #if EXTRA_DEFAULT_REFS
626 // Is it worth pre-loading all this stuff?
628 "Accessibility",
629 "System.Configuration.Install",
630 "System.Design",
631 "System.DirectoryServices",
632 "System.Drawing.Design",
633 "System.Drawing",
634 "System.EnterpriseServices",
635 "System.Management",
636 "System.Messaging",
637 "System.Runtime.Remoting",
638 "System.Runtime.Serialization.Formatters.Soap",
639 "System.Security",
640 "System.ServiceProcess",
641 "System.Web",
642 "System.Web.RegularExpressions",
643 "System.Web.Services" ,
644 "System.Windows.Forms"
645 #endif
648 foreach (string def in default_config)
649 if (!(references.Contains(def) || references.Contains (def + ".dll")))
650 soft_references.Add(def);
653 [ArgumentProcessor]
654 public void AddFile(string fileName)
656 string f = fileName;
657 if (first_source == null)
658 first_source = f;
660 if (source_files.Contains(f))
661 Report.Error(1516, "Source file '" + f + "' specified multiple times");
662 else
663 source_files.Add(f, f);
666 void ProcessSourceFile(string filename)
668 if (tokenize)
669 GenericParser.Tokenize(filename);
670 else
671 GenericParser.Parse(filename);
674 string outputFile_Name = null;
676 string outputFileName
678 get
680 if (outputFile_Name == null)
682 if (OutputFileName == null)
684 int pos = first_source.LastIndexOf(".");
686 if (pos > 0)
687 OutputFileName = first_source.Substring(0, pos);
688 else
689 OutputFileName = first_source;
691 string bname = CodeGen.Basename(OutputFileName);
692 if (bname.IndexOf(".") == -1)
693 OutputFileName += target_ext;
694 outputFile_Name = OutputFileName;
696 return outputFile_Name;
700 bool ParseAll() // Phase 1
702 if (first_source == null) {
703 Report.Error(2008, "No files to compile were specified");
704 return false;
707 foreach(string filename in source_files.Values)
708 ProcessSourceFile(filename);
710 if (tokenize || parse_only || (Report.Errors > 0))
711 return false;
713 return true; // everything went well go ahead
716 void InitializeDebuggingSupport()
718 string[] debug_args = new string [debug_arglist.Count];
719 debug_arglist.CopyTo(debug_args);
720 CodeGen.Init(outputFileName, outputFileName, want_debugging_support, debug_args);
721 TypeManager.AddModule(CodeGen.ModuleBuilder);
724 public bool ResolveAllTypes() // Phase 2
726 // Load Core Library for default compilation
727 if (RootContext.StdLib)
728 references.Insert(0, "mscorlib");
730 if (load_default_config)
731 DefineDefaultConfig();
733 if (timestamps)
734 ShowTime("Loading references");
736 // Load assemblies required
737 if (LoadReferences() > 0)
739 Error ("Could not load one or more assemblies");
740 return false;
743 if (timestamps)
744 ShowTime("References loaded");
746 InitializeDebuggingSupport();
748 // target is Module
749 if (target == Target.Module) {
750 PropertyInfo module_only = typeof (AssemblyBuilder).GetProperty ("IsModuleOnly", BindingFlags.Instance|BindingFlags.Public|BindingFlags.NonPublic);
751 if (module_only == null) {
752 Report.Error (0, new Location (-1, -1), "Cannot use /target:module on this runtime: try the Mono runtime instead.");
753 Environment.Exit (1);
756 MethodInfo set_method = module_only.GetSetMethod (true);
757 set_method.Invoke (CodeGen.AssemblyBuilder, BindingFlags.Default, null, new object[]{true}, null);
759 TypeManager.AddModule (CodeGen.ModuleBuilder);
762 if (AddedModules.Count > 0) {
763 MethodInfo adder_method = typeof (AssemblyBuilder).GetMethod ("AddModule", BindingFlags.Instance|BindingFlags.NonPublic);
764 if (adder_method == null) {
765 Report.Error (0, new Location (-1, -1), "Cannot use /addmodule on this runtime: Try the Mono runtime instead.");
766 Environment.Exit (1);
769 foreach (string module in AddedModules)
770 LoadModule (adder_method, module);
775 // Before emitting, we need to get the core
776 // types emitted from the user defined types
777 // or from the system ones.
779 if (timestamps)
780 ShowTime ("Initializing Core Types");
782 if (!RootContext.StdLib)
783 RootContext.ResolveCore ();
784 if (Report.Errors > 0)
785 return false;
787 TypeManager.InitCoreTypes();
788 if (Report.Errors > 0)
789 return false;
791 if (timestamps)
792 ShowTime (" Core Types done");
794 if (timestamps)
795 ShowTime ("Resolving tree");
797 // The second pass of the compiler
798 RootContext.ResolveTree ();
799 if (Report.Errors > 0)
800 return false;
802 if (timestamps)
803 ShowTime ("Populate tree");
805 if (!RootContext.StdLib)
806 RootContext.BootCorlib_PopulateCoreTypes();
807 if (Report.Errors > 0)
808 return false;
810 RootContext.PopulateTypes();
811 if (Report.Errors > 0)
812 return false;
814 TypeManager.InitCodeHelpers();
815 if (Report.Errors > 0)
816 return false;
818 return true;
821 bool IsSWFApp()
823 string mainclass = GetFQMainClass();
825 if (mainclass != null) {
826 foreach (string r in references) {
827 if (r.IndexOf ("System.Windows.Forms") >= 0) {
828 Type t = TypeManager.LookupType(mainclass);
829 if (t != null)
830 return t.IsSubclassOf (TypeManager.LookupType("System.Windows.Forms.Form"));
831 break;
835 return false;
838 string GetFQMainClass()
840 if (RootContext.RootNamespace != "")
841 return RootContext.RootNamespace + "." + RootContext.MainClass;
842 else
843 return RootContext.MainClass;
846 void FixEntryPoint()
848 if (target == Target.Exe || target == Target.WinExe)
850 MethodInfo ep = RootContext.EntryPoint;
852 if (ep == null)
854 // If we don't have a valid entry point yet
855 // AND if System.Windows.Forms is included
856 // among the dependencies, we have to build
857 // a new entry point on-the-fly. Otherwise we
858 // won't be able to compile SWF code out of the box.
860 if (IsSWFApp())
862 Type t = TypeManager.LookupType(GetFQMainClass());
863 if (t != null)
865 TypeBuilder tb = t as TypeBuilder;
866 MethodBuilder mb = tb.DefineMethod ("Main", MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard,
867 typeof(void), new Type[0]);
869 Type SWFA = TypeManager.LookupType("System.Windows.Forms.Application");
870 Type SWFF = TypeManager.LookupType("System.Windows.Forms.Form");
871 Type[] args = new Type[1];
872 args[0] = SWFF;
873 MethodInfo mi = SWFA.GetMethod("Run", args);
874 ILGenerator ig = mb.GetILGenerator();
875 ConstructorInfo ci = TypeManager.GetConstructor (TypeManager.LookupType(t.FullName), new Type[0]);
877 ig.Emit (OpCodes.Newobj, ci);
878 ig.Emit (OpCodes.Call, mi);
879 ig.Emit (OpCodes.Ret);
881 RootContext.EntryPoint = mb as MethodInfo;
888 bool GenerateAssembly()
891 // The code generator
893 if (timestamps)
894 ShowTime ("Emitting code");
898 RootContext.EmitCode();
899 FixEntryPoint();
900 if (Report.Errors > 0)
901 return false;
903 if (timestamps)
904 ShowTime (" done");
907 if (timestamps)
908 ShowTime ("Closing types");
910 RootContext.CloseTypes ();
911 if (Report.Errors > 0)
912 return false;
914 if (timestamps)
915 ShowTime (" done");
917 PEFileKinds k = PEFileKinds.ConsoleApplication;
919 if (target == Target.Library || target == Target.Module)
920 k = PEFileKinds.Dll;
921 else if (target == Target.Exe)
922 k = PEFileKinds.ConsoleApplication;
923 else if (target == Target.WinExe)
924 k = PEFileKinds.WindowApplication;
926 if (target == Target.Exe || target == Target.WinExe)
928 MethodInfo ep = RootContext.EntryPoint;
930 if (ep == null)
932 Report.Error (30737, "Program " + outputFileName +
933 " does not have an entry point defined");
934 return false;
937 CodeGen.AssemblyBuilder.SetEntryPoint (ep, k);
940 // Add the resources
941 if (EmbeddedResources != null)
942 foreach (string file in EmbeddedResources)
943 CodeGen.AssemblyBuilder.AddResourceFile (file, file);
945 CodeGen.Save(outputFileName);
947 if (timestamps)
948 ShowTime ("Saved output");
951 if (want_debugging_support)
953 CodeGen.SaveSymbols ();
954 if (timestamps)
955 ShowTime ("Saved symbols");
958 return true;
961 public void CompileAll()
964 VB.NET expects the default namespace to be "" (empty string)
966 if (RootContext.RootNamespace == "")
968 RootContext.RootNamespace = System.IO.Path.GetFileNameWithoutExtension(outputFileName);
971 if (!ParseAll()) // Phase 1
972 return;
974 if (!ResolveAllTypes()) // Phase 2
975 return;
977 GenerateAssembly(); // Phase 3
980 /// <summary>
981 /// Parses the arguments, and calls the compilation process.
982 /// </summary>
983 int MainDriver(string [] args)
985 Console.WriteLine ("--------");
986 Console.WriteLine ("MonoBASIC: THIS IS AN ALPHA SOFTWARE.");
987 Console.WriteLine ("--------");
988 SetupDefaultDefines();
990 SetupDefaultImports();
992 // Some defaults
993 RootContext.Checked = true;
995 ProcessArgs(args);
997 if (first_source == null)
999 if (!quiet)
1000 DoHelp();
1001 return 2;
1004 CompileAll();
1006 return Report.ProcessResults(quiet);
1009 public static int Main (string[] args)
1011 Driver Exec = new Driver();
1013 Report.Stacktrace = false;
1015 return Exec.MainDriver(args);