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 (CompilationSourceFile 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 (module.Compiler.SourceFiles);
74
bool tokenize_only = module.Compiler.Settings.TokenizeOnly;
75
var sources = module.Compiler.SourceFiles;
76
for (int i = 0; i < sources.Count; ++i) {
78
tokenize_file (sources[i]);
80
Parse (sources[i], module);
85
public void Parse (CompilationSourceFile 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, CompilationSourceFile file, ModuleContainer module)
113
file.NamespaceContainer = new NamespaceContainer (null, module, null, file);
115
CSharpParser parser = new CSharpParser (reader, file);
119
public static int Main (string[] args)
121
Location.InEmacs = Environment.GetEnvironmentVariable ("EMACS") == "t";
123
var r = new Report (new ConsoleReportPrinter ());
124
CommandLineParser cmd = new CommandLineParser (r);
125
var settings = cmd.ParseArguments (args);
126
if (settings == null || r.Errors > 0)
129
if (cmd.HasBeenStopped)
132
Driver d = new Driver (new CompilerContext (settings, r));
134
if (d.Compile () && d.Report.Errors == 0) {
135
if (d.Report.Warnings > 0) {
136
Console.WriteLine ("Compilation succeeded - {0} warning(s)", d.Report.Warnings);
138
Environment.Exit (0);
143
Console.WriteLine("Compilation failed: {0} error(s), {1} warnings",
144
d.Report.Errors, d.Report.Warnings);
145
Environment.Exit (1);
149
public static string GetPackageFlags (string packages, Report report)
151
ProcessStartInfo pi = new ProcessStartInfo ();
152
pi.FileName = "pkg-config";
153
pi.RedirectStandardOutput = true;
154
pi.UseShellExecute = false;
155
pi.Arguments = "--libs " + packages;
158
p = Process.Start (pi);
159
} catch (Exception e) {
163
report.Error (-27, "Couldn't run pkg-config: " + e.Message);
167
if (p.StandardOutput == null) {
169
throw new ApplicationException ("Specified package did not return any information");
171
report.Warning (-27, 1, "Specified package did not return any information");
176
string pkgout = p.StandardOutput.ReadToEnd ();
178
if (p.ExitCode != 0) {
180
throw new ApplicationException (pkgout);
182
report.Error (-27, "Error running pkg-config. Check the above output.");
192
// Main compilation method
194
public bool Compile ()
196
var settings = ctx.Settings;
199
// If we are an exe, require a source file for the entry point or
200
// if there is nothing to put in the assembly, and we are not a library
202
if (settings.FirstSourceFile == null &&
203
((settings.Target == Target.Exe || settings.Target == Target.WinExe || settings.Target == Target.Module) ||
204
settings.Resources == null)) {
205
Report.Error (2008, "No files to compile were specified");
209
TimeReporter tr = new TimeReporter (settings.Timestamps);
210
ctx.TimeReporter = tr;
213
var module = new ModuleContainer (ctx);
214
RootContext.ToplevelTypes = module;
216
tr.Start (TimeReporter.TimerType.ParseTotal);
218
tr.Stop (TimeReporter.TimerType.ParseTotal);
220
if (Report.Errors > 0)
223
if (settings.TokenizeOnly || settings.ParseOnly) {
229
var output_file = settings.OutputFile;
230
string output_file_name;
231
if (output_file == null) {
232
var source_file = settings.FirstSourceFile;
234
if (source_file == null) {
235
Report.Error (1562, "If no source files are specified you must specify the output file with -out:");
239
output_file_name = source_file.Name;
240
int pos = output_file_name.LastIndexOf ('.');
243
output_file_name = output_file_name.Substring (0, pos);
245
output_file_name += settings.TargetExt;
246
output_file = output_file_name;
248
output_file_name = Path.GetFileName (output_file);
252
var importer = new StaticImporter (module);
253
var references_loader = new StaticLoader (importer, ctx);
255
tr.Start (TimeReporter.TimerType.AssemblyBuilderSetup);
256
var assembly = new AssemblyDefinitionStatic (module, references_loader, output_file_name, output_file);
257
assembly.Create (references_loader.Domain);
258
tr.Stop (TimeReporter.TimerType.AssemblyBuilderSetup);
260
// Create compiler types first even before any referenced
261
// assembly is loaded to allow forward referenced types from
262
// loaded assembly into compiled builder to be resolved
264
tr.Start (TimeReporter.TimerType.CreateTypeTotal);
265
module.CreateType ();
266
importer.AddCompiledAssembly (assembly);
267
tr.Stop (TimeReporter.TimerType.CreateTypeTotal);
269
references_loader.LoadReferences (module);
271
tr.Start (TimeReporter.TimerType.PredefinedTypesInit);
272
if (!ctx.BuiltinTypes.CheckDefinitions (module))
275
tr.Stop (TimeReporter.TimerType.PredefinedTypesInit);
277
references_loader.LoadModules (assembly, module.GlobalRootNamespace);
279
var assembly = new AssemblyDefinitionDynamic (module, output_file_name, output_file);
280
module.SetDeclaringAssembly (assembly);
282
var importer = new ReflectionImporter (module, ctx.BuiltinTypes);
283
assembly.Importer = importer;
285
var loader = new DynamicLoader (importer, ctx);
286
loader.LoadReferences (module);
288
if (!ctx.BuiltinTypes.CheckDefinitions (module))
291
if (!assembly.Create (AppDomain.CurrentDomain, AssemblyBuilderAccess.Save))
294
module.CreateType ();
296
loader.LoadModules (assembly, module.GlobalRootNamespace);
298
module.InitializePredefinedTypes ();
300
tr.Start (TimeReporter.TimerType.UsingResolve);
301
foreach (var source_file in ctx.SourceFiles) {
302
source_file.NamespaceContainer.Resolve ();
304
tr.Stop (TimeReporter.TimerType.UsingResolve);
306
tr.Start (TimeReporter.TimerType.ModuleDefinitionTotal);
308
tr.Stop (TimeReporter.TimerType.ModuleDefinitionTotal);
310
if (Report.Errors > 0)
313
if (settings.DocumentationFile != null) {
314
var doc = new DocumentationBuilder (module);
315
doc.OutputDocComment (output_file, settings.DocumentationFile);
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;
355
public class CompilerCompilationUnit {
356
public ModuleContainer ModuleCompiled { get; set; }
357
public LocationsBag LocationsBag { get; set; }
358
public UsingsBag UsingsBag { get; set; }
359
public SpecialsBag SpecialsBag { get; set; }
363
// This is the only public entry point
365
public class CompilerCallableEntryPoint : MarshalByRefObject {
367
public static bool InvokeCompiler (string [] args, TextWriter error)
370
var r = new Report (new StreamReportPrinter (error));
371
CommandLineParser cmd = new CommandLineParser (r, error);
372
var setting = cmd.ParseArguments (args);
373
if (setting == null || r.Errors > 0)
376
var d = new Driver (new CompilerContext (setting, r));
383
public static int[] AllWarningNumbers {
385
return Report.AllWarnings;
389
public static void Reset ()
394
public static void PartialReset ()
399
public static void Reset (bool full_flag)
401
CSharpParser.yacc_verbose_flag = 0;
407
AnonymousTypeClass.Reset ();
408
AnonymousMethodBody.Reset ();
409
AnonymousMethodStorey.Reset ();
410
SymbolWriter.Reset ();
412
Linq.QueryBlock.TransparentParameter.Reset ();
416
public static CompilerCompilationUnit ParseFile (string[] args, Stream input, string inputFile, TextWriter reportStream)
418
return ParseFile (args, input, inputFile, new StreamReportPrinter (reportStream));
421
internal static object parseLock = new object ();
423
public static CompilerCompilationUnit ParseFile (string[] args, Stream input, string inputFile, ReportPrinter reportPrinter)
427
// Driver d = Driver.Create (args, false, null, reportPrinter);
431
var r = new Report (reportPrinter);
432
CommandLineParser cmd = new CommandLineParser (r, Console.Out);
433
var setting = cmd.ParseArguments (args);
434
if (setting == null || r.Errors > 0)
437
CompilerContext ctx = new CompilerContext (setting, r);
439
var files = new List<CompilationSourceFile> ();
440
var unit = new CompilationSourceFile (inputFile, inputFile, 0);
441
var module = new ModuleContainer (ctx);
442
unit.NamespaceContainer = new NamespaceContainer (null, module, null, unit);
444
Location.Initialize (files);
446
// TODO: encoding from driver
447
SeekableStreamReader reader = new SeekableStreamReader (input, Encoding.Default);
449
RootContext.ToplevelTypes = module;
451
CSharpParser parser = new CSharpParser (reader, unit);
452
parser.Lexer.TabSize = 1;
453
parser.Lexer.sbag = new SpecialsBag ();
454
parser.LocationsBag = new LocationsBag ();
455
parser.UsingsBag = new UsingsBag ();
458
return new CompilerCompilationUnit () { ModuleCompiled = RootContext.ToplevelTypes, LocationsBag = parser.LocationsBag, UsingsBag = parser.UsingsBag, SpecialsBag = parser.Lexer.sbag };