Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/HeuristicLab.ExtLibs/HeuristicLab.NRefactory/5.5.0/NRefactory.CSharp-5.5.0/Parser/mcs/driver.cs @ 16240

Last change on this file since 16240 was 11700, checked in by jkarder, 10 years ago

#2077: created branch and added first version

File size: 12.2 KB
Line 
1//
2// driver.cs: The compiler command line driver.
3//
4// Authors:
5//   Miguel de Icaza (miguel@gnu.org)
6//   Marek Safar (marek.safar@gmail.com)
7//
8// Dual licensed under the terms of the MIT X11 or GNU GPL
9//
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
13//
14
15using System;
16using System.Reflection;
17using System.Reflection.Emit;
18using System.Collections.Generic;
19using System.IO;
20using System.Text;
21using System.Globalization;
22using System.Diagnostics;
23using System.Threading;
24
25namespace Mono.CSharp
26{
27  /// <summary>
28  ///    The compiler driver.
29  /// </summary>
30  class Driver
31  {
32    readonly CompilerContext ctx;
33
34    public Driver (CompilerContext ctx)
35    {
36      this.ctx = ctx;
37    }
38
39    Report Report {
40      get {
41        return ctx.Report;
42      }
43    }
44
45    void tokenize_file (SourceFile sourceFile, ModuleContainer module, ParserSession session)
46    {
47      Stream input;
48
49      try {
50        input = File.OpenRead (sourceFile.Name);
51      } catch {
52        Report.Error (2001, "Source file `" + sourceFile.Name + "' could not be found");
53        return;
54      }
55
56      using (input){
57        SeekableStreamReader reader = new SeekableStreamReader (input, ctx.Settings.Encoding);
58        var file = new CompilationSourceFile (module, sourceFile);
59
60        Tokenizer lexer = new Tokenizer (reader, file, session, ctx.Report);
61        int token, tokens = 0, errors = 0;
62
63        while ((token = lexer.token ()) != Token.EOF){
64          tokens++;
65          if (token == Token.ERROR)
66            errors++;
67        }
68        Console.WriteLine ("Tokenized: " + tokens + " found " + errors + " errors");
69      }
70     
71      return;
72    }
73
74    void Parse (ModuleContainer module)
75    {
76      bool tokenize_only = module.Compiler.Settings.TokenizeOnly;
77      var sources = module.Compiler.SourceFiles;
78
79      Location.Initialize (sources);
80
81      var session = new ParserSession {
82        UseJayGlobalArrays = true,
83        LocatedTokens = new LocatedToken[15000]
84      };
85
86      for (int i = 0; i < sources.Count; ++i) {
87        if (tokenize_only) {
88          tokenize_file (sources[i], module, session);
89        } else {
90          Parse (sources[i], module, session, Report);
91        }
92      }
93    }
94
95#if false
96    void ParseParallel (ModuleContainer module)
97    {
98      var sources = module.Compiler.SourceFiles;
99
100      Location.Initialize (sources);
101
102      var pcount = Environment.ProcessorCount;
103      var threads = new Thread[System.Math.Max (2, pcount - 1)];
104
105      for (int i = 0; i < threads.Length; ++i) {
106        var t = new Thread (l => {
107          var session = new ParserSession () {
108            //UseJayGlobalArrays = true,
109          };
110
111          var report = new Report (ctx, Report.Printer); // TODO: Implement flush at once printer
112
113          for (int ii = (int) l; ii < sources.Count; ii += threads.Length) {
114            Parse (sources[ii], module, session, report);
115          }
116
117          // TODO: Merge warning regions
118        });
119
120        t.Start (i);
121        threads[i] = t;
122      }
123
124      for (int t = 0; t < threads.Length; ++t) {
125        threads[t].Join ();
126      }
127    }
128#endif
129
130    public void Parse (SourceFile file, ModuleContainer module, ParserSession session, Report report)
131    {
132      Stream input;
133
134      try {
135        input = File.OpenRead (file.Name);
136      } catch {
137        report.Error (2001, "Source file `{0}' could not be found", file.Name);
138        return;
139      }
140
141      // Check 'MZ' header
142      if (input.ReadByte () == 77 && input.ReadByte () == 90) {
143
144        report.Error (2015, "Source file `{0}' is a binary file and not a text file", file.Name);
145        input.Close ();
146        return;
147      }
148
149      input.Position = 0;
150      SeekableStreamReader reader = new SeekableStreamReader (input, ctx.Settings.Encoding, session.StreamReaderBuffer);
151
152      Parse (reader, file, module, session, report);
153
154      if (ctx.Settings.GenerateDebugInfo && report.Errors == 0 && !file.HasChecksum) {
155        input.Position = 0;
156        var checksum = session.GetChecksumAlgorithm ();
157        file.SetChecksum (checksum.ComputeHash (input));
158      }
159
160      reader.Dispose ();
161      input.Close ();
162    }
163
164    public static CSharpParser Parse (SeekableStreamReader reader, SourceFile sourceFile, ModuleContainer module, ParserSession session, Report report, int lineModifier = 0, int colModifier = 0)
165    {
166      var file = new CompilationSourceFile (module, sourceFile);
167      module.AddTypeContainer(file);
168
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 ();
173      parser.parse ();
174      return parser;
175    }
176
177    public static int Main (string[] args)
178    {
179      Location.InEmacs = Environment.GetEnvironmentVariable ("EMACS") == "t";
180
181      CommandLineParser cmd = new CommandLineParser (Console.Out);
182      var settings = cmd.ParseArguments (args);
183      if (settings == null)
184        return 1;
185
186      if (cmd.HasBeenStopped)
187        return 0;
188
189      Driver d = new Driver (new CompilerContext (settings, new ConsoleReportPrinter ()));
190
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);
194        }
195        Environment.Exit (0);
196        return 0;
197      }
198     
199     
200      Console.WriteLine("Compilation failed: {0} error(s), {1} warnings",
201        d.Report.Errors, d.Report.Warnings);
202      Environment.Exit (1);
203      return 1;
204    }
205
206    public static string GetPackageFlags (string packages, Report report)
207    {
208      ProcessStartInfo pi = new ProcessStartInfo ();
209      pi.FileName = "pkg-config";
210      pi.RedirectStandardOutput = true;
211      pi.UseShellExecute = false;
212      pi.Arguments = "--libs " + packages;
213      Process p = null;
214      try {
215        p = Process.Start (pi);
216      } catch (Exception e) {
217        if (report == null)
218          throw;
219
220        report.Error (-27, "Couldn't run pkg-config: " + e.Message);
221        return null;
222      }
223     
224      if (p.StandardOutput == null) {
225        if (report == null)
226          throw new ApplicationException ("Specified package did not return any information");
227
228        report.Warning (-27, 1, "Specified package did not return any information");
229        p.Close ();
230        return null;
231      }
232
233      string pkgout = p.StandardOutput.ReadToEnd ();
234      p.WaitForExit ();
235      if (p.ExitCode != 0) {
236        if (report == null)
237          throw new ApplicationException (pkgout);
238
239        report.Error (-27, "Error running pkg-config. Check the above output.");
240        p.Close ();
241        return null;
242      }
243
244      p.Close ();
245      return pkgout;
246    }
247
248    //
249    // Main compilation method
250    //
251    public bool Compile ()
252    {
253      var settings = ctx.Settings;
254
255      //
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
258      //
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");
263        return false;
264      }
265
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");
268        return false;
269      }
270
271      TimeReporter tr = new TimeReporter (settings.Timestamps);
272      ctx.TimeReporter = tr;
273      tr.StartTotal ();
274
275      var module = new ModuleContainer (ctx);
276      RootContext.ToplevelTypes = module;
277
278      tr.Start (TimeReporter.TimerType.ParseTotal);
279      Parse (module);
280      tr.Stop (TimeReporter.TimerType.ParseTotal);
281
282      if (Report.Errors > 0)
283        return false;
284
285      if (settings.TokenizeOnly || settings.ParseOnly) {
286        tr.StopTotal ();
287        tr.ShowStats ();
288        return true;
289      }
290
291      var output_file = settings.OutputFile;
292      string output_file_name;
293      if (output_file == null) {
294        var source_file = settings.FirstSourceFile;
295
296        if (source_file == null) {
297          Report.Error (1562, "If no source files are specified you must specify the output file with -out:");
298          return false;
299        }
300
301        output_file_name = source_file.Name;
302        int pos = output_file_name.LastIndexOf ('.');
303
304        if (pos > 0)
305          output_file_name = output_file_name.Substring (0, pos);
306       
307        output_file_name += settings.TargetExt;
308        output_file = output_file_name;
309      } else {
310        output_file_name = Path.GetFileName (output_file);
311
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");
315          return false;
316        }
317      }
318
319#if STATIC
320      var importer = new StaticImporter (module);
321      var references_loader = new StaticLoader (importer, ctx);
322
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);
327
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
331      // correctly
332      tr.Start (TimeReporter.TimerType.CreateTypeTotal);
333      module.CreateContainer ();
334      importer.AddCompiledAssembly (assembly);
335      references_loader.CompiledAssembly = assembly;
336      tr.Stop (TimeReporter.TimerType.CreateTypeTotal);
337
338      references_loader.LoadReferences (module);
339
340      tr.Start (TimeReporter.TimerType.PredefinedTypesInit);
341      if (!ctx.BuiltinTypes.CheckDefinitions (module))
342        return false;
343
344      tr.Stop (TimeReporter.TimerType.PredefinedTypesInit);
345
346      references_loader.LoadModules (assembly, module.GlobalRootNamespace);
347#else
348      var assembly = new AssemblyDefinitionDynamic (module, output_file_name, output_file);
349      module.SetDeclaringAssembly (assembly);
350
351      var importer = new ReflectionImporter (module, ctx.BuiltinTypes);
352      assembly.Importer = importer;
353
354      var loader = new DynamicLoader (importer, ctx);
355      loader.LoadReferences (module);
356
357      if (!ctx.BuiltinTypes.CheckDefinitions (module))
358        return false;
359
360      if (!assembly.Create (AppDomain.CurrentDomain, AssemblyBuilderAccess.Save))
361        return false;
362
363      module.CreateContainer ();
364
365      loader.LoadModules (assembly, module.GlobalRootNamespace);
366#endif
367      module.InitializePredefinedTypes ();
368
369      tr.Start (TimeReporter.TimerType.ModuleDefinitionTotal);
370      module.Define ();
371      tr.Stop (TimeReporter.TimerType.ModuleDefinitionTotal);
372
373      if (Report.Errors > 0)
374        return false;
375
376      if (settings.DocumentationFile != null) {
377        var doc = new DocumentationBuilder (module);
378        doc.OutputDocComment (output_file, settings.DocumentationFile);
379      }
380
381      assembly.Resolve ();
382     
383      if (Report.Errors > 0)
384        return false;
385
386
387      tr.Start (TimeReporter.TimerType.EmitTotal);
388      assembly.Emit ();
389      tr.Stop (TimeReporter.TimerType.EmitTotal);
390
391      if (Report.Errors > 0){
392        return false;
393      }
394
395      tr.Start (TimeReporter.TimerType.CloseTypes);
396      module.CloseContainer ();
397      tr.Stop (TimeReporter.TimerType.CloseTypes);
398
399      tr.Start (TimeReporter.TimerType.Resouces);
400      if (!settings.WriteMetadataOnly)
401        assembly.EmbedResources ();
402      tr.Stop (TimeReporter.TimerType.Resouces);
403
404      if (Report.Errors > 0)
405        return false;
406
407      assembly.Save ();
408
409#if STATIC
410      references_loader.Dispose ();
411#endif
412      tr.StopTotal ();
413      tr.ShowStats ();
414
415      return Report.Errors == 0;
416    }
417  }
418
419  public class CompilerCompilationUnit {
420    public ModuleContainer ModuleCompiled { get; set; }
421    public LocationsBag LocationsBag { get; set; }
422    public SpecialsBag SpecialsBag { get; set; }
423    public IDictionary<string, bool> Conditionals { get; set; }
424    public object LastYYValue { get; set; }
425  }
426
427  //
428  // This is the only public entry point
429  //
430  public class CompilerCallableEntryPoint : MarshalByRefObject
431  {
432    public static bool InvokeCompiler (string [] args, TextWriter error)
433    {
434      try {
435        CommandLineParser cmd = new CommandLineParser (error);
436        var setting = cmd.ParseArguments (args);
437        if (setting == null)
438          return false;
439
440        var d = new Driver (new CompilerContext (setting, new StreamReportPrinter (error)));
441        return d.Compile ();
442      } finally {
443        Reset ();
444      }
445    }
446
447    public static int[] AllWarningNumbers {
448      get {
449        return Report.AllWarnings;
450      }
451    }
452
453    public static void Reset ()
454    {
455      Reset (true);
456    }
457
458    public static void PartialReset ()
459    {
460      Reset (false);
461    }
462   
463    public static void Reset (bool full_flag)
464    {
465      Location.Reset ();
466     
467      if (!full_flag)
468        return;
469
470      Linq.QueryBlock.TransparentParameter.Reset ();
471      TypeInfo.Reset ();
472    }
473  }
474 
475}
Note: See TracBrowser for help on using the repository browser.