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 ();
\r
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 "--parse Only parses the source file\n" +
89 "--probe X L Probes for the source to generate code X on line L\n" +
90 "--checked Set default context to checked\n" +
91 "-r References an assembly\n");
95 public static void error (string msg)
97 Console.WriteLine ("Error: " + msg);
100 public static void notice (string msg)
102 Console.WriteLine (msg);
105 public static int Main(string[] args)
107 Driver driver = new Driver (args);
109 return driver.error_count;
112 public int LoadAssembly (string assembly)
115 string total_log = "";
118 a = Assembly.Load (assembly);
119 context.TypeManager.AddAssembly (a);
121 } catch (FileNotFoundException){
122 foreach (string dir in link_paths){
123 string full_path = dir + "/" + assembly + ".dll";
126 a = Assembly.LoadFrom (full_path);
127 context.TypeManager.AddAssembly (a);
129 } catch (FileNotFoundException ff) {
130 total_log += ff.FusionLog;
134 } catch (BadImageFormatException f) {
135 error ("// Bad file format while loading assembly");
136 error ("Log: " + f.FusionLog);
138 } catch (FileLoadException f){
139 error ("// File Load Exception: ");
140 error ("Log: " + f.FusionLog);
142 } catch (ArgumentNullException){
143 error ("// Argument Null exception ");
147 Report.Error (6, "Can not find assembly `" + assembly + "'" );
148 Console.WriteLine ("Log: \n" + total_log);
154 // Loads all assemblies referenced on the command line
156 public int LoadReferences ()
160 foreach (string r in references){
161 errors += LoadAssembly (r);
168 // Parses the arguments, and drives the compilation
171 // TODO: Mostly structured to debug the compiler
172 // now, needs to be turned into a real driver soon.
174 public Driver (string [] args)
176 ITreeDump generator = null;
178 string output_file = null;
180 context = new RootContext ();
181 references = new ArrayList ();
182 link_paths = new ArrayList ();
187 // This is not required because Assembly.Load knows about this
190 link_paths.Add ("file:///C:/WINNT/Microsoft.NET/Framework/v1.0.2914");
192 for (i = 0; i < args.Length; i++){
193 string arg = args [i];
196 if (arg.StartsWith ("-")){
202 if (arg == "--parse"){
207 if (arg == "--probe"){
210 code = Int32.Parse (args [++i], 0);
211 line = Int32.Parse (args [++i], 0);
212 Report.SetProbe (code, line);
217 generator.ParseOptions (args [++i]);
221 if (arg == "-o" || arg == "--output"){
223 output_file = args [++i];
225 error ("Could not write to `"+args [i]);
232 if (arg == "--checked"){
233 context.Checked = true;
237 if (arg == "--target"){
238 string type = args [++i];
242 target = Target.Library;
251 target = Target.WinExe;
255 target = Target.Module;
263 references.Add (args [++i]);
268 link_paths.Add (args [++i]);
272 if (arg == "--nostdlib"){
273 context.StdLib = false;
277 if (arg == "--fatal"){
285 } catch (System.IndexOutOfRangeException){
289 } catch (System.FormatException) {
295 if (first_source == null)
298 if (!arg.EndsWith (".cs")){
299 error ("Do not know how to compile " + arg);
304 errors += parse (arg);
307 if (first_source == null){
308 Report.Error (2008, "No files to compile were specified");
312 if (Report.Errors > 0)
319 // Load Core Library for default compilation
322 references.Insert (0, "mscorlib");
323 references.Insert (1, "System");
327 error ("Parsing failed");
332 // Load assemblies required
334 errors += LoadReferences ();
337 error ("Could not load one or more assemblies");
343 // Dumping the parsed tree.
345 // This code generation interface is only here
346 // for debugging the parser.
348 if (generator != null){
349 if (output_file == null){
350 error ("Error: no output file specified");
354 Stream output_stream = File.Create (output_file);
355 StreamWriter output = new StreamWriter (output_stream);
357 errors += generator.Dump (context.Tree, output);
360 error ("Compilation failed");
363 notice ("Compilation successful");
370 error_count = errors;
375 if (output_file == null){
376 int pos = first_source.LastIndexOf (".");
378 output_file = first_source.Substring (0, pos) + target_ext;
381 context.CodeGen = new CodeGen (output_file, output_file);
384 // Before emitting, we need to get the core
385 // types emitted from the user defined types
386 // or from the system ones.
388 context.TypeManager.InitCoreTypes ();
390 context.TypeManager.AddModule (context.CodeGen.ModuleBuilder);
393 // The second pass of the compiler
395 context.ResolveTree ();
396 context.PopulateTypes ();
398 if (Report.Errors > 0){
399 error ("Compilation failed");
404 // The code generator
408 if (Report.Errors > 0){
409 error ("Compilation failed");
413 context.CloseTypes ();
415 PEFileKinds k = PEFileKinds.ConsoleApplication;
417 if (target == Target.Library || target == Target.Module)
419 else if (target == Target.Exe)
420 k = PEFileKinds.ConsoleApplication;
421 else if (target == Target.WinExe)
422 k = PEFileKinds.WindowApplication;
424 if (target == Target.Exe || target == Target.WinExe){
425 MethodInfo ep = context.EntryPoint;
428 Report.Error (5001, "Program " + output_file +
429 " does not have an entry point defined");
433 context.CodeGen.AssemblyBuilder.SetEntryPoint (ep, k);
436 context.CodeGen.Save (output_file);
438 if (Report.Errors > 0){
439 error ("Compilation failed");
441 } else if (Report.ProbeCode != 0){
442 error ("Failed to report code " + Report.ProbeCode);
443 Environment.Exit (124);