2 // driver.cs: The compiler command line driver.
5 // Miguel de Icaza (miguel@gnu.org)
6 // Marek Safar (marek.safar@gmail.com)
8 // Dual licensed under the terms of the MIT X11 or GNU GPL
10 // Copyright 2001, 2002, 2003 Ximian, Inc (http://www.ximian.com)
11 // Copyright 2004, 2005, 2006, 2007, 2008 Novell, Inc
15 using System.Reflection;
16 using System.Reflection.Emit;
17 using System.Collections.Generic;
20 using System.Globalization;
21 using System.Diagnostics;
26 /// The compiler driver.
30 readonly CompilerContext ctx;
32 public Driver (CompilerContext ctx)
43 void tokenize_file (CompilationUnit file)
48 input = File.OpenRead (file.Name);
50 Report.Error (2001, "Source file `" + file.Name + "' could not be found");
55 SeekableStreamReader reader = new SeekableStreamReader (input, ctx.Settings.Encoding);
56 Tokenizer lexer = new Tokenizer (reader, file, ctx);
57 int token, tokens = 0, errors = 0;
59 while ((token = lexer.token ()) != Token.EOF){
61 if (token == Token.ERROR)
64 Console.WriteLine ("Tokenized: " + tokens + " found " + errors + " errors");
70 void Parse (ModuleContainer module)
72 Location.Initialize ();
74 bool tokenize_only = ctx.Settings.TokenizeOnly;
75 var cu = Location.SourceFiles;
76 for (int i = 0; i < cu.Count; ++i) {
78 tokenize_file (cu[i]);
80 Parse (cu[i], module);
85 void Parse (CompilationUnit file, ModuleContainer module)
90 input = File.OpenRead (file.Name);
92 Report.Error (2001, "Source file `{0}' could not be found", file.Name);
97 if (input.ReadByte () == 77 && input.ReadByte () == 90) {
98 Report.Error (2015, "Source file `{0}' is a binary file and not a text file", file.Name);
104 SeekableStreamReader reader = new SeekableStreamReader (input, ctx.Settings.Encoding);
106 Parse (reader, file, module);
111 public void Parse (SeekableStreamReader reader, CompilationUnit file, ModuleContainer module)
113 CSharpParser parser = new CSharpParser (reader, file, module);
117 public static int Main (string[] args)
119 Location.InEmacs = Environment.GetEnvironmentVariable ("EMACS") == "t";
121 var r = new Report (new ConsoleReportPrinter ());
122 CommandLineParser cmd = new CommandLineParser (r);
123 var settings = cmd.ParseArguments (args);
124 if (settings == null || r.Errors > 0)
127 if (cmd.HasBeenStopped)
130 Driver d = new Driver (new CompilerContext (settings, r));
132 if (d.Compile () && d.Report.Errors == 0) {
133 if (d.Report.Warnings > 0) {
134 Console.WriteLine ("Compilation succeeded - {0} warning(s)", d.Report.Warnings);
136 Environment.Exit (0);
141 Console.WriteLine("Compilation failed: {0} error(s), {1} warnings",
142 d.Report.Errors, d.Report.Warnings);
143 Environment.Exit (1);
147 public static string GetPackageFlags (string packages, Report report)
149 ProcessStartInfo pi = new ProcessStartInfo ();
150 pi.FileName = "pkg-config";
151 pi.RedirectStandardOutput = true;
152 pi.UseShellExecute = false;
153 pi.Arguments = "--libs " + packages;
156 p = Process.Start (pi);
157 } catch (Exception e) {
161 report.Error (-27, "Couldn't run pkg-config: " + e.Message);
165 if (p.StandardOutput == null) {
167 throw new ApplicationException ("Specified package did not return any information");
169 report.Warning (-27, 1, "Specified package did not return any information");
174 string pkgout = p.StandardOutput.ReadToEnd ();
176 if (p.ExitCode != 0) {
178 throw new ApplicationException (pkgout);
180 report.Error (-27, "Error running pkg-config. Check the above output.");
190 // Main compilation method
192 public bool Compile ()
194 var settings = ctx.Settings;
197 // If we are an exe, require a source file for the entry point or
198 // if there is nothing to put in the assembly, and we are not a library
200 if (Location.FirstFile == null &&
201 ((settings.Target == Target.Exe || settings.Target == Target.WinExe || settings.Target == Target.Module) ||
202 settings.Resources == null)) {
203 Report.Error (2008, "No files to compile were specified");
207 TimeReporter tr = new TimeReporter (settings.Timestamps);
208 ctx.TimeReporter = tr;
211 var module = new ModuleContainer (ctx);
212 RootContext.ToplevelTypes = module;
214 tr.Start (TimeReporter.TimerType.ParseTotal);
216 tr.Stop (TimeReporter.TimerType.ParseTotal);
218 if (Report.Errors > 0)
221 if (settings.TokenizeOnly || settings.ParseOnly)
224 if (RootContext.ToplevelTypes.NamespaceEntry != null)
225 throw new InternalErrorException ("who set it?");
227 var output_file = settings.OutputFile;
228 string output_file_name;
229 if (output_file == null) {
230 output_file_name = Location.FirstFile;
232 if (output_file_name == null) {
233 Report.Error (1562, "If no source files are specified you must specify the output file with -out:");
237 int pos = output_file_name.LastIndexOf ('.');
240 output_file_name = output_file_name.Substring (0, pos);
242 output_file_name += settings.TargetExt;
243 output_file = output_file_name;
245 output_file_name = Path.GetFileName (output_file);
249 var importer = new StaticImporter (module);
250 var references_loader = new StaticLoader (importer, ctx);
252 tr.Start (TimeReporter.TimerType.AssemblyBuilderSetup);
253 var assembly = new AssemblyDefinitionStatic (module, references_loader, output_file_name, output_file);
254 assembly.Create (references_loader.Domain);
255 tr.Stop (TimeReporter.TimerType.AssemblyBuilderSetup);
257 // Create compiler types first even before any referenced
258 // assembly is loaded to allow forward referenced types from
259 // loaded assembly into compiled builder to be resolved
261 tr.Start (TimeReporter.TimerType.CreateTypeTotal);
262 module.CreateType ();
263 importer.AddCompiledAssembly (assembly);
264 tr.Stop (TimeReporter.TimerType.CreateTypeTotal);
266 references_loader.LoadReferences (module);
268 tr.Start (TimeReporter.TimerType.PredefinedTypesInit);
269 if (!ctx.BuildinTypes.CheckDefinitions (module))
272 tr.Stop (TimeReporter.TimerType.PredefinedTypesInit);
274 references_loader.LoadModules (assembly, module.GlobalRootNamespace);
276 var assembly = new AssemblyDefinitionDynamic (module, output_file_name, output_file);
277 module.SetDeclaringAssembly (assembly);
279 var importer = new ReflectionImporter (module, ctx.BuildinTypes);
280 assembly.Importer = importer;
282 var loader = new DynamicLoader (importer, ctx);
283 loader.LoadReferences (module);
285 if (!ctx.BuildinTypes.CheckDefinitions (module))
288 if (!assembly.Create (AppDomain.CurrentDomain, AssemblyBuilderAccess.Save))
291 module.CreateType ();
293 loader.LoadModules (assembly, module.GlobalRootNamespace);
295 tr.Start (TimeReporter.TimerType.ModuleDefinitionTotal);
297 tr.Stop (TimeReporter.TimerType.ModuleDefinitionTotal);
299 if (Report.Errors > 0)
302 if (settings.Documentation != null &&
303 !settings.Documentation.OutputDocComment (
304 output_file, Report))
308 // Verify using aliases now
310 tr.Start (TimeReporter.TimerType.UsingVerification);
311 NamespaceEntry.VerifyAllUsing ();
312 tr.Stop (TimeReporter.TimerType.UsingVerification);
314 if (Report.Errors > 0){
320 if (Report.Errors > 0)
324 tr.Start (TimeReporter.TimerType.EmitTotal);
326 tr.Stop (TimeReporter.TimerType.EmitTotal);
328 if (Report.Errors > 0){
332 tr.Start (TimeReporter.TimerType.CloseTypes);
334 tr.Stop (TimeReporter.TimerType.CloseTypes);
336 tr.Start (TimeReporter.TimerType.Resouces);
337 assembly.EmbedResources ();
338 tr.Stop (TimeReporter.TimerType.Resouces);
340 if (Report.Errors > 0)
346 references_loader.Dispose ();
351 return Report.Errors == 0;
356 // This is the only public entry point
358 public class CompilerCallableEntryPoint : MarshalByRefObject {
359 public static bool InvokeCompiler (string [] args, TextWriter error)
362 var r = new Report (new StreamReportPrinter (error));
363 CommandLineParser cmd = new CommandLineParser (r, error);
364 var setting = cmd.ParseArguments (args);
365 if (setting == null || r.Errors > 0)
368 var d = new Driver (new CompilerContext (setting, r));
375 public static int[] AllWarningNumbers {
377 return Report.AllWarnings;
381 public static void Reset ()
386 public static void PartialReset ()
391 public static void Reset (bool full_flag)
393 CSharpParser.yacc_verbose_flag = 0;
399 RootContext.Reset (full_flag);
400 TypeManager.Reset ();
401 ReferenceContainer.Reset ();
402 PointerContainer.Reset ();
405 CastFromDecimal.Reset ();
406 StringConcat.Reset ();
408 NamespaceEntry.Reset ();
410 AnonymousTypeClass.Reset ();
411 AnonymousMethodBody.Reset ();
412 AnonymousMethodStorey.Reset ();
413 SymbolWriter.Reset ();
415 Linq.QueryBlock.TransparentParameter.Reset ();