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;
21 /// The compiler driver.
27 Library, Exe, Module, WinExe
31 // Assemblies references to be linked. Initialized with
40 bool yacc_verbose = false;
46 Target target = Target.Exe;
47 string target_ext = ".exe";
49 bool parse_only = false;
51 public int parse (string input_file)
54 System.IO.Stream input;
58 input = System.IO.File.OpenRead (input_file);
60 Report.Error (2001, "Source file '" + input_file + "' could not be opened");
64 parser = new CSharpParser (context, input_file, input);
65 parser.yacc_verbose = yacc_verbose;
67 errors = parser.parse ();
\r
68 } catch (Exception ex) {
69 Console.WriteLine (ex);
70 Console.WriteLine ("Compilation aborted");
80 "compiler [options] source-files\n\n" +
81 "-v Verbose parsing\n"+
82 "-o Specifies output file\n" +
83 "-L Specifies path for loading assemblies\n" +
84 "--checked Set default context to checked\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 "-r References an assembly\n");
94 public static void error (string msg)
96 Console.WriteLine ("Error: " + msg);
99 public static void notice (string msg)
101 Console.WriteLine (msg);
104 public static int Main(string[] args)
106 Driver driver = new Driver (args);
108 return driver.error_count;
111 public int LoadAssembly (string assembly)
114 string total_log = "";
117 a = Assembly.Load (assembly);
118 context.TypeManager.AddAssembly (a);
120 } catch (FileNotFoundException){
121 foreach (string dir in link_paths){
122 string full_path = dir + "/" + assembly + ".dll";
125 a = Assembly.LoadFrom (full_path);
126 context.TypeManager.AddAssembly (a);
128 } catch (FileNotFoundException ff) {
129 total_log += ff.FusionLog;
133 } catch (BadImageFormatException f) {
134 error ("// Bad file format while loading assembly");
135 error ("Log: " + f.FusionLog);
137 } catch (FileLoadException f){
138 error ("// File Load Exception: ");
139 error ("Log: " + f.FusionLog);
141 } catch (ArgumentNullException){
142 error ("// Argument Null exception ");
146 Report.Error (6, "Can not find assembly `" + assembly + "'" );
147 Console.WriteLine ("Log: \n" + total_log);
153 /// Loads all assemblies referenced on the command line
155 public int LoadReferences ()
159 foreach (string r in references){
160 errors += LoadAssembly (r);
167 /// Parses the arguments, and drives the compilation
172 /// TODO: Mostly structured to debug the compiler
173 /// now, needs to be turned into a real driver soon.
175 public Driver (string [] args)
177 ITreeDump generator = null;
179 string output_file = null;
181 context = new RootContext ();
182 references = new ArrayList ();
183 link_paths = new ArrayList ();
188 // This is not required because Assembly.Load knows about this
191 link_paths.Add ("file:///C:/WINNT/Microsoft.NET/Framework/v1.0.2914");
193 for (i = 0; i < args.Length; i++){
194 string arg = args [i];
197 if (arg.StartsWith ("-")){
203 if (arg == "--parse"){
208 if (arg == "--probe"){
211 code = Int32.Parse (args [++i], 0);
212 line = Int32.Parse (args [++i], 0);
213 Report.SetProbe (code, line);
218 generator.ParseOptions (args [++i]);
222 if (arg == "-o" || arg == "--output"){
224 output_file = args [++i];
226 error ("Could not write to `"+args [i]);
233 if (arg == "--checked"){
234 context.Checked = true;
238 if (arg == "--target"){
239 string type = args [++i];
243 target = Target.Library;
252 target = Target.WinExe;
256 target = Target.Module;
264 references.Add (args [++i]);
269 link_paths.Add (args [++i]);
273 if (arg == "--nostdlib"){
274 context.StdLib = false;
278 if (arg == "--fatal"){
286 } catch (System.IndexOutOfRangeException){
290 } catch (System.FormatException) {
296 if (first_source == null)
299 if (!arg.EndsWith (".cs")){
300 error ("Do not know how to compile " + arg);
305 errors += parse (arg);
308 if (first_source == null){
309 Report.Error (2008, "No files to compile were specified");
313 if (Report.Errors > 0)
320 // Load Core Library for default compilation
323 references.Insert (0, "mscorlib");
324 references.Insert (1, "System");
328 error ("Parsing failed");
333 // Load assemblies required
335 errors += LoadReferences ();
338 error ("Could not load one or more assemblies");
344 // Dumping the parsed tree.
346 // This code generation interface is only here
347 // for debugging the parser.
349 if (generator != null){
350 if (output_file == null){
351 error ("Error: no output file specified");
355 Stream output_stream = File.Create (output_file);
356 StreamWriter output = new StreamWriter (output_stream);
358 errors += generator.Dump (context.Tree, output);
361 error ("Compilation failed");
364 notice ("Compilation successful");
371 error_count = errors;
376 if (output_file == null){
377 int pos = first_source.LastIndexOf (".");
379 output_file = first_source.Substring (0, pos) + target_ext;
382 context.CodeGen = new CodeGen (output_file, output_file);
385 // Before emitting, we need to get the core
386 // types emitted from the user defined types
387 // or from the system ones.
389 context.TypeManager.InitCoreTypes ();
391 context.TypeManager.AddModule (context.CodeGen.ModuleBuilder);
394 // The second pass of the compiler
396 context.ResolveTree ();
397 context.PopulateTypes ();
399 if (Report.Errors > 0){
400 error ("Compilation failed");
405 // The code generator
409 if (Report.Errors > 0){
410 error ("Compilation failed");
414 context.CloseTypes ();
416 PEFileKinds k = PEFileKinds.ConsoleApplication;
418 if (target == Target.Library || target == Target.Module)
420 else if (target == Target.Exe)
421 k = PEFileKinds.ConsoleApplication;
422 else if (target == Target.WinExe)
423 k = PEFileKinds.WindowApplication;
425 if (target == Target.Exe || target == Target.WinExe){
426 MethodInfo ep = context.EntryPoint;
429 Report.Error (5001, "Program " + output_file +
430 " does not have an entry point defined");
434 context.CodeGen.AssemblyBuilder.SetEntryPoint (ep, k);
437 context.CodeGen.Save (output_file);
439 if (Report.Errors > 0){
440 error ("Compilation failed");
442 } else if (Report.ProbeCode != 0){
443 error ("Failed to report code " + Report.ProbeCode);
444 Environment.Exit (124);