2 // driver.cs: The compiler command line driver.
4 // Author: Miguel de Icaza (miguel@gnu.org)
6 // Licensed under the terms of the GNU GPL
8 // (C) 2001 Ximian, Inc (http://www.ximian.com)
14 using System.Reflection;
15 using System.Reflection.Emit;
16 using System.Collections;
22 /// The compiler driver.
28 Library, Exe, Module, WinExe
32 // Assemblies references to be linked. Initialized with
41 bool yacc_verbose = false;
47 Target target = Target.Exe;
48 string target_ext = ".exe";
50 bool parse_only = false;
52 public int parse (string input_file)
55 System.IO.Stream input;
59 input = System.IO.File.OpenRead (input_file);
61 Report.Error (2001, "Source file '" + input_file + "' could not be opened");
65 parser = new CSharpParser (context, input_file, input);
66 parser.yacc_verbose = yacc_verbose;
68 errors = parser.parse ();
69 } catch (Exception ex) {
70 Console.WriteLine (ex);
71 Console.WriteLine ("Compilation aborted");
81 "compiler [options] source-files\n\n" +
82 "-v Verbose parsing\n"+
83 "-o Specifies output file\n" +
84 "-L Specifies path for loading assemblies\n" +
85 "--fatal Makes errors fatal\n" +
86 "--nostdlib Does not load core libraries\n" +
87 "--target Specifies the target (exe, winexe, library, module)\n" +
88 "--dumper Specifies a tree dumper\n" +
89 "--parse Only parses the source file\n" +
90 "--probe X L Probes for the source to generate code X on line L\n" +
91 "-r References an assembly\n");
95 public ITreeDump lookup_dumper (string name)
98 return new Generator.TreeDump ();
101 // return new MSIL.Generator ();
106 public static void error (string msg)
108 Console.WriteLine ("Error: " + msg);
111 public static void notice (string msg)
113 Console.WriteLine (msg);
116 public static int Main(string[] args)
118 Driver driver = new Driver (args);
120 return driver.error_count;
123 public int LoadAssembly (string assembly)
126 string total_log = "";
129 a = Assembly.Load (assembly);
130 context.TypeManager.AddAssembly (a);
132 } catch (FileNotFoundException){
133 foreach (string dir in link_paths){
134 string full_path = dir + "/" + assembly;;
137 a = Assembly.LoadFrom (full_path);
138 context.TypeManager.AddAssembly (a);
140 } catch (FileNotFoundException ff) {
141 total_log += ff.FusionLog;
145 } catch (BadImageFormatException f) {
146 error ("// Bad file format while loading assembly");
147 error ("Log: " + f.FusionLog);
149 } catch (FileLoadException f){
150 error ("// File Load Exception: ");
151 error ("Log: " + f.FusionLog);
153 } catch (ArgumentNullException){
154 error ("// Argument Null exception ");
158 Report.Error (6, "Can not find assembly `" + assembly + "'" );
159 Console.WriteLine ("Log: \n" + total_log);
165 // Loads all assemblies referenced on the command line
167 public int LoadReferences ()
171 foreach (string r in references){
172 errors += LoadAssembly (r);
179 // Parses the arguments, and drives the compilation
182 // TODO: Mostly structured to debug the compiler
183 // now, needs to be turned into a real driver soon.
185 public Driver (string [] args)
187 ITreeDump generator = null;
189 string output_file = null;
191 context = new RootContext ();
192 references = new ArrayList ();
193 link_paths = new ArrayList ();
198 // This is not required because Assembly.Load knows about this
201 // link_paths.Add ("file:///C:/WINNT/Microsoft.NET/Framework/v1.0.2914");
203 for (i = 0; i < args.Length; i++){
204 string arg = args [i];
207 if (arg.StartsWith ("-")){
213 if (arg.StartsWith ("--dumper")){
214 generator = lookup_dumper (args [++i]);
218 if (arg == "--parse"){
223 if (arg == "--probe"){
226 code = Int32.Parse (args [++i], 0);
227 line = Int32.Parse (args [++i], 0);
228 Report.SetProbe (code, line);
233 generator.ParseOptions (args [++i]);
237 if (arg == "-o" || arg == "--output"){
239 output_file = args [++i];
241 error ("Could not write to `"+args [i]);
248 if (arg == "--target"){
249 string type = args [++i];
253 target = Target.Library;
262 target = Target.WinExe;
266 target = Target.Module;
274 references.Add (args [++i]);
279 link_paths.Add (args [++i]);
283 if (arg == "--nostdlib"){
284 context.StdLib = false;
288 if (arg == "--fatal"){
296 } catch (System.IndexOutOfRangeException){
300 } catch (System.FormatException) {
306 if (!arg.EndsWith (".cs")){
308 error ("Do not know how to compile " + arg);
313 if (first_source == null)
316 errors += parse (arg);
319 if (first_source == null){
320 Report.Error (2008, "No files to compile were specified");
324 if (Report.Errors > 0)
331 // Load Core Library for default compilation
334 references.Insert (0, "mscorlib");
335 references.Insert (1, "System");
339 error ("Parsing failed");
342 notice ("Parsing successful");
345 // Load assemblies required
347 errors += LoadReferences ();
350 error ("Could not load one or more assemblies");
356 // Dumping the parsed tree.
358 // This code generation interface is only here
359 // for debugging the parser.
361 if (generator != null){
362 if (output_file == null){
363 error ("Error: no output file specified");
367 Stream output_stream = File.Create (output_file);
368 StreamWriter output = new StreamWriter (output_stream);
370 errors += generator.Dump (context.Tree, output);
373 error ("Compilation failed");
376 notice ("Compilation successful");
383 error_count = errors;
388 if (output_file == null){
389 int pos = first_source.LastIndexOf (".");
391 output_file = first_source.Substring (0, pos) + target_ext;
394 context.CodeGen = new CodeGen (output_file, output_file);
397 // Before emitting, we need to get the core
398 // types emitted from the user defined types
399 // or from the system ones.
401 context.TypeManager.InitCoreTypes ();
404 // The second pass of the compiler
406 context.ResolveTree ();
407 context.PopulateTypes ();
409 if (Report.Errors > 0){
410 error ("Compilation failed");
415 // The code generator
419 if (Report.Errors > 0){
420 error ("Compilation failed");
424 context.CloseTypes ();
426 PEFileKinds k = PEFileKinds.ConsoleApplication;
428 if (target == Target.Library || target == Target.Module)
430 else if (target == Target.Exe)
431 k = PEFileKinds.ConsoleApplication;
432 else if (target == Target.WinExe)
433 k = PEFileKinds.WindowApplication;
435 if (target == Target.Exe || target == Target.WinExe){
436 MethodInfo ep = context.EntryPoint;
439 Report.Error (5001, "Program " + output_file +
440 " does not have an entry point defined");
444 context.CodeGen.AssemblyBuilder.SetEntryPoint (ep, k);
447 context.CodeGen.Save (output_file);
449 if (Report.Errors > 0){
450 error ("Compilation failed");
452 } else if (Report.ProbeCode != 0){
453 error ("Failed to report code " + Report.ProbeCode);
454 Environment.Exit (124);