-//
+//
// driver.cs: The compiler command line driver.
//
// Author: Rafael Teixeira (rafaelteixeirabr@hotmail.com)
using System.Collections;
using System.IO;
using System.Globalization;
- using Mono.CSharp;
+ using Mono.MonoBASIC;
using Mono.GetOptions;
enum Target
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;
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";
(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)
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;
defines = new ArrayList ();
defines.Add ("__MonoBASIC__");
}
+
+ void SetupDefaultImports()
+ {
+ Mono.MonoBASIC.Parser.ImportsList = new ArrayList();
+ Mono.MonoBASIC.Parser.ImportsList.Add("Microsoft.VisualBasic");
+ }
//
"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?
//
"System.ServiceProcess",
"System.Web",
"System.Web.RegularExpressions",
- "System.Web.Services",
+ "System.Web.Services" ,
"System.Windows.Forms"
#endif
};
{
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)
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()
{
//
//
if (timestamps)
ShowTime ("Emitting code");
+
+
RootContext.EmitCode();
+ FixEntryPoint();
if (Report.Errors > 0)
return false;
if (ep == null)
{
- Report.Error (5001, "Program " + outputFileName +
+ Report.Error (30737, "Program " + outputFileName +
" does not have an entry point defined");
return false;
}
}
// 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);
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);
}
}