Created
December 19, 2017 01:08
-
-
Save RedBeard0531/17c08ac262d8c4f62b130cee8dd50240 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# This is based on ninja's depfile_parser.in.cc | |
const | |
plain = {'a'..'z', 'A'..'Z', '0'..'9', '+', ',', '/', '_', ':', '.', '~', | |
'(', ')', '}', '{', '@', '=', '!', '-', '\x80'..'\xFF'} | |
escaped = {' ', '\\', '#', '*', '[', '|'} # \c -> c | |
notEscaped = {'\0', '\c', '\L'} # swallow the \ and handle c normally | |
type Deps* = object | |
output*: string | |
inputs*: seq[string] | |
proc parseDeps*(s: string): Deps = | |
result.inputs = @[] | |
var | |
haveColon = false | |
curStr = newStringOfCap(64) | |
i = 0 | |
while true: | |
let c = s[i] | |
inc i | |
case c | |
of plain: | |
let begin = i-1 | |
while s[i] in plain: inc i | |
curStr &= s[begin..<i] | |
of '\\': | |
if s[i] in escaped: | |
curStr &= s[i] | |
inc i | |
elif s[i] in notEscaped: | |
discard # swallow the '\' | |
else: | |
curStr &= c # Use the '\' as a normal char | |
# TODO consider normalizing to '/' here | |
of '$': | |
if s[i] == '$': | |
curStr &= c | |
inc i | |
else: | |
curStr.shallow | |
let isTarget = not haveColon | |
if curStr.len > 0 and curStr[^1] == ':': | |
if haveColon: | |
echo "Warning: ignoring last colon in '" & curStr & '\'' | |
curStr.setLen(curStr.len-1) | |
haveColon = true | |
if curStr.len == 0: | |
if c == '\0': break | |
continue | |
if isTarget: | |
if not result.output.isNil: | |
raise newException(Exception, "multiple outputs in depfile not supported") | |
result.output = curStr | |
else: | |
result.inputs &= curStr | |
if c == '\0': break | |
curStr = newStringOfCap(64) | |
if not haveColon: | |
raise newException(Exception, "no colon in deps file") | |
when isMainModule: | |
import sets | |
import os | |
var seen = initSet[string]() | |
let files = if paramCount() >= 1: commandLineParams() | |
else: @["status.os.d"] | |
for f in files: | |
let deps = f.readFile.parseDeps | |
for input in deps.inputs: | |
if not seen.containsOrIncl input: | |
if input.fileExists: | |
discard input.getLastModificationTime() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment