// (C) 2001 Ximian, Inc (http://www.ximian.com)\r
//\r
\r
-namespace CSC\r
+namespace CIR\r
{\r
using System;\r
using System.Reflection;\r
using System.IO;\r
using CIR;\r
using Generator;\r
- using CSC;\r
\r
/// <summary>\r
- /// Summary description for Class1.\r
+ /// The compiler driver.\r
/// </summary>\r
public class Driver\r
{\r
+\r
+ enum Target {\r
+ Library, Exe, Module, WinExe\r
+ };\r
+ \r
//\r
// Assemblies references to be linked. Initialized with\r
// mscorlib.dll here.\r
// Lookup paths\r
ArrayList link_paths;\r
\r
- // Our parser context.\r
- Tree context;\r
- \r
+ RootContext context; \r
+\r
bool yacc_verbose = false;\r
\r
int error_count = 0;\r
\r
- public int parse (Tree context, string input_file)\r
+ string first_source;\r
+\r
+ Target target = Target.Exe;\r
+ \r
+ public int parse (string input_file)\r
{\r
CSharpParser parser;\r
System.IO.Stream input;\r
public void Usage ()\r
{\r
Console.WriteLine (\r
- "compiler [-v] [-t tree] [-o output] [-L path] [-r reference] sources.cs\n" +\r
- "-v Verbose parsing\n"+\r
- "-o Specifies output file\n" +\r
- "-L Specifies path for loading assemblies\n" +\r
- "-r References an assembly\n");\r
+ "compiler [options] source-files\n\n" +\r
+ "-v Verbose parsing\n"+\r
+ "-o Specifies output file\n" +\r
+ "-L Specifies path for loading assemblies\n" +\r
+ "--nostdlib Does not load core libraries\n" +\r
+ "--target Specifies the target (exe, winexe, library, module)\n" +\r
+ "--dumper Specifies a tree dumper\n" +\r
+ "-r References an assembly\n");\r
\r
}\r
\r
- public IGenerator lookup_output (string name)\r
+ public ITreeDump lookup_dumper (string name)\r
{\r
if (name == "tree")\r
return new Generator.TreeDump ();\r
- if (name == "il")\r
- return new MSIL.Generator ();\r
+ \r
+ // if (name == "il")\r
+ // return new MSIL.Generator ();\r
\r
return null;\r
}\r
string full_path = dir + "/" + assembly;\r
\r
try {\r
+ Console.WriteLine ("Loading: " + assembly);\r
a = Assembly.Load (assembly);\r
} catch (FileNotFoundException f) {\r
error ("// File not found: " + full_path);\r
return 1;\r
}\r
\r
- context.AddAssembly (a);\r
+ context.TypeManager.AddAssembly (a);\r
}\r
return 0;\r
}\r
- \r
+\r
+ // <summary>\r
+ // Loads all assemblies referenced on the command line\r
+ // </summary>\r
public int LoadReferences ()\r
{\r
int errors = 0;\r
return errors;\r
}\r
\r
- \r
+ // <summary>\r
+ // Parses the arguments, and drives the compilation\r
+ // process.\r
+ //\r
+ // TODO: Mostly structured to debug the compiler\r
+ // now, needs to be turned into a real driver soon.\r
+ // </summary>\r
public Driver (string [] args)\r
{\r
- Stream output_stream = Console.OpenStandardOutput ();\r
- IGenerator generator = null;\r
+ ITreeDump generator = null;\r
int errors = 0, i;\r
+ string output_file = null;\r
\r
- context = new Tree ();\r
+ context = new RootContext ();\r
references = new ArrayList ();\r
link_paths = new ArrayList ();\r
\r
//\r
// Setup defaults\r
//\r
- references.Add ("mscorlib");\r
link_paths.Add ("file:///C:/WINNT/Microsoft.NET/Framework/v1.0.2914");\r
\r
for (i = 0; i < args.Length; i++){\r
continue;\r
}\r
\r
- if (arg.StartsWith ("-t")){\r
- generator = lookup_output (args [++i]);\r
+ if (arg.StartsWith ("--dumper")){\r
+ generator = lookup_dumper (args [++i]);\r
continue;\r
}\r
\r
\r
if (arg.StartsWith ("-o")){\r
try {\r
- output_stream = File.Create (args [++i]);\r
+ output_file = args [++i];\r
} catch (Exception){\r
error ("Could not write to `"+args [i]);\r
error_count++;\r
continue;\r
}\r
\r
+ if (arg.StartsWith ("--target")){\r
+ string type = args [++i];\r
+\r
+ switch (type){\r
+ case "library":\r
+ target = Target.Library;\r
+ break;\r
+ \r
+ case "exe":\r
+ target = Target.Exe;\r
+ break;\r
+\r
+ case "winexe":\r
+ target = Target.WinExe;\r
+ break;\r
+ \r
+ case "module":\r
+ target = Target.Module;\r
+ break;\r
+ }\r
+ }\r
+ \r
if (arg.StartsWith ("-r")){\r
references.Add (args [++i]);\r
continue;\r
continue;\r
}\r
\r
+ if (arg == "--nostdlib"){\r
+ context.StdLib = false;\r
+ }\r
+\r
Usage ();\r
error_count++;\r
return;\r
}\r
\r
if (!arg.EndsWith (".cs")){\r
+ \r
error ("Do not know how to compile " + arg);\r
errors++;\r
continue;\r
}\r
\r
- errors += parse (context, arg);\r
+ if (first_source == null)\r
+ first_source = arg;\r
+ \r
+ errors += parse (arg);\r
+ }\r
+\r
+ if (first_source == null){\r
+ context.Report.Error (2008, "No files to compile were specified");\r
+ return;\r
}\r
- if (errors > 0)\r
- error ("// Parsing failed");\r
- else\r
- notice ("// Parsing successful"); \r
+ \r
+ //\r
+ // Load Core Library for default compilation\r
+ //\r
+ if (context.StdLib)\r
+ references.Insert (0, "mscorlib");\r
+\r
+ if (errors > 0){\r
+ error ("Parsing failed");\r
+ return;\r
+ } else\r
+ notice ("Parsing successful");\r
\r
//\r
// Load assemblies required\r
//\r
errors += LoadReferences ();\r
\r
- if (errors > 0)\r
- error ("// Could not load one or more assemblies");\r
- else\r
- notice ("// Assemblies loaded");\r
-\r
+ if (errors > 0){\r
+ error ("Could not load one or more assemblies");\r
+ return;\r
+ }\r
\r
- errors += context.BuilderInit ("Module", "Module.exe");\r
\r
//\r
- // Name resolution on the tree.\r
- //\r
- errors += context.Resolve ();\r
- \r
+ // Dumping the parsed tree.\r
//\r
- // Code generation from the tree\r
+ // This code generation interface is only here\r
+ // for debugging the parser. \r
//\r
if (generator != null){\r
+ if (output_file == null){\r
+ error ("Error: no output file specified");\r
+ return;\r
+ }\r
+\r
+ Stream output_stream = File.Create (output_file);\r
StreamWriter output = new StreamWriter (output_stream);\r
\r
- errors += generator.GenerateFromTree (context, output);\r
+ errors += generator.Dump (context.Tree, output);\r
\r
- if (errors > 0)\r
- error ("// Compilation failed");\r
- else\r
- notice ("// Compilation successful");\r
+ if (errors > 0){\r
+ error ("Compilation failed");\r
+ return;\r
+ } else\r
+ notice ("Compilation successful");\r
\r
output.Flush ();\r
output.Close ();\r
- }\r
+ } \r
\r
+ \r
error_count = errors;\r
+\r
+ //\r
+ // Quick hack\r
+ //\r
+ if (output_file == null){\r
+ int pos = first_source.LastIndexOf (".");\r
+\r
+ output_file = first_source.Substring (0, pos) + ".exe";\r
+ }\r
+\r
+ context.CodeGen = new CodeGen (output_file, output_file);\r
+\r
+ //\r
+ // The second pass of the compiler\r
+ //\r
+ context.ResolveTree ();\r
+ context.PopulateTypes ();\r
+\r
+ //\r
+ // Before emitting, we need to get the core\r
+ // types emitted from the user defined types\r
+ // or from the system ones.\r
+ //\r
+ context.TypeManager.InitCoreTypes ();\r
+\r
+ //\r
+ // The code generator\r
+ //\r
+ context.EmitCode ();\r
+ \r
+ if (context.Report.Errors > 0){\r
+ error ("Compilation failed");\r
+ return;\r
+ }\r
+ \r
+ context.CloseTypes ();\r
+\r
+ PEFileKinds k = PEFileKinds.ConsoleApplication;\r
+ \r
+ if (target == Target.Library || target == Target.Module)\r
+ k = PEFileKinds.Dll;\r
+ else if (target == Target.Exe)\r
+ k = PEFileKinds.ConsoleApplication;\r
+ else if (target == Target.WinExe)\r
+ k = PEFileKinds.WindowApplication;\r
+\r
+ if (target == Target.Exe || target == Target.WinExe){\r
+ MethodInfo ep = context.EntryPoint;\r
+\r
+ if (ep == null){\r
+ context.Report.Error (5001, "Program " + output_file +\r
+ " does not have an entry point defined");\r
+ return;\r
+ }\r
+ \r
+ context.CodeGen.AssemblyBuilder.SetEntryPoint (ep, k);\r
+ }\r
+ \r
+ context.CodeGen.Save (context.Report, output_file);\r
+\r
+ if (context.Report.Errors > 0){\r
+ error ("Compilation failed");\r
+ return;\r
+ }\r
+\r
+ notice ("Success");\r
}\r
\r
}\r
}\r
-\r