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.
26 Library, Exe, Module, WinExe
30 // Assemblies references to be linked. Initialized with
32 static ArrayList references;
35 static ArrayList link_paths;
37 static bool yacc_verbose = false;
39 static int error_count = 0;
41 static string first_source;
43 static Target target = Target.Exe;
44 static string target_ext = ".exe";
46 static bool parse_only = false;
48 static ArrayList defines;
50 static int parse (string input_file)
57 input = File.OpenRead (input_file);
59 Report.Error (2001, "Source file '" + input_file + "' could not be opened");
63 parser = new CSharpParser (input_file, input, defines);
64 parser.yacc_verbose = yacc_verbose;
66 errors = parser.parse ();
\r
67 } catch (Exception ex) {
68 Console.WriteLine (ex);
69 Console.WriteLine ("Compilation aborted");
76 static void Usage (bool is_error)
79 "Mono C# compiler, (C) 2001 Ximian, Inc.\n" +
80 "mcs [options] source-files\n" +
81 " --about About the Mono C# compiler\n" +
82 " --checked Set default context to checked\n" +
83 " --define SYM Defines the symbol SYM\n" +
84 " --fatal Makes errors fatal\n" +
85 " --stacktrace Shows stack trace at error location\n" +
86 " -L PATH Adds PATH to the assembly link path\n" +
87 " --nostdlib Does not load core libraries\n" +
88 " --nowarn XXX Ignores warning number XXX\n" +
89 " -o FNAME Specifies output file\n" +
90 " --optimize Optimizes\n" +
91 " --parse Only parses the source file\n" +
92 " --probe X L Probes for the source to generate code X on line L\n" +
93 " --target KIND Specifies the target (KIND is one of: exe, winexe, " +
94 "library, module)\n" +
95 " --unsafe Allows unsafe code\n" +
96 " --werror Treat warnings as errors\n" +
97 " --wlevel LEVEL Sets warning level (the highest is 4, the default)\n" +
98 " -r References an assembly\n" +
99 " -v Verbose parsing (for debugging the parser)\n" +
100 " @file Read response file for more options");
108 "The Mono C# compiler is (C) 2001 Ximian, Inc.\n\n" +
109 "The compiler source code is released under the terms of the GNU GPL\n\n" +
111 "For more information on Mono, visit the project Web site\n" +
112 " http://www.go-mono.com\n\n" +
114 "The compiler was written by Miguel de Icaza and Ravi Pratap");
117 static void error (string msg)
119 Console.WriteLine ("Error: " + msg);
122 static void notice (string msg)
124 Console.WriteLine (msg);
127 public static int Main (string[] args)
134 static public int LoadAssembly (string assembly)
137 string total_log = "";
140 a = Assembly.Load (assembly);
141 RootContext.TypeManager.AddAssembly (a);
143 } catch (FileNotFoundException){
144 foreach (string dir in link_paths){
145 string full_path = dir + "/" + assembly + ".dll";
148 a = Assembly.LoadFrom (full_path);
149 RootContext.TypeManager.AddAssembly (a);
151 } catch (FileNotFoundException ff) {
152 total_log += ff.FusionLog;
156 } catch (BadImageFormatException f) {
157 error ("// Bad file format while loading assembly");
158 error ("Log: " + f.FusionLog);
160 } catch (FileLoadException f){
161 error ("// File Load Exception: ");
162 error ("Log: " + f.FusionLog);
164 } catch (ArgumentNullException){
165 error ("// Argument Null exception ");
169 Report.Error (6, "Can not find assembly `" + assembly + "'" );
170 Console.WriteLine ("Log: \n" + total_log);
176 /// Loads all assemblies referenced on the command line
178 static public int LoadReferences ()
182 foreach (string r in references)
183 errors += LoadAssembly (r);
188 static void SetupDefaultDefines ()
190 defines = new ArrayList ();
191 defines.Add ("__MonoCS__");
194 static string [] LoadArgs (string file)
197 ArrayList args = new ArrayList ();
200 f = new StreamReader (file);
205 while ((line = f.ReadLine ()) != null){
206 string [] line_args = line.Split (new char [] { ' ' });
208 foreach (string arg in line_args)
212 string [] ret_value = new string [args.Count];
213 args.CopyTo (ret_value, 0);
219 /// Parses the arguments, and drives the compilation
224 /// TODO: Mostly structured to debug the compiler
225 /// now, needs to be turned into a real driver soon.
227 static void MainDriver (string [] args)
230 string output_file = null;
232 references = new ArrayList ();
233 link_paths = new ArrayList ();
235 SetupDefaultDefines ();
240 // This is not required because Assembly.Load knows about this
243 link_paths.Add ("file:///C:/WINNT/Microsoft.NET/Framework/v1.0.2914");
245 int argc = args.Length;
246 for (i = 0; i < argc; i++){
247 string arg = args [i];
249 if (arg.StartsWith ("@")){
250 string [] new_args, extra_args;
251 string response_file = arg.Substring (1);
253 extra_args = LoadArgs (response_file);
254 if (extra_args == null){
255 Report.Error (2011, "Unable to open response file: " +
260 new_args = new string [extra_args.Length + argc];
261 args.CopyTo (new_args, 0);
262 extra_args.CopyTo (new_args, argc);
264 argc = new_args.Length;
268 if (arg.StartsWith ("-")){
278 case "--main": case "-m":
279 if ((i + 1) >= argc){
283 RootContext.MainClass = args [++i];
287 RootContext.Unsafe = true;
291 RootContext.Optimize = true;
299 if ((i + 1) >= argc){
303 defines.Add (args [++i]);
309 code = Int32.Parse (args [++i], 0);
310 line = Int32.Parse (args [++i], 0);
311 Report.SetProbe (code, line);
315 case "-o": case "--output":
316 if ((i + 1) >= argc){
320 output_file = args [++i];
324 RootContext.Checked = true;
328 Report.Stacktrace = true;
332 if ((i + 1) >= argc){
337 string type = args [++i];
340 target = Target.Library;
349 target = Target.WinExe;
353 target = Target.Module;
360 if ((i + 1) >= argc){
365 references.Add (args [++i]);
369 if ((i + 1) >= argc){
373 link_paths.Add (args [++i]);
377 RootContext.StdLib = false;
385 Report.WarningsAreErrors = true;
389 if ((i + 1) >= argc){
396 warn = Int32.Parse (args [++i]);
401 Report.SetIgnoreWarning (warn);
405 if ((i + 1) >= argc){
413 level = Int32.Parse (args [++i]);
418 if (level < 0 || level > 4){
419 Report.Error (1900, "Warning level must be 0 to 4");
422 RootContext.WarningLevel = level;
435 if (first_source == null)
438 string [] files = Directory.GetFiles (".", arg);
439 foreach (string f in files){
440 if (!f.ToLower ().EndsWith (".cs")){
441 error ("Do not know how to compile " + arg);
449 if (first_source == null){
450 Report.Error (2008, "No files to compile were specified");
454 if (Report.Errors > 0)
461 // Load Core Library for default compilation
463 if (RootContext.StdLib){
464 references.Insert (0, "mscorlib");
465 references.Insert (1, "System");
469 error ("Parsing failed");
474 // Load assemblies required
476 errors += LoadReferences ();
479 error ("Could not load one or more assemblies");
483 error_count = errors;
488 if (output_file == null){
489 int pos = first_source.LastIndexOf (".");
491 output_file = first_source.Substring (0, pos) + target_ext;
494 RootContext.CodeGen = new CodeGen (output_file, output_file);
497 // Before emitting, we need to get the core
498 // types emitted from the user defined types
499 // or from the system ones.
501 RootContext.TypeManager.InitCoreTypes ();
503 RootContext.TypeManager.AddModule (RootContext.CodeGen.ModuleBuilder);
506 // The second pass of the compiler
508 RootContext.ResolveTree ();
509 RootContext.PopulateTypes ();
511 if (Report.Errors > 0){
512 error ("Compilation failed");
517 // The code generator
519 RootContext.EmitCode ();
521 if (Report.Errors > 0){
522 error ("Compilation failed");
526 RootContext.CloseTypes ();
528 PEFileKinds k = PEFileKinds.ConsoleApplication;
530 if (target == Target.Library || target == Target.Module)
532 else if (target == Target.Exe)
533 k = PEFileKinds.ConsoleApplication;
534 else if (target == Target.WinExe)
535 k = PEFileKinds.WindowApplication;
537 if (target == Target.Exe || target == Target.WinExe){
538 MethodInfo ep = RootContext.EntryPoint;
541 Report.Error (5001, "Program " + output_file +
542 " does not have an entry point defined");
546 RootContext.CodeGen.AssemblyBuilder.SetEntryPoint (ep, k);
549 RootContext.CodeGen.Save (output_file);
551 if (Report.Errors > 0){
552 error ("Compilation failed");
554 } else if (Report.ProbeCode != 0){
555 error ("Failed to report code " + Report.ProbeCode);
556 Environment.Exit (124);