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
12
// Copyright 2011 Xamarin Inc
16
using System.Reflection;
17
using System.Reflection.Emit;
18
using System.Collections.Generic;
21
using System.Globalization;
22
using System.Diagnostics;
23
using System.Threading;
28
/// The compiler driver.
32
readonly CompilerContext ctx;
34
public Driver (CompilerContext ctx)
45
void tokenize_file (SourceFile sourceFile, ModuleContainer module, ParserSession session)
50
input = File.OpenRead (sourceFile.Name);
52
Report.Error (2001, "Source file `" + sourceFile.Name + "' could not be found");
57
SeekableStreamReader reader = new SeekableStreamReader (input, ctx.Settings.Encoding);
58
var file = new CompilationSourceFile (module, sourceFile);
60
Tokenizer lexer = new Tokenizer (reader, file, session);
61
int token, tokens = 0, errors = 0;
63
while ((token = lexer.token ()) != Token.EOF){
65
if (token == Token.ERROR)
68
Console.WriteLine ("Tokenized: " + tokens + " found " + errors + " errors");
74
void Parse (ModuleContainer module)
76
bool tokenize_only = module.Compiler.Settings.TokenizeOnly;
77
var sources = module.Compiler.SourceFiles;
79
Location.Initialize (sources);
81
var session = new ParserSession () {
82
UseJayGlobalArrays = true,
83
LocatedTokens = new Tokenizer.LocatedToken[15000]
86
for (int i = 0; i < sources.Count; ++i) {
88
tokenize_file (sources[i], module, session);
90
Parse (sources[i], module, session, Report);
96
void ParseParallel (ModuleContainer module)
98
var sources = module.Compiler.SourceFiles;
100
Location.Initialize (sources);
102
var pcount = Environment.ProcessorCount;
103
var threads = new Thread[System.Math.Max (2, pcount - 1)];
105
for (int i = 0; i < threads.Length; ++i) {
106
var t = new Thread (l => {
107
var session = new ParserSession () {
108
//UseJayGlobalArrays = true,
111
var report = new Report (ctx, Report.Printer); // TODO: Implement flush at once printer
113
for (int ii = (int) l; ii < sources.Count; ii += threads.Length) {
114
Parse (sources[ii], module, session, report);
117
// TODO: Merge warning regions
124
for (int t = 0; t < threads.Length; ++t) {
130
public void Parse (SourceFile file, ModuleContainer module, ParserSession session, Report report)
135
input = File.OpenRead (file.Name);
137
report.Error (2001, "Source file `{0}' could not be found", file.Name);
142
if (input.ReadByte () == 77 && input.ReadByte () == 90) {
144
report.Error (2015, "Source file `{0}' is a binary file and not a text file", file.Name);
150
SeekableStreamReader reader = new SeekableStreamReader (input, ctx.Settings.Encoding, session.StreamReaderBuffer);
152
Parse (reader, file, module, session, report);
154
if (ctx.Settings.GenerateDebugInfo && report.Errors == 0 && !file.HasChecksum) {
156
var checksum = session.GetChecksumAlgorithm ();
157
file.SetChecksum (checksum.ComputeHash (input));
164
public static CSharpParser Parse (SeekableStreamReader reader, SourceFile sourceFile, ModuleContainer module, ParserSession session, Report report, int lineModifier = 0, int colModifier = 0)
166
var file = new CompilationSourceFile (module, sourceFile);
167
module.AddTypeContainer(file);
169
CSharpParser parser = new CSharpParser (reader, file, report, session);
170
parser.Lexer.Line += lineModifier;
171
parser.Lexer.Column += colModifier;
172
parser.Lexer.sbag = new SpecialsBag ();
177
public static int Main (string[] args)
179
Location.InEmacs = Environment.GetEnvironmentVariable ("EMACS") == "t";
181
CommandLineParser cmd = new CommandLineParser (Console.Out);
182
var settings = cmd.ParseArguments (args);
183
if (settings == null)
186
if (cmd.HasBeenStopped)
189
Driver d = new Driver (new CompilerContext (settings, new ConsoleReportPrinter ()));
191
if (d.Compile () && d.Report.Errors == 0) {
192
if (d.Report.Warnings > 0) {
193
Console.WriteLine ("Compilation succeeded - {0} warning(s)", d.Report.Warnings);
195
Environment.Exit (0);
200
Console.WriteLine("Compilation failed: {0} error(s), {1} warnings",
201
d.Report.Errors, d.Report.Warnings);
202
Environment.Exit (1);
206
public static string GetPackageFlags (string packages, Report report)
208
ProcessStartInfo pi = new ProcessStartInfo ();
209
pi.FileName = "pkg-config";
210
pi.RedirectStandardOutput = true;
211
pi.UseShellExecute = false;
212
pi.Arguments = "--libs " + packages;
215
p = Process.Start (pi);
216
} catch (Exception e) {
220
report.Error (-27, "Couldn't run pkg-config: " + e.Message);
224
if (p.StandardOutput == null) {
226
throw new ApplicationException ("Specified package did not return any information");
228
report.Warning (-27, 1, "Specified package did not return any information");
233
string pkgout = p.StandardOutput.ReadToEnd ();
235
if (p.ExitCode != 0) {
237
throw new ApplicationException (pkgout);
239
report.Error (-27, "Error running pkg-config. Check the above output.");
249
// Main compilation method
251
public bool Compile ()
253
var settings = ctx.Settings;
256
// If we are an exe, require a source file for the entry point or
257
// if there is nothing to put in the assembly, and we are not a library
259
if (settings.FirstSourceFile == null &&
260
((settings.Target == Target.Exe || settings.Target == Target.WinExe || settings.Target == Target.Module) ||
261
settings.Resources == null)) {
262
Report.Error (2008, "No files to compile were specified");
266
if (settings.Platform == Platform.AnyCPU32Preferred && (settings.Target == Target.Library || settings.Target == Target.Module)) {
267
Report.Error (4023, "Platform option `anycpu32bitpreferred' is valid only for executables");
271
TimeReporter tr = new TimeReporter (settings.Timestamps);
272
ctx.TimeReporter = tr;
275
var module = new ModuleContainer (ctx);
276
RootContext.ToplevelTypes = module;
278
tr.Start (TimeReporter.TimerType.ParseTotal);
280
tr.Stop (TimeReporter.TimerType.ParseTotal);
282
if (Report.Errors > 0)
285
if (settings.TokenizeOnly || settings.ParseOnly) {
291
var output_file = settings.OutputFile;
292
string output_file_name;
293
if (output_file == null) {
294
var source_file = settings.FirstSourceFile;
296
if (source_file == null) {
297
Report.Error (1562, "If no source files are specified you must specify the output file with -out:");
301
output_file_name = source_file.Name;
302
int pos = output_file_name.LastIndexOf ('.');
305
output_file_name = output_file_name.Substring (0, pos);
307
output_file_name += settings.TargetExt;
308
output_file = output_file_name;
310
output_file_name = Path.GetFileName (output_file);
312
if (string.IsNullOrEmpty (Path.GetFileNameWithoutExtension (output_file_name)) ||
313
output_file_name.IndexOfAny (Path.GetInvalidFileNameChars ()) >= 0) {
314
Report.Error (2021, "Output file name is not valid");
320
var importer = new StaticImporter (module);
321
var references_loader = new StaticLoader (importer, ctx);
323
tr.Start (TimeReporter.TimerType.AssemblyBuilderSetup);
324
var assembly = new AssemblyDefinitionStatic (module, references_loader, output_file_name, output_file);
325
assembly.Create (references_loader.Domain);
326
tr.Stop (TimeReporter.TimerType.AssemblyBuilderSetup);
328
// Create compiler types first even before any referenced
329
// assembly is loaded to allow forward referenced types from
330
// loaded assembly into compiled builder to be resolved
332
tr.Start (TimeReporter.TimerType.CreateTypeTotal);
333
module.CreateContainer ();
334
importer.AddCompiledAssembly (assembly);
335
tr.Stop (TimeReporter.TimerType.CreateTypeTotal);
337
references_loader.LoadReferences (module);
339
tr.Start (TimeReporter.TimerType.PredefinedTypesInit);
340
if (!ctx.BuiltinTypes.CheckDefinitions (module))
343
tr.Stop (TimeReporter.TimerType.PredefinedTypesInit);
345
references_loader.LoadModules (assembly, module.GlobalRootNamespace);
347
var assembly = new AssemblyDefinitionDynamic (module, output_file_name, output_file);
348
module.SetDeclaringAssembly (assembly);
350
var importer = new ReflectionImporter (module, ctx.BuiltinTypes);
351
assembly.Importer = importer;
353
var loader = new DynamicLoader (importer, ctx);
354
loader.LoadReferences (module);
356
if (!ctx.BuiltinTypes.CheckDefinitions (module))
359
if (!assembly.Create (AppDomain.CurrentDomain, AssemblyBuilderAccess.Save))
362
module.CreateContainer ();
364
loader.LoadModules (assembly, module.GlobalRootNamespace);
366
module.InitializePredefinedTypes ();
368
tr.Start (TimeReporter.TimerType.ModuleDefinitionTotal);
370
tr.Stop (TimeReporter.TimerType.ModuleDefinitionTotal);
372
if (Report.Errors > 0)
375
if (settings.DocumentationFile != null) {
376
var doc = new DocumentationBuilder (module);
377
doc.OutputDocComment (output_file, settings.DocumentationFile);
382
if (Report.Errors > 0)
386
tr.Start (TimeReporter.TimerType.EmitTotal);
388
tr.Stop (TimeReporter.TimerType.EmitTotal);
390
if (Report.Errors > 0){
394
tr.Start (TimeReporter.TimerType.CloseTypes);
395
module.CloseContainer ();
396
tr.Stop (TimeReporter.TimerType.CloseTypes);
398
tr.Start (TimeReporter.TimerType.Resouces);
399
if (!settings.WriteMetadataOnly)
400
assembly.EmbedResources ();
401
tr.Stop (TimeReporter.TimerType.Resouces);
403
if (Report.Errors > 0)
409
references_loader.Dispose ();
414
return Report.Errors == 0;
418
public class CompilerCompilationUnit {
419
public ModuleContainer ModuleCompiled { get; set; }
420
public LocationsBag LocationsBag { get; set; }
421
public SpecialsBag SpecialsBag { get; set; }
422
public IEnumerable<string> Conditionals { get; set; }
423
public object LastYYValue { get; set; }
427
// This is the only public entry point
429
public class CompilerCallableEntryPoint : MarshalByRefObject
431
public static bool InvokeCompiler (string [] args, TextWriter error)
434
CommandLineParser cmd = new CommandLineParser (error);
435
var setting = cmd.ParseArguments (args);
439
var d = new Driver (new CompilerContext (setting, new StreamReportPrinter (error)));
446
public static int[] AllWarningNumbers {
448
return Report.AllWarnings;
452
public static void Reset ()
457
public static void PartialReset ()
462
public static void Reset (bool full_flag)
469
Linq.QueryBlock.TransparentParameter.Reset ();