Start
[mono.git] / mcs / mbas / driver.cs
index 2966d2f3a132081e7091093be185ecfba436f6d1..dd4c27c76ff859421ebed9296a166406d1635b4b 100644 (file)
@@ -1,4 +1,4 @@
-//
+//
 // driver.cs: The compiler command line driver.
 //
 // Author: Rafael Teixeira (rafaelteixeirabr@hotmail.com)
@@ -17,7 +17,7 @@ namespace Mono.Languages
        using System.Collections;
        using System.IO;
        using System.Globalization;
-       using Mono.CSharp;
+       using Mono.MonoBASIC;
        using Mono.GetOptions;
 
        enum Target 
@@ -25,97 +25,88 @@ namespace Mono.Languages
                Library, Exe, Module, WinExe
        };
        
+       enum OptionCompare
+       {
+               Binary, Text
+       };
+       
        /// <summary>
        ///    The compiler driver.
        /// </summary>
        public class Driver : Options
        {
-               
-               [Option("Verbose parsing (for debugging the parser)",'v')] 
-               public bool verbose     { set { GenericParser.yacc_verbose_flag = value; } }
+               // Temporary options
+               //------------------------------------------------------------------
+               [Option("[Mono] Only parses the source file (for debugging the tokenizer)", "parse")]
+               public bool parse_only = false;
 
-               [Option("Specifies PARAM as main (starting) class", 'm')]
-               public string main { set { RootContext.MainClass = value; } }
+               [Option("[Mono] Only tokenizes source files")]
+               public bool tokenize = false;
 
+               [Option("[Mono] Shows stack trace at Error location")]
+               public bool stacktrace { set { Report.Stacktrace = value; } }
+
+               [Option("[Mono] Displays time stamps of various compiler events")]
+               public bool timestamp
+               {
+                       set
+                       {
+                               timestamps = true;
+                               last_time = DateTime.Now;
+                               debug_arglist.Add("timestamp");
+                       }
+               }
+
+               // Mono-specific options
+               //------------------------------------------------------------------
                [Option("About the MonoBASIC compiler", "about")]
                public override WhatToDoNext DoAbout()
                {
                        return base.DoAbout();
                }
 
-               [Option("Adds PARAM to the assembly link path", 'L')]
-               public string[] LinkPaths = null;
-
-               [Option("Defines the symbol PARAM", "define")]
-               public string[] Defines = null;
+               [Option("[Mono] Don\'t assume the standard library", "nostdlib")]
+               public bool NoStandardLibraries { set { RootContext.StdLib = !value; } }
 
-               [Option("Only parses the source file (for debugging the tokenizer)", "parse")]
-               public bool parse_only = false;
-
-
-               [Option("Disables implicit references to assemblies", "noconfig")]
+               [Option("[Mono] Disables implicit references to assemblies", "noconfig")]
                public bool NoConfig { set { load_default_config = !value; } }
 
-               [Option("Allows unsafe code", "unsafe")]
+               [Option("[Mono] Allows unsafe code", "unsafe")]
                public bool AllowUnsafeCode { set { RootContext.Unsafe = value; } }
 
-               [Option("Specifies output file", 'o', "output")]
-               public string output_file = null;
-
-               [Option("Only tokenizes source files", "tokenize")]
-               public bool tokenize = false;
-
-               [Option("Set default context to checked", "checked")]
+               [Option("[Mono] Set default context to checked", "checked")]
                public bool Checked { set { RootContext.Checked = value; } }
 
-               [Option("Shows stack trace at Error location", "Stacktrace")]
-               public bool Stacktrace { set { Report.Stacktrace = value; } }
-
-               [Option("References an assembly", 'r')]
-               public string reference { set { references.Add(value); } }
-
-               [Option("Adds PARAM as a resource", "resource")]
-               public string[] resources;
-
-               [Option("Set default context to checked", "nostdlib")]
-               public bool nostdlib { set { RootContext.StdLib = !value; } }
-
-               [Option("Makes errors fatal", "fatal")]
-               public bool Fatal { set { Report.Fatal = value; } }
-
-               [Option("Treat warnings as errors", "werror")]
-               public bool WarningsAreErrors { set { Report.WarningsAreErrors = value; } }
-
-               [Option("Ignores warning number PARAM", "nowarn")]
-               public WhatToDoNext SetIgnoreWarning(int warn)
+               [Option("[Mono] Debugger {arguments}", "debug-args")]
+               public WhatToDoNext SetDebugArgs(string args)
                {
-                       Report.SetIgnoreWarning(warn);
+                       char[] sep = { ',' };
+                       debug_arglist.AddRange (args.Split (sep));
                        return WhatToDoNext.GoAhead;
                }
 
-               [Option("Recursively compiles the files in PARAM ([dir]/file)", "recurse")]
-               public WhatToDoNext recurse(string DirName)
+               [Option("[Mono] Ignores warning number {XXXX}", "ignorewarn")]
+               public WhatToDoNext SetIgnoreWarning(int warn)
                {
-                       AddFiles (DirName, true);
+                       Report.SetIgnoreWarning(warn);
                        return WhatToDoNext.GoAhead;
-               }
-       
+               }       
 
-               [Option("Write symbolic debugging information to FILE-debug.s", 'g', "debug")]
-               public bool want_debugging_support = false;
+               [Option("[Mono] Sets warning {level} (the highest is 4, the default)", "wlevel")]
+               public int WarningLevel { set { RootContext.WarningLevel = value; } }
 
-               [Option("Debugger arguments", "debug-args")]
-               public WhatToDoNext SetDebugArgs(string args)
-               {
-                       char[] sep = { ',' };
-                       debug_arglist.AddRange (args.Split (sep));
-                       return WhatToDoNext.GoAhead;
-               }
+               [Option("[Mono] Makes errors fatal", "fatal")]
+               public bool Fatal { set { Report.Fatal = value; } }
+
+               // Output file options
+               //------------------------------------------------------------------
+               [Option("Specifies the output {file} name", 'o', "out")]
+               public string OutputFileName = null;
 
-               [Option("Specifies the target (PARAM is one of: exe, winexe, library, module)", "target")]
+               [Option("Specifies the target {type} for the output file (exe [default], winexe, library, module)", "target")]
                public WhatToDoNext SetTarget(string type)
                {
-                       switch (type)
+                       switch (type.ToLower())
                        {
                                case "library":
                                        target = Target.Library;
@@ -138,26 +129,186 @@ namespace Mono.Languages
                        return WhatToDoNext.GoAhead;
                }
 
-               [Option("Sets warning level (the highest is 4, the default)", "wlevel")]
-               public int wlevel { set { RootContext.WarningLevel = value; } }
+               // input file options
+               //------------------------------------------------------------------
+               public ArrayList AddedModules = new ArrayList();
 
-               [Option("Displays time stamps of various compiler events")]
-               public bool timestamp
+               [Option("[NOT IMPLEMENTED YET]References metadata from specified {module}", "addmodule")]
+               public string AddedModule { set { AddedModules.Add(value); } }
+
+               [Option("[NOT IMPLEMENTED YET]Include all files in the current directory and subdirectories according to the {wildcard}", "recurse")]
+               public WhatToDoNext Recurse(string wildcard)
                {
-                       set
+                       //AddFiles (DirName, true); // TODO wrong semantics
+                       return WhatToDoNext.GoAhead;
+               }
+
+               [Option(-1, "References metadata from the specified {assembly}", 'r', "reference")]
+               public string AddedReference { set { references.Add(value); } }
+               
+               // support for the Compact Framework
+               //------------------------------------------------------------------
+               [Option("[NOT IMPLEMENTED YET]Sets the compiler to target the Compact Framework","netcf")]
+               public bool CompileForCompactFramework = false;
+               
+               [Option("[NOT IMPLEMENTED YET]Specifies the {path} to the location of mscorlib.dll and microsoft.visualbasic.dll", "sdkpath")]
+               public string SDKPath = null;
+
+               // resource options
+               //------------------------------------------------------------------
+               public ArrayList EmbeddedResources = new ArrayList();
+               
+               [Option(-1, "Adds the specified {file} as an embedded assembly resource", "resource", "res")]
+               public string AddedResource { set { EmbeddedResources.Add(value); } }
+
+               public ArrayList LinkedResources = new ArrayList();
+               
+               [Option(-1, "[NOT IMPLEMENTED YET]Adds the specified {file} as a linked assembly resource", "linkresource", "linkres")]
+               public string AddedLinkresource { set { LinkedResources.Add(value); } }
+
+               public ArrayList Win32Resources = new ArrayList();
+               
+               [Option(-1, "[NOT IMPLEMENTED YET]Specifies a Win32 resource {file} (.res)", "win32resource")]
+               public string AddedWin32resource { set { Win32Resources.Add(value); } }
+
+               public ArrayList Win32Icons = new ArrayList();
+               
+               [Option(-1, "[NOT IMPLEMENTED YET]Specifies a Win32 icon {file} (.ico) for the default Win32 resources", "win32icon")]
+               public string AddedWin32icon { set { Win32Icons.Add(value); } }
+
+               // code generation options
+               //------------------------------------------------------------------
+               [Option("[NOT IMPLEMENTED YET]Enable optimizations", "optimize")]
+               public bool optimize = false;
+
+               [Option("[NOT IMPLEMENTED YET]Remove integer checks. Default off.")]
+               public bool removeintchecks = false;
+
+               // TODO: handle VB.NET [+|-] boolean syntax
+               [Option("Emit debugging information", 'g', "debug")]
+               public bool want_debugging_support = false;
+
+               [Option("Emit full debugging information (default)", "debug:full")]
+               public bool fullDebugging = false;
+
+               [Option("[IGNORED]Emit PDB file only", "debug:pdbonly")]
+               public bool pdbOnly = false;
+
+               // errors and warnings options
+               //------------------------------------------------------------------
+               [Option("Treat warnings as errors", "warnaserror")]
+               public bool WarningsAreErrors { set { Report.WarningsAreErrors = value; } }
+
+               [Option("Disable warnings", "nowarn")]
+               public bool NoWarnings { set { if (value) RootContext.WarningLevel = 0; } }
+
+
+               // language options
+               //------------------------------------------------------------------
+               public Hashtable Defines = new Hashtable();
+               
+               [Option(-1, "Declares global conditional compilation symbol(s). {symbol-list}:name=value,...", 'd', "define")]
+               public string define { 
+                       set 
                        {
-                               timestamps = true;
-                               last_time = DateTime.Now;
-                               debug_arglist.Add("timestamp");
-                       }
+                               foreach(string item in value.Split(',')) 
+                               {       
+                                       string[] dados = item.Split('=');
+                                       try
+                                       {
+                                               if (dados.Length > 1)
+                                                       Defines.Add(dados[0], dados[1]); 
+                                               else
+                                                       Defines.Add(dados[0], string.Empty);
+                                       }
+                                       catch 
+                                       {
+                                               Error ("Could not define symbol" + dados[0]);
+                                       }
+                               }
+                       } 
+               }
+               
+               [Option("Declare global Imports for namespaces in referenced metadata files. {import-list}:namespace,...", "imports")]
+               public WhatToDoNext imports(string importslist)
+               {
+                       Mono.MonoBASIC.Parser.ImportsList.AddRange(importslist.Split(','));
+                       return WhatToDoNext.GoAhead;
                }
 
-               // TODO : response file support
+               // TODO: handle VB.NET [+|-] boolean syntax
+               [Option("[NOT IMPLEMENTED YET]Require explicit declaration of variables")]
+               public bool optionexplicit { set { Mono.MonoBASIC.Parser.InitialOptionExplicit = value; } }
 
-       
+               // TODO: handle VB.NET [+|-] boolean syntax
+               [Option("[NOT IMPLEMENTED YET]Enforce strict language semantics")]
+               public bool optionstrict { set { Mono.MonoBASIC.Parser.InitialOptionStrict = value; } }
+               
+               [Option("[NOT IMPLEMENTED YET]Specifies binary-style string comparisons. This is the default", "optioncompare:binary")]
+               public bool optioncomparebinary { set { Mono.MonoBASIC.Parser.InitialOptionCompareBinary = true; } }
+
+               [Option("[NOT IMPLEMENTED YET]Specifies text-style string comparisons.", "optioncompare:text")]
+               public bool optioncomparetext { set { Mono.MonoBASIC.Parser.InitialOptionCompareBinary = false; } }
+
+               [Option("Specifies de root {namespace} for all type declarations")]
+               public string rootnamespace { set { RootContext.RootNamespace = value; } }
+               
+               // Miscellaneous options        
+               //------------------------------------------------------------------
+               
+               [Option("[IGNORED]Do not display compiler copyright banner")]
+               public bool nologo = false;
+               
+               [Option("[NOT IMPLEMENTED YET]Quiet output mode")]
+               public bool quiet = false;
+               
+               // TODO: semantics are different and should be adjusted
+               [Option("Display verbose messages", 'v')] 
+               public bool verbose     { set { GenericParser.yacc_verbose_flag = value; } }
+
+               // Advanced options     
+               //------------------------------------------------------------------
+               // TODO: force option to accept number in hex format
+               [Option("[NOT IMPLEMENTED YET]The base {address} for a library or module (hex)")]
+               public int baseaddress;
+               
+               [Option("[NOT IMPLEMENTED YET]Create bug report {file}")]
+               public string bugreport;
+               
+               // TODO: handle VB.NET [+|-] boolean syntax
+               [Option("[NOT IMPLEMENTED YET]Delay-sign the assembly using only the public portion of the strong name key")]
+               public bool delaysign;
+               
+               [Option("[NOT IMPLEMENTED YET]Specifies a strong name key {container}")]
+               public string keycontainer;
+               
+               [Option("[NOT IMPLEMENTED YET]Specifies a strong name key {file}")]
+               public string keyfile;
+
+               public string[] libpath = null;
+               
+               [Option("List of directories to search for metadata references {path-list}:path;...", "libpath")]
+               public WhatToDoNext setlibpath(string pathlist)
+               {
+                       libpath = pathlist.Split(';');
+                       return WhatToDoNext.GoAhead;
+               }
+
+               [Option(@"Specifies the Class or Module that contains Sub Main.
+                       It can also be a {class} that inherits from System.Windows.Forms.Form.",
+                       'm', "main")]
+               public string main { set { RootContext.MainClass = value; } }
+
+               // TODO: handle VB.NET [+|-] boolean syntax
+               [Option("[IGNORED]Emit compiler output in UTF8 character encoding")]
+               public bool utf8output;
+
+               // TODO : response file support
+               
                ArrayList defines = new ArrayList();
                ArrayList references = new ArrayList();
                ArrayList soft_references = new ArrayList();
+               
                string first_source = null;
                Target target = Target.Exe;
                string target_ext = ".exe";
@@ -181,36 +332,13 @@ namespace Mono.Languages
                                (int) span.TotalSeconds, span.Milliseconds, msg);
                }
                        
-               public static int Main (string[] args)
-               {
-                       Driver Exec = new Driver();
-                       
-                       Exec.MainDriver(args);
-
-                       if (Report.Errors == 0) 
-                       {
-                               Console.Write("Compilation succeeded");
-                               if (Report.Warnings > 0) 
-                               {
-                                       Console.Write(" - {0} warning(s)", Report.Warnings);
-                               } 
-                               Console.WriteLine();
-                               return 0;
-                       } 
-                       else 
-                       {
-                               Console.WriteLine("Compilation failed: {0} Error(s), {1} warnings",
-                                       Report.Errors, Report.Warnings);
-                               return 1;
-                       }
-               }
-
                public int LoadAssembly (string assembly, bool soft)
                {
                        Assembly a;
                        string total_log = "";
 
-                       try {
+                       try 
+                       {
                                char[] path_chars = { '/', '\\' };
 
                                if (assembly.IndexOfAny (path_chars) != -1)
@@ -219,22 +347,33 @@ namespace Mono.Languages
                                        a = Assembly.Load(assembly);
                                TypeManager.AddAssembly (a);
                                return 0;
-                       } catch (FileNotFoundException){
-                               foreach (string dir in LinkPaths){
-                                       string full_path = dir + "/" + assembly + ".dll";
-
-                                       try {
-                                               a = Assembly.LoadFrom (full_path);
-                                               TypeManager.AddAssembly (a);
-                                               return 0;
-                                       } catch (FileNotFoundException ff) {
-                                               total_log += ff.FusionLog;
-                                               continue;
+                       }
+                       catch (FileNotFoundException)
+                       {
+                               if (libpath != null)
+                               {
+                                       foreach (string dir in libpath)
+                                       {
+                                               string full_path = dir + "/" + assembly + ".dll";
+
+                                               try 
+                                               {
+                                                       a = Assembly.LoadFrom (full_path);
+                                                       TypeManager.AddAssembly (a);
+                                                       return 0;
+                                               } 
+                                               catch (FileNotFoundException ff) 
+                                               {
+                                                       total_log += ff.FusionLog;
+                                                       continue;
+                                               }
                                        }
                                }
                                if (soft)
                                        return 0;
-                       } catch (BadImageFormatException f) {
+                       }
+                       catch (BadImageFormatException f) 
+                       {
                                Error ("// Bad file format while loading assembly");
                                Error ("Log: " + f.FusionLog);
                                return 1;
@@ -279,6 +418,12 @@ namespace Mono.Languages
                        defines = new ArrayList ();
                        defines.Add ("__MonoBASIC__");
                }
+               
+               void SetupDefaultImports()
+               {
+                       Mono.MonoBASIC.Parser.ImportsList = new ArrayList();
+                       Mono.MonoBASIC.Parser.ImportsList.Add("Microsoft.VisualBasic");
+               }
 
 
                //
@@ -386,8 +531,8 @@ namespace Mono.Languages
                                "System",
                                "System.Data",
                                "System.Xml",
-                               "Microsoft.VisualBasic", // just for now
-#if false
+                               "Microsoft.VisualBasic" , 
+#if EXTRA_DEFAULT_REFS
                                //
                                // Is it worth pre-loading all this stuff?
                                //
@@ -406,7 +551,7 @@ namespace Mono.Languages
                                "System.ServiceProcess",
                                "System.Web",
                                "System.Web.RegularExpressions",
-                               "System.Web.Services",
+                               "System.Web.Services" ,
                                "System.Windows.Forms"
 #endif
                        };
@@ -444,38 +589,24 @@ namespace Mono.Languages
                        {
                                if (outputFile_Name == null)
                                {
-                                       if (output_file == null)
+                                       if (OutputFileName == null)
                                        {
                                                int pos = first_source.LastIndexOf(".");
 
                                                if (pos > 0)
-                                                       output_file = first_source.Substring(0, pos);
+                                                       OutputFileName = first_source.Substring(0, pos);
                                                else
-                                                       output_file = first_source;
+                                                       OutputFileName = first_source;
                                        }
-                                       string bname = CodeGen.Basename(output_file);
+                                       string bname = CodeGen.Basename(OutputFileName);
                                        if (bname.IndexOf(".") == -1)
-                                               output_file +=  target_ext;
-                                       outputFile_Name = output_file;
+                                               OutputFileName +=  target_ext;
+                                       outputFile_Name = OutputFileName;
                                }
                                return outputFile_Name;
                        }
                }
 
-               /// <summary>
-               ///    Parses the arguments, and calls the compilation process.
-               /// </summary>
-               void MainDriver(string [] args)
-               {
-                       ProcessArgs(args);
-                       CompileAll();
-               }
-
-               public Driver()
-               {
-                       SetupDefaultDefines();  
-               }
-
                bool ParseAll() // Phase 1
                {
                        if (first_source == null)
@@ -572,6 +703,73 @@ namespace Mono.Languages
                        return true;
                }
                
+               bool IsSWFApp()
+               {
+                       string mainclass = GetFQMainClass();
+                       
+                       if (mainclass != null) {
+                               foreach (string r in references) {
+                                       if (r.IndexOf ("System.Windows.Forms") >= 0) {
+                                               Type t = TypeManager.LookupType(mainclass);
+                                               if (t != null) 
+                                                       return t.IsSubclassOf (TypeManager.LookupType("System.Windows.Forms.Form"));
+                                               break;  
+                                       }       
+                               }
+                       }
+                       return false;
+               }
+               
+               string GetFQMainClass()
+               {       
+                       if (RootContext.RootNamespace != "")
+                               return RootContext.RootNamespace + "." + RootContext.MainClass;
+                       else
+                               return RootContext.MainClass;                   
+               }
+               
+               void FixEntryPoint()
+               {
+                       if (target == Target.Exe || target == Target.WinExe)
+                       {
+                               MethodInfo ep = RootContext.EntryPoint;
+                       
+                               if (ep == null)
+                               {
+                                       // If we don't have a valid entry point yet
+                                       // AND if System.Windows.Forms is included
+                                       // among the dependencies, we have to build
+                                       // a new entry point on-the-fly. Otherwise we
+                                       // won't be able to compile SWF code out of the box.
+
+                                       if (IsSWFApp()) 
+                                       {                                                                                               
+                                               Type t = TypeManager.LookupType(GetFQMainClass());
+                                               if (t != null) 
+                                               {                                                       
+                                                       TypeBuilder tb = t as TypeBuilder;
+                                                       MethodBuilder mb = tb.DefineMethod ("Main", MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard, 
+                                                               typeof(void), new Type[0]);
+
+                                                       Type SWFA = TypeManager.LookupType("System.Windows.Forms.Application");
+                                                       Type SWFF = TypeManager.LookupType("System.Windows.Forms.Form");
+                                                       Type[] args = new Type[1];
+                                                       args[0] = SWFF;
+                                                       MethodInfo mi = SWFA.GetMethod("Run", args);
+                                                       ILGenerator ig = mb.GetILGenerator();
+                                                       ConstructorInfo ci = TypeManager.GetConstructor (TypeManager.LookupType(t.FullName), new Type[0]);
+                                                       
+                                                       ig.Emit (OpCodes.Newobj, ci);
+                                                       ig.Emit (OpCodes.Call, mi);
+                                                       ig.Emit (OpCodes.Ret);
+
+                                                       RootContext.EntryPoint = mb as MethodInfo;
+                                               }
+                                       }
+                               }
+                       }
+               }
+
                bool GenerateAssembly()
                {
                        //
@@ -579,8 +777,11 @@ namespace Mono.Languages
                        //
                        if (timestamps)
                                ShowTime ("Emitting code");
+                       
+                       
 
                        RootContext.EmitCode();
+                       FixEntryPoint();
                        if (Report.Errors > 0)
                                return false;
 
@@ -613,7 +814,7 @@ namespace Mono.Languages
                        
                                if (ep == null)
                                {
-                                       Report.Error (5001, "Program " + outputFileName +
+                                       Report.Error (30737, "Program " + outputFileName +
                                                " does not have an entry point defined");
                                        return false;
                                }
@@ -622,8 +823,8 @@ namespace Mono.Languages
                        }
 
                        // Add the resources
-                       if (resources != null)
-                               foreach (string file in resources)
+                       if (EmbeddedResources != null)
+                               foreach (string file in EmbeddedResources)
                                        CodeGen.AssemblyBuilder.AddResourceFile (file, file);
                        
                        CodeGen.Save(outputFileName);
@@ -644,17 +845,54 @@ namespace Mono.Languages
 
                public void CompileAll()
                {
+/* 
+                   VB.NET expects the default namespace to be "" (empty string)                
+                   
+                   if (RootContext.RootNamespace == "")
+                   {
+                     RootContext.RootNamespace = System.IO.Path.GetFileNameWithoutExtension(outputFileName);
+                   }
+*/
                        if (!ParseAll()) // Phase 1
                                return;
 
                        if (!ResolveAllTypes()) // Phase 2
                                return;
 
-                       if (!GenerateAssembly()) // Phase 3 
-                               return;
+                       GenerateAssembly(); // Phase 3 
+               }
+
+               /// <summary>
+               ///    Parses the arguments, and calls the compilation process.
+               /// </summary>
+               int MainDriver(string [] args)
+               {
+                       Console.WriteLine ("THIS IS ALPHA AND UNSUPPORTED SOFTWARE, USE AT YOUR OWN RISK.");
+                       SetupDefaultDefines();  
+                       
+                       SetupDefaultImports();
+
+                       ProcessArgs(args);
+                       
+                       if (first_source == null)
+                       {
+                               if (!quiet) 
+                                       DoHelp();
+                               return 2;
+                       }
+
+                       CompileAll();
+
+                       return Report.ProcessResults(quiet);
+               }
+
+               public static int Main (string[] args)
+               {
+                       Driver Exec = new Driver();
+                       
+                       Report.Stacktrace = false;
 
-                       if (Report.ExpectedError != 0)
-                               Error("Failed to report expected Error " + Report.ExpectedError);
+                       return Exec.MainDriver(args);
                }
 
        }