Files
ThirdParty-6/ParaView-5.0.1/VTK/Utilities/vtkindent.py

282 lines
9.7 KiB
Python
Executable File

#!/usr/bin/env python
"""
This script takes old-style "Whitesmiths" indented VTK source files as
input, and re-indents the braces according to the new VTK style.
Only the brace indentation is modified.
Written by David Gobbi on Sep 30, 2015.
"""
import sys
import re
def reindent(filename):
"""Reindent a file from Whitesmiths style to Allman style"""
# This first part of this function clears all strings and comments
# where non-grammatical braces might be hiding.
keychar = re.compile(r"""[/"']""")
c_comment = re.compile(r"\/\*(\*(?!\/)|[^*])*\*\/")
c_comment_start = re.compile(r"\/\*(\*(?!\/)|[^*])*$")
c_comment_end = re.compile(r"^(\*(?!\/)|[^*])*\*\/")
cpp_comment = re.compile(r"\/\/.*")
string_literal = re.compile(r'"([^\\"]|\\.)*"')
string_literal_start = re.compile(r'"([^\\"]|\\.)*\\$')
string_literal_end = re.compile(r'^([^\\"]|\\.)*"')
char_literal = re.compile(r"'([^\\']|\\.)*'")
char_literal_start = re.compile(r"'([^\\']|\\.)*\\$")
char_literal_end = re.compile(r"^([^\\']|\\.)*'")
try:
f = open(filename)
lines = f.readlines()
f.close()
except:
sys.stderr.write(filename + ": ")
sys.stderr.write(str(sys.exc_info()[1]) + "\n")
sys.exit(1)
n = len(lines)
newlines = []
cont = None
for i in range(n):
line = lines[i].rstrip()
if cont is not None:
match = cont.match(line)
if match:
line = line[match.end():]
cont = None
else:
if cont is c_comment_end:
newlines.append("")
continue
else:
newlines.append('\\')
continue
pos = 0
while True:
match = keychar.search(line, pos)
if match is None:
break
pos = match.start()
end = match.end()
match = c_comment.match(line, pos)
if match:
line = line[0:pos] + " " + line[match.end():]
pos += 1
continue
match = c_comment_start.match(line, pos)
if match:
if line[-1] == '\\':
line = line[0:pos] + ' \\'
else:
line = line[0:pos]
cont = c_comment_end
break
match = cpp_comment.match(line, pos)
if match:
if line[-1] == '\\':
line = line[0:pos] + ' \\'
else:
line = line[0:pos]
break
match = string_literal.match(line, pos)
if match:
line = line[0:pos] + "\"\"" + line[match.end():]
pos += 2
continue
match = string_literal_start.match(line, pos)
if match:
line = line[0:pos] + "\"\"\\"
cont = string_literal_end
break
match = char_literal.match(line, pos)
if match:
line = line[0:pos] + "\' \'" + line[match.end():]
pos += 3
continue
match = char_literal_start.match(line, pos)
if match:
line = line[0:pos] + "\' \'\\"
cont = char_literal_end
break
pos += 1
newlines.append(line.rstrip())
# all changes go through this function
lines_changed = {}
def changeline(i, newtext, lines_changed=lines_changed):
if newtext != lines[i]:
lines[i] = newtext
lines_changed[i] = newtext
# Use a stack to keep track of braces and, whenever a closing brace is
# found, properly indent it and its opening brace.
# For #if directives, check whether there are mismatched braces within
# the conditional block, and if so, print a warning and reset the stack
# to the depth that it had at the start of the block.
# stack holds tuples (delim, row, col, newcol)
stack = []
lastdepth = 0
# save the stack for conditional compilation blocks
dstack = []
directive = re.compile(r" *# *(..)")
label = re.compile(r""" *(case *)?(' '|""|[A-Za-z0-9_]| *:: *)+ *:$""")
delims = re.compile(r"[{}()\[\]]")
spaces = re.compile(r" *")
cplusplus = re.compile(r" *# *ifdef *__cplusplus")
lastpos = 0
newpos = 0
continuation = False
new_context = True
in_else = False
in_define = False
in_assign = False
leaving_define = False
save_stack = None
for i in range(n):
line = newlines[i]
pos = 0
# restore stack when leaving #define
if leaving_define:
stack, lastpos, newpos, continuation = save_stack
save_stack = None
in_define = False
leaving_define = False
# handle #if conditionals
is_directive = False
in_else = False
match = directive.match(line)
if match:
is_directive = True
if match.groups()[0] == 'if':
dstack.append((list(stack), line))
elif match.groups()[0] in ('en', 'el'):
oldstack, dline = dstack.pop()
if len(stack) > len(oldstack) and not cplusplus.match(dline):
sys.stderr.write(filename + ":" + str(i) + ": ")
sys.stderr.write("mismatched delimiter in \"" +
dline + "\" block\n")
if match.groups()[0] == 'el':
in_else = True
stack = oldstack
dstack.append((list(stack), line))
elif match.groups()[0] == 'de':
in_define = True
leaving_define = False
save_stack = (stack, lastpos, newpos, continuation)
stack = []
new_context = True
# remove backslash at end of line, if present
if len(line) > 0 and line[-1] == '\\':
line = line[0:-1].rstrip()
elif in_define:
leaving_define = True
if not is_directive and len(line) > 0 and not continuation:
# what is the indentation of the current line?
match = spaces.match(line)
newpos = match.end()
# all statements end with ':', ';', '{', or '}'
if len(line) > 0:
if (new_context or line[-1] in ('{', '}', ';') or
(label.match(line) and not continuation)):
continuation = False
new_context = False
elif not is_directive:
continuation = True
# search for braces
while True:
match = delims.search(line, pos)
if match is None:
break
pos = match.start()
delim = line[pos]
if delim in ('(', '['):
# save delim, row, col, and current indentation
stack.append((delim, i, pos, newpos))
elif delim == '{':
if in_assign:
# do not adjust braces for initializer lists
stack.append((delim, i, pos, pos))
elif ((in_else or in_define) and spaces.sub("", line) == "{"):
# for opening braces that might have no match
indent = " "*lastpos
changeline(i, spaces.sub(indent, lines[i], count=1))
stack.append((delim, i, lastpos, lastpos))
else:
# save delim, row, col, and previous indentation
stack.append((delim, i, pos, lastpos))
newpos = pos + 2
lastpos = newpos
else:
# found a ')', ']', or '}' delimiter, so pop its partner
try:
ldelim, j, k, newpos = stack.pop()
except IndexError:
ldelim = ""
if ldelim != {'}':'{', ')':'(', ']':'['}[delim]:
sys.stderr.write(filename + ":" + str(i) + ": ")
sys.stderr.write("mismatched \'" + delim + "\'\n")
# adjust the indentation of matching '{', '}'
if (ldelim == '{' and delim == '}' and
spaces.sub("", lines[i][0:pos]) == "" and
spaces.sub("", lines[j][0:k]) == ""):
indent = " "*newpos
changeline(i, spaces.sub(indent, lines[i], count=1))
changeline(j, spaces.sub(indent, lines[j], count=1))
pos += 1
# check for " = " and #define assignments for the sake of
# the { inializer list } that might be on the following line
if len(line) > 0:
if (line[-1] == '=' or
(is_directive and in_define and not leaving_define)):
in_assign = True
elif not is_directive:
in_assign = False
lastpos = newpos
if len(dstack) != 0:
sys.stderr.write(filename + ": ")
sys.stderr.write("mismatched #if conditional.\n")
if len(stack) != 0:
sys.stderr.write(filename + ":" + str(stack[0][1]) + ": ")
sys.stderr.write("no match for " + stack[0][0] +
" before end of file.\n")
if lines_changed:
# remove any trailing whitespace
trailing = re.compile(r" *$")
for i in range(n):
lines[i] = trailing.sub("", lines[i])
while n > 0 and lines[n-1].rstrip() == "":
n -= 1
# rewrite the file
ofile = open(filename, 'w')
ofile.writelines(lines)
ofile.close()
if __name__ == "__main__":
for filename in sys.argv[1:]:
reindent(filename)