mirror of
https://github.com/asmjit/asmjit.git
synced 2025-12-17 20:44:37 +03:00
Initial.
This commit is contained in:
424
tools/autoexp-patch.py
Normal file
424
tools/autoexp-patch.py
Normal file
@@ -0,0 +1,424 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import os
|
||||
|
||||
AUTOEXP_FILES = [
|
||||
# Visual Studio 8.0 (2005).
|
||||
"C:\\Program Files\\Microsoft Visual Studio 8\\Common7\\Packages\\Debugger\\autoexp.dat",
|
||||
"C:\\Program Files (x86)\\Microsoft Visual Studio 8\\Common7\\Packages\\Debugger\\autoexp.dat",
|
||||
|
||||
# Visual Studio 9.0 (2008).
|
||||
"C:\\Program Files\\Microsoft Visual Studio 9.0\\Common7\\Packages\\Debugger\\autoexp.dat",
|
||||
"C:\\Program Files (x86)\\Microsoft Visual Studio 9.0\\Common7\\Packages\\Debugger\\autoexp.dat",
|
||||
|
||||
# Visual Studio 10.0 (2010).
|
||||
"C:\\Program Files\\Microsoft Visual Studio 10.0\\Common7\\Packages\\Debugger\\autoexp.dat",
|
||||
"C:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\Common7\\Packages\\Debugger\\autoexp.dat"
|
||||
]
|
||||
|
||||
DIRECTIVE_SYMBOL = '@'
|
||||
|
||||
# =============================================================================
|
||||
# [Log]
|
||||
# =============================================================================
|
||||
|
||||
def log(str):
|
||||
print(str)
|
||||
|
||||
# =============================================================================
|
||||
# [Is...]
|
||||
# =============================================================================
|
||||
|
||||
def isDirective(c):
|
||||
return c == DIRECTIVE_SYMBOL
|
||||
|
||||
def isAlpha(c):
|
||||
c = ord(c)
|
||||
return (c >= ord('a') and c <= ord('z')) or (c >= ord('A') and c <= ord('Z'))
|
||||
|
||||
def isAlpha_(c):
|
||||
return isAlpha(c) or (c == '_')
|
||||
|
||||
def isNumber(c):
|
||||
c = ord(c)
|
||||
return (c >= ord('0')) and (c <= ord('9'))
|
||||
|
||||
def isAlnum(c):
|
||||
return isAlpha(c) or isNumber(c)
|
||||
|
||||
def isAlnum_(c):
|
||||
return isAlnum(c) or (c == '_')
|
||||
|
||||
def isSpace(c):
|
||||
return (c == ' ') or (c == '\t')
|
||||
|
||||
def isNewLine(c):
|
||||
return c == '\n'
|
||||
|
||||
# =============================================================================
|
||||
# [SyntaxError]
|
||||
# =============================================================================
|
||||
|
||||
class SyntaxError(Exception):
|
||||
def __init__(self, msg):
|
||||
self.msg = msg
|
||||
|
||||
def __str__(self):
|
||||
return repr(self.msg)
|
||||
|
||||
# =============================================================================
|
||||
# [Context]
|
||||
# =============================================================================
|
||||
|
||||
class Context(object):
|
||||
def __init__(self, data):
|
||||
self.data = data
|
||||
self.index = 0
|
||||
self.size = len(data)
|
||||
|
||||
def isNewLine(self):
|
||||
if self.index == 0:
|
||||
return True
|
||||
else:
|
||||
return self.data[self.index - 1] == '\n'
|
||||
|
||||
def isEnd(self):
|
||||
return self.index >= self.size
|
||||
|
||||
def getChar(self):
|
||||
if self.index >= self.size:
|
||||
return '\0'
|
||||
return self.data[self.index]
|
||||
|
||||
def advance(self):
|
||||
if self.index < self.size:
|
||||
self.index += 1
|
||||
|
||||
def parseUntilTrue(self, func, advance):
|
||||
while not self.isEnd():
|
||||
c = self.data[self.index]
|
||||
if func(c):
|
||||
self.index += 1
|
||||
continue
|
||||
if advance:
|
||||
self.index += 1
|
||||
return True
|
||||
return False
|
||||
|
||||
def parseUntilFalse(self, func, advance):
|
||||
while not self.isEnd():
|
||||
c = self.data[self.index]
|
||||
if not func(c):
|
||||
self.index += 1
|
||||
continue
|
||||
if advance:
|
||||
self.index += 1
|
||||
return True
|
||||
return False
|
||||
|
||||
def skipString(self):
|
||||
def func(c):
|
||||
return c == '"'
|
||||
return self.parseUntilFalse(func, True)
|
||||
|
||||
def skipSpaces(self):
|
||||
return self.parseUntilTrue(isSpace, False)
|
||||
|
||||
def skipLine(self):
|
||||
return self.parseUntilFalse(isNewLine, True)
|
||||
|
||||
def parseDirective(self, index):
|
||||
start = index
|
||||
|
||||
data = self.data
|
||||
size = self.size
|
||||
|
||||
c = data[index]
|
||||
assert isAlpha_(c)
|
||||
|
||||
while True:
|
||||
index += 1
|
||||
if index >= size:
|
||||
break
|
||||
c = data[index]
|
||||
if isAlnum_(c):
|
||||
continue
|
||||
break
|
||||
|
||||
self.index = index
|
||||
return data[start:index]
|
||||
|
||||
def parseSymbol(self, index):
|
||||
start = index
|
||||
|
||||
data = self.data
|
||||
size = self.size
|
||||
|
||||
c = data[index]
|
||||
assert isAlpha_(c)
|
||||
|
||||
while True:
|
||||
index += 1
|
||||
if index >= size:
|
||||
return data[start:index]
|
||||
c = data[index]
|
||||
if isAlnum_(c):
|
||||
continue
|
||||
if c == ':' and index + 2 < size and data[index + 1] == ':' and isAlpha_(data[index + 2]):
|
||||
index += 2
|
||||
continue
|
||||
|
||||
self.index = index
|
||||
return data[start:index]
|
||||
|
||||
def parseMacro(self, index):
|
||||
start = index
|
||||
end = None
|
||||
|
||||
data = self.data
|
||||
size = self.size
|
||||
|
||||
if index >= size:
|
||||
return ""
|
||||
|
||||
while True:
|
||||
c = data[index]
|
||||
index += 1
|
||||
|
||||
if c == '\n' or index >= size:
|
||||
if end == None:
|
||||
end = index - 1
|
||||
break
|
||||
|
||||
if c == ';':
|
||||
if end == None:
|
||||
end = index
|
||||
|
||||
while start < end and isSpace(data[end - 1]):
|
||||
end -= 1
|
||||
|
||||
self.index = index
|
||||
return data[start:end]
|
||||
|
||||
def replaceRange(self, start, end, content):
|
||||
old = self.data
|
||||
|
||||
self.data = old[0:start] + content + old[end:]
|
||||
self.size = len(self.data)
|
||||
|
||||
assert(self.index >= end)
|
||||
|
||||
self.index -= end - start
|
||||
self.index += len(content)
|
||||
|
||||
# =============================================================================
|
||||
# [AutoExpDat]
|
||||
# =============================================================================
|
||||
|
||||
class AutoExpDat(object):
|
||||
def __init__(self, data):
|
||||
self.library = None
|
||||
self.symbols = {}
|
||||
self.data = self.process(data.replace('\r', ''))
|
||||
|
||||
def process(self, data):
|
||||
ctx = Context(data)
|
||||
|
||||
while not ctx.isEnd():
|
||||
c = ctx.getChar()
|
||||
|
||||
# Skip comments.
|
||||
if c == ';':
|
||||
ctx.skipLine()
|
||||
continue
|
||||
|
||||
# Skip strings.
|
||||
if c == '"':
|
||||
ctx.advance()
|
||||
ctx.skipString()
|
||||
continue
|
||||
|
||||
# Skip numbers.
|
||||
if isNumber(c):
|
||||
ctx.parseUntilTrue(isAlnum_, True)
|
||||
continue
|
||||
|
||||
# Parse directives.
|
||||
if isDirective(c) and ctx.isNewLine():
|
||||
start = ctx.index
|
||||
|
||||
ctx.advance()
|
||||
c = ctx.getChar()
|
||||
|
||||
# Remove lines that have '@' followed by space or newline.
|
||||
if isNewLine(c) or c == '\0':
|
||||
ctx.advance()
|
||||
ctx.replaceRange(start, ctx.index, "")
|
||||
continue
|
||||
if isSpace(c):
|
||||
ctx.skipLine()
|
||||
ctx.replaceRange(start, ctx.index, "")
|
||||
continue
|
||||
|
||||
directive = ctx.parseDirective(ctx.index)
|
||||
|
||||
c = ctx.getChar()
|
||||
if not isSpace(c):
|
||||
self.error("Directive Error: @" + directive + ".")
|
||||
ctx.skipSpaces()
|
||||
|
||||
# Directive '@library'.
|
||||
if directive == "library":
|
||||
self.library = ctx.parseMacro(ctx.index)
|
||||
|
||||
# Directive '@define'.
|
||||
elif directive == "define":
|
||||
c = ctx.getChar()
|
||||
if not isAlpha_(c):
|
||||
self.error("Define Directive has to start with alpha character or underscore")
|
||||
symbol = ctx.parseSymbol(ctx.index)
|
||||
|
||||
c = ctx.getChar()
|
||||
|
||||
# No Macro.
|
||||
if isNewLine(c):
|
||||
ctx.advance()
|
||||
self.addSymbol(symbol, "")
|
||||
# Has Macro.
|
||||
else:
|
||||
ctx.skipSpaces()
|
||||
|
||||
macro = ctx.parseMacro(ctx.index)
|
||||
self.addSymbol(symbol, macro)
|
||||
|
||||
# Unknown Directive.
|
||||
else:
|
||||
self.error("Unknown Directive: @" + directive + ".")
|
||||
|
||||
ctx.replaceRange(start, ctx.index, "")
|
||||
continue
|
||||
|
||||
# Parse/Replace symbol.
|
||||
if isAlpha_(c) and ctx.index > 0 and ctx.data[ctx.index - 1] != '#':
|
||||
start = ctx.index
|
||||
symbol = ctx.parseSymbol(start)
|
||||
|
||||
if symbol in self.symbols:
|
||||
ctx.replaceRange(start, start + len(symbol), self.symbols[symbol])
|
||||
continue
|
||||
|
||||
ctx.advance()
|
||||
|
||||
return ctx.data
|
||||
|
||||
def addSymbol(self, symbol, macro):
|
||||
if symbol in self.symbols:
|
||||
self.error("Symbol '" + symbol + "' redefinition.")
|
||||
else:
|
||||
# Recurse.
|
||||
macro = self.process(macro)
|
||||
|
||||
log("-- @define " + symbol + " " + macro)
|
||||
self.symbols[symbol] = macro
|
||||
|
||||
def error(self, msg):
|
||||
raise SyntaxError(msg)
|
||||
|
||||
# =============================================================================
|
||||
# [LoadFile / SaveFile]
|
||||
# =============================================================================
|
||||
|
||||
def loadFile(file):
|
||||
h = None
|
||||
data = None
|
||||
|
||||
try:
|
||||
h = open(file, "rb")
|
||||
data = h.read()
|
||||
except:
|
||||
pass
|
||||
finally:
|
||||
if h:
|
||||
h.close()
|
||||
|
||||
return data
|
||||
|
||||
def saveFile(file, data):
|
||||
h = None
|
||||
result = False
|
||||
|
||||
try:
|
||||
h = open(file, "wb")
|
||||
h.truncate()
|
||||
h.write(data)
|
||||
result = True
|
||||
except:
|
||||
pass
|
||||
finally:
|
||||
if h:
|
||||
h.close()
|
||||
|
||||
return result
|
||||
|
||||
# =============================================================================
|
||||
# [PatchFile]
|
||||
# =============================================================================
|
||||
|
||||
def patchFile(file, mark, data):
|
||||
input = loadFile(file)
|
||||
if not input:
|
||||
return
|
||||
|
||||
beginMark = ";${" + mark + ":Begin}"
|
||||
endMark = ";${" + mark + ":End}"
|
||||
|
||||
if beginMark in input:
|
||||
# Replace.
|
||||
if not endMark in input:
|
||||
log("-- Corrupted File:\n" + " " + file)
|
||||
return
|
||||
|
||||
beginMarkIndex = input.find(beginMark)
|
||||
endMarkIndex = input.find(endMark)
|
||||
|
||||
beginMarkIndex = input.find('\n', beginMarkIndex) + 1
|
||||
endMarkIndex = input.rfind('\n', 0, endMarkIndex) + 1
|
||||
|
||||
if beginMarkIndex == -1 or \
|
||||
endMarkIndex == -1 or \
|
||||
beginMarkIndex > endMarkIndex:
|
||||
log("-- Corrupted File:\n" + " " + file)
|
||||
return
|
||||
|
||||
output = input[:beginMarkIndex] + data + input[endMarkIndex:]
|
||||
|
||||
else:
|
||||
# Add.
|
||||
output = input
|
||||
output += "\n"
|
||||
output += beginMark + "\n"
|
||||
output += data
|
||||
output += endMark + "\n"
|
||||
|
||||
if input == output:
|
||||
log("-- Unaffected:\n" + " " + file)
|
||||
else:
|
||||
log("-- Patching:\n" + " " + file)
|
||||
if not saveFile(file, output):
|
||||
log("!! Can't write:\n" + " " + file)
|
||||
|
||||
def main():
|
||||
src = loadFile("autoexp.dat")
|
||||
if src == None:
|
||||
log("!! Can't read autoexp.dat")
|
||||
return
|
||||
|
||||
src = AutoExpDat(src)
|
||||
if not src.library:
|
||||
log("!! Library not defined, use @library directive.")
|
||||
return
|
||||
|
||||
for file in AUTOEXP_FILES:
|
||||
patchFile(file, src.library, src.data)
|
||||
|
||||
main()
|
||||
Reference in New Issue
Block a user