| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| using System; |
| using System.Collections.Generic; |
| using System.Linq; |
| using System.Text; |
| |
| using System.IO; |
| |
| namespace NaCl.Build.CPPTasks |
| { |
| /// <summary> |
| /// Parser for the dependancy files generated by gcc (.d files). |
| /// This is not a general purpose .d file parser. In particular it |
| /// assumes exactly one dependancy per line. |
| /// </summary> |
| public class DependencyParser |
| { |
| private List<string> m_dependencies = new List<string>(); |
| |
| public List<String> Dependencies |
| { |
| get |
| { |
| return m_dependencies; |
| } |
| } |
| |
| public DependencyParser() |
| { |
| } |
| |
| public DependencyParser(string filename) |
| { |
| using (StreamReader reader = new StreamReader(filename, Encoding.ASCII)) |
| { |
| Parse(reader); |
| } |
| } |
| |
| public void Parse(string content) |
| { |
| Parse(new StringReader(content)); |
| } |
| |
| public void Parse(TextReader reader) |
| { |
| while (true) |
| { |
| string str = reader.ReadLine(); |
| if (str == null) |
| break; |
| ParseLine(str); |
| } |
| reader.Close(); |
| } |
| |
| private void AddDependency(string filename) |
| { |
| filename = GCCUtilities.ConvertPathPosixToWindows(filename); |
| filename = filename.Replace("\\ ", " "); |
| m_dependencies.Add(filename); |
| } |
| |
| /// <summary> |
| /// Find the end of the current filename on the given line from a dependancy file. |
| /// Normally this is the space char but, spaces can be escaped with backslash and |
| /// end of string could also terminate the filename. |
| /// </summary> |
| private static int FindEndOfFilename(string line) |
| { |
| bool escapeSpace = false; |
| int i = 0; |
| for (i = 0; i < line.Length; i++) |
| { |
| if (line.ElementAt(i) == '\\') |
| { |
| escapeSpace = true; |
| } |
| else if (line.ElementAt(i) == ' ' && !escapeSpace) |
| { |
| // we found an unescaped space which represents the |
| // end of the current filename. |
| break; |
| } |
| else if (escapeSpace) |
| { |
| escapeSpace = false; |
| } |
| } |
| return i; |
| } |
| |
| /// <summary> |
| /// Parse a single line from a dependancy file. |
| /// </summary> |
| private void ParseLine(string line) |
| { |
| // Strip any trailing line continuation character. Most lines of a gcc |
| // generated .d files end with this char |
| if (line.ElementAt(line.Length - 1) == '\\') |
| line = line.Substring(0, line.Length - 1); |
| |
| if (m_dependencies.Count == 0) |
| { |
| // The first line of the .d files is <target>: <first_dep>. |
| // For this line we want to strip the <target>: part. |
| line = line.Split(new[] { ':' }, 2)[1]; |
| } |
| |
| // trim trailing whitespace |
| line = line.Trim(); |
| |
| // Now iterate through the line which can contain zero or more dependencies. |
| // Although they are seperated by spaces we can't use Split() here since filenames |
| // can also contain spaces that are escaped using backslash. For some reason only |
| // spaces are escaped. Even literal backslash chars don't need escaping. |
| while (line.Length != 0) |
| { |
| int end = FindEndOfFilename(line); |
| AddDependency(line.Substring(0, end)); |
| if (end == line.Length) |
| break; |
| line = line.Substring(end + 1).Trim(); |
| } |
| } |
| } |
| } |