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;
23 /// The compiler driver.
29 Library, Exe, Module, WinExe
33 // Assemblies references to be linked. Initialized with
42 bool yacc_verbose = false;
48 Target target = Target.Exe;
49 string target_ext = ".exe";
51 bool parse_only = false;
53 public int parse (string input_file)
56 System.IO.Stream input;
60 input = System.IO.File.OpenRead (input_file);
62 Report.Error (2001, "Source file '" + input_file + "' could not be opened");
66 parser = new CSharpParser (context, input_file, input);
67 parser.yacc_verbose = yacc_verbose;
69 errors = parser.parse ();
\r
70 } catch (Exception ex) {
71 Console.WriteLine (ex);
72 Console.WriteLine ("Compilation aborted");
82 "compiler [options] source-files\n\n" +
83 "-v Verbose parsing\n"+
84 "-o Specifies output file\n" +
85 "-L Specifies path for loading assemblies\n" +
86 "--fatal Makes errors fatal\n" +
87 "--nostdlib Does not load core libraries\n" +
88 "--target Specifies the target (exe, winexe, library, module)\n" +
89 "--dumper Specifies a tree dumper\n" +
90 "--parse Only parses the source file\n" +
91 "--probe X L Probes for the source to generate code X on line L\n" +
92 "--checked Set default context to checked\n" +
93 "-r References an assembly\n");
97 public ITreeDump lookup_dumper (string name)
100 return new Generator.TreeDump ();
103 // return new MSIL.Generator ();
108 public static void error (string msg)
110 Console.WriteLine ("Error: " + msg);
113 public static void notice (string msg)
115 Console.WriteLine (msg);
118 public static int Main(string[] args)
120 Driver driver = new Driver (args);
122 return driver.error_count;
125 public int LoadAssembly (string assembly)
128 string total_log = "";
131 a = Assembly.Load (assembly);
132 context.TypeManager.AddAssembly (a);
134 } catch (FileNotFoundException){
135 foreach (string dir in link_paths){
136 string full_path = dir + "/" + assembly;;
139 a = Assembly.LoadFrom (full_path);
140 context.TypeManager.AddAssembly (a);
142 } catch (FileNotFoundException ff) {
143 total_log += ff.FusionLog;
147 } catch (BadImageFormatException f) {
148 error ("// Bad file format while loading assembly");
149 error ("Log: " + f.FusionLog);
151 } catch (FileLoadException f){
152 error ("// File Load Exception: ");
153 error ("Log: " + f.FusionLog);
155 } catch (ArgumentNullException){
156 error ("// Argument Null exception ");
160 Report.Error (6, "Can not find assembly `" + assembly + "'" );
161 Console.WriteLine ("Log: \n" + total_log);
167 // Loads all assemblies referenced on the command line
169 public int LoadReferences ()
173 foreach (string r in references){
174 errors += LoadAssembly (r);
181 // Parses the arguments, and drives the compilation
184 // TODO: Mostly structured to debug the compiler
185 // now, needs to be turned into a real driver soon.
187 public Driver (string [] args)
189 ITreeDump generator = null;
191 string output_file = null;
193 context = new RootContext ();
194 references = new ArrayList ();
195 link_paths = new ArrayList ();
200 // This is not required because Assembly.Load knows about this
203 // link_paths.Add ("file:///C:/WINNT/Microsoft.NET/Framework/v1.0.2914");
205 for (i = 0; i < args.Length; i++){
206 string arg = args [i];
209 if (arg.StartsWith ("-")){
215 if (arg.StartsWith ("--dumper")){
216 generator = lookup_dumper (args [++i]);
220 if (arg == "--parse"){
225 if (arg == "--probe"){
228 code = Int32.Parse (args [++i], 0);
229 line = Int32.Parse (args [++i], 0);
230 Report.SetProbe (code, line);
235 generator.ParseOptions (args [++i]);
239 if (arg == "-o" || arg == "--output"){
241 output_file = args [++i];
243 error ("Could not write to `"+args [i]);
250 if (arg == "--checked"){
251 context.Checked = true;
255 if (arg == "--target"){
256 string type = args [++i];
260 target = Target.Library;
269 target = Target.WinExe;
273 target = Target.Module;
281 references.Add (args [++i]);
286 link_paths.Add (args [++i]);
290 if (arg == "--nostdlib"){
291 context.StdLib = false;
295 if (arg == "--fatal"){
303 } catch (System.IndexOutOfRangeException){
307 } catch (System.FormatException) {
313 if (first_source == null)
316 if (!arg.EndsWith (".cs")){
317 error ("Do not know how to compile " + arg);
322 errors += parse (arg);
325 if (first_source == null){
326 Report.Error (2008, "No files to compile were specified");
330 if (Report.Errors > 0)
337 // Load Core Library for default compilation
340 references.Insert (0, "mscorlib");
341 references.Insert (1, "System");
345 error ("Parsing failed");
350 // Load assemblies required
352 errors += LoadReferences ();
355 error ("Could not load one or more assemblies");
361 // Dumping the parsed tree.
363 // This code generation interface is only here
364 // for debugging the parser.
366 if (generator != null){
367 if (output_file == null){
368 error ("Error: no output file specified");
372 Stream output_stream = File.Create (output_file);
373 StreamWriter output = new StreamWriter (output_stream);
375 errors += generator.Dump (context.Tree, output);
378 error ("Compilation failed");
381 notice ("Compilation successful");
388 error_count = errors;
393 if (output_file == null){
394 int pos = first_source.LastIndexOf (".");
396 output_file = first_source.Substring (0, pos) + target_ext;
399 context.CodeGen = new CodeGen (output_file, output_file);
402 // Before emitting, we need to get the core
403 // types emitted from the user defined types
404 // or from the system ones.
406 context.TypeManager.InitCoreTypes ();
408 context.TypeManager.AddModule (context.CodeGen.ModuleBuilder);
411 // The second pass of the compiler
413 context.ResolveTree ();
414 context.PopulateTypes ();
416 if (Report.Errors > 0){
417 error ("Compilation failed");
422 // The code generator
426 if (Report.Errors > 0){
427 error ("Compilation failed");
431 context.CloseTypes ();
433 PEFileKinds k = PEFileKinds.ConsoleApplication;
435 if (target == Target.Library || target == Target.Module)
437 else if (target == Target.Exe)
438 k = PEFileKinds.ConsoleApplication;
439 else if (target == Target.WinExe)
440 k = PEFileKinds.WindowApplication;
442 if (target == Target.Exe || target == Target.WinExe){
443 MethodInfo ep = context.EntryPoint;
446 Report.Error (5001, "Program " + output_file +
447 " does not have an entry point defined");
451 context.CodeGen.AssemblyBuilder.SetEntryPoint (ep, k);
454 context.CodeGen.Save (output_file);
456 if (Report.Errors > 0){
457 error ("Compilation failed");
459 } else if (Report.ProbeCode != 0){
460 error ("Failed to report code " + Report.ProbeCode);
461 Environment.Exit (124);