1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178
|
#!/usr/bin/python
#
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#
#
#
# Find places in our code that are part of control statements
# i.e. "for", "if" and "while". That output is then easily
# searched for various interesting / complex pattern.
#
#
# USAGE: find-control-statements.py FILE1 FILE2 ...
#
import sys
header_shown = False
last_line_num = None
def print_line(fname, line_num, line):
""" Print LINE of number LINE_NUM in file FNAME.
Show FNAME only once per file and LINE_NUM only for
non-consecutive lines.
"""
global header_shown
global last_line_num
if not header_shown:
print('')
print(fname)
header_shown = True
if last_line_num and (last_line_num + 1 == line_num):
print(" %s" % line),
else:
print('%5d:%s' % (line_num, line)),
last_line_num = line_num
def is_control(line, index, word):
""" Return whether LINE[INDEX] is actual the start position of
control statement WORD. It must be followed by an opening
parantheses and only whitespace in between WORD and the '('.
"""
if index > 0:
if not (line[index-1] in [' ', '\t', ';']):
return False
index = index + len(word)
parantheses_index = line.find('(', index)
if parantheses_index == -1:
return False
while index < parantheses_index:
if not (line[index] in [' ', '\t',]):
return False
index += 1
return True
def find_specific_control(line, control):
""" Return the first offset of the control statement CONTROL
in LINE, or -1 if it can't be found.
"""
current = 0
while current != -1:
index = line.find(control, current)
if index == -1:
break
if is_control(line, index, control):
return index
current = index + len(control);
return -1
def find_control(line):
""" Return the offset of the first control in LINE or -1
if there is none.
"""
current = 0
for_index = find_specific_control(line, "for")
if_index = find_specific_control(line, "if")
while_index = find_specific_control(line, "while")
first = len(line)
if for_index >= 0 and first > for_index:
first = for_index
if if_index >= 0 and first > if_index:
first = if_index
if while_index >= 0 and first > while_index:
first = while_index
if first == len(line):
return -1
return first
def parantheses_delta(line):
""" Return the number of opening minus the number of closing
parantheses in LINE. Don't count those inside strings or chars.
"""
escaped = False
in_squote = False
in_dquote = False
delta = 0
for c in line:
if escaped:
escaped = False
elif in_dquote:
if c == '\\':
escaped = True
elif c == '"':
in_dquote = False
elif in_squote:
if c == '\\':
escaped = True
elif c == "'":
in_squote = False
elif c == '(':
delta += 1
elif c == ')':
delta -= 1
elif c == '"':
in_dquote = True
elif c == "'":
in_squote -= True
return delta
def scan_file(fname):
lines = open(fname).readlines()
line_num = 1
parantheses_level = 0
for line in lines:
if parantheses_level > 0:
index = 0
else:
index = find_control(line)
if index >= 0:
print_line(fname, line_num, line)
parantheses_level += parantheses_delta(line[index:])
line_num += 1
if __name__ == '__main__':
for fname in sys.argv[1:]:
header_shown = False
last_line_num = None
scan_file(fname)
|