3 alphanum
= "0123456789abcdefghijklmnopqrstuvwzyxABCDEFGHIJKLMNOPQRSTUVWXYZ_"
4 cpp_keywords
= ["auto", "const", "double", "float", "int", "short", "struct", "unsigned", # C
5 "break", "continue", "else", "for", "long", "signed", "switch", "void",
6 "case", "default", "enum", "goto", "register", "sizeof", "typedef", "volatile",
7 "char", "do", "extern", "if", "return", "static", "union", "while",
9 "asm", "dynamic_cast", "namespace", "reinterpret_cast", "try", # C++
10 "bool", "explicit", "new", "static_cast", "typeid",
11 "catch", "false", "operator", "template", "typename",
12 "class", "friend", "private", "this", "using",
13 "const_cast", "inline", "public", "throw", "virtual",
14 "delete", "mutable", "protected", "true", "wchar_t"]
18 #allowed_words += ["bitmap_left", "advance", "glyph"] # ft2
21 allowed_words
+= ["qsort"] # stdio / stdlib
22 allowed_words
+= ["size_t", "cosf", "sinf", "asinf", "acosf", "atanf", "powf", "fabs", "rand", "powf", "fmod", "sqrtf"] # math.h
23 allowed_words
+= ["time_t", "time", "strftime", "localtime"] # time.h
24 allowed_words
+= [ # system.h
26 "dbg_assert", "dbg_msg", "dbg_break", "dbg_logger_stdout", "dbg_logger_debugger", "dbg_logger_file",
27 "mem_alloc", "mem_zero", "mem_free", "mem_copy", "mem_move", "mem_comp", "mem_stats", "total_allocations", "allocated",
28 "thread_create", "thread_sleep", "lock_wait", "lock_create", "lock_release", "lock_destroy", "swap_endian",
29 "io_open", "io_read", "io_read", "io_write", "io_flush", "io_close", "io_seek", "io_skip", "io_tell", "io_length",
30 "str_comp", "str_length", "str_quickhash", "str_format", "str_copy", "str_comp_nocase", "str_sanitize", "str_append",
31 "str_comp_num", "str_find_nocase", "str_sanitize_strong", "str_uppercase", "str_toint", "str_tofloat",
32 "str_utf8_encode", "str_utf8_rewind", "str_utf8_forward", "str_utf8_decode", "str_sanitize_cc", "str_skip_whitespaces",
33 "fs_makedir", "fs_listdir", "fs_storage_path", "fs_is_dir",
34 "net_init", "net_addr_comp", "net_host_lookup", "net_addr_str", "type", "port", "net_addr_from_str",
35 "net_udp_create", "net_udp_send", "net_udp_recv", "net_udp_close", "net_socket_read_wait",
36 "net_stats", "sent_bytes", "recv_bytes", "recv_packets", "sent_packets",
37 "time_get", "time_freq", "time_timestamp"]
39 allowed_words
+= ["vec2", "vec3", "vec4", "round", "clamp", "length", "dot", "normalize", "frandom", "mix", "distance", "min",
40 "closest_point_on_line", "max", "absolute"] # math.hpp
41 allowed_words
+= [ # tl
42 "array", "sorted_array", "string",
43 "all", "sort", "add", "remove_index", "remove", "delete_all", "set_size",
44 "base_ptr", "size", "swap", "empty", "front", "pop_front", "find_binary", "find_linear", "clear", "range", "end", "cstr",
45 "partition_linear", "partition_binary"]
46 allowed_words
+= ["fx2f", "f2fx"] # fixed point math
48 def CheckIdentifier(ident
):
52 def CheckStart(self
, checker
, filename
):
54 def CheckLine(self
, checker
, line
):
56 def CheckEnd(self
, checker
):
59 class FilenameExtentionChecker(Checker
):
61 self
.allowed
= [".cpp", ".h"]
62 def CheckStart(self
, checker
, filename
):
63 ext
= os
.path
.splitext(filename
)[1]
64 if not ext
in self
.allowed
:
65 checker
.Error("file extention '%s' is not allowed" % ext
)
67 class IncludeChecker(Checker
):
69 self
.disallowed_headers
= ["stdio.h", "stdlib.h", "string.h", "memory.h"]
70 def CheckLine(self
, checker
, line
):
71 if "#include" in line
:
74 include_file
= line
.split('<')[1].split(">")[0]
75 #if not "/" in include_file:
76 # checker.Error("%s is not allowed" % include_file)
78 include_file
= line
.split('"')[1]
81 if include_file
in self
.disallowed_headers
:
82 checker
.Error("%s is not allowed" % include_file
)
84 class HeaderGuardChecker(Checker
):
85 def CheckStart(self
, checker
, filename
):
86 self
.check
= ".h" in filename
87 self
.guard
= "#ifndef " + filename
[4:].replace("/", "_").replace(".hpp", "").replace(".h", "").upper() + "_H"
88 def CheckLine(self
, checker
, line
):
93 if line
.strip() == self
.guard
:
96 checker
.Error("malformed or missing header guard. Should be '%s'" % self
.guard
)
98 class CommentChecker(Checker
):
99 def CheckLine(self
, checker
, line
):
100 if line
.strip()[-2:] == "*/" and "/*" in line
:
101 checker
.Error("single line multiline comment")
106 self
.checkers
+= [FilenameExtentionChecker()]
107 self
.checkers
+= [HeaderGuardChecker()]
108 self
.checkers
+= [IncludeChecker()]
109 self
.checkers
+= [CommentChecker()]
111 def Error(self
, errormessage
):
112 self
.current_errors
+= [(self
.current_line
, errormessage
)]
114 def CheckLine(self
, line
):
115 for c
in self
.checkers
:
116 c
.CheckLine(self
, line
)
119 def CheckFile(self
, filename
):
120 self
.current_file
= filename
121 self
.current_line
= 0
122 self
.current_errors
= []
123 for c
in self
.checkers
:
124 c
.CheckStart(self
, filename
)
126 for line
in file(filename
).readlines():
127 self
.current_line
+= 1
128 if "ignore_check" in line
:
132 for c
in self
.checkers
:
136 return self
.current_errors
141 if "ignore_convention" in l
:
143 l
= re
.sub("^[\t ]*#.*", "", l
)
144 l
= re
.sub("//.*", "", l
)
145 l
= re
.sub('\".*?\"', '"String"', l
) # remove strings
147 d
= re
.sub('\/\*.*?\*\/', "", d
) # remove /* */ comments
148 d
= d
.replace("\t", " ") # tab to space
149 d
= re
.sub(" *", " ", d
) # remove double spaces
150 #d = re.sub("", "", d) # remove /* */ comments
154 # this eats up cases like 'n {'
158 if not (d
[i
-1] in alphanum
and d
[i
+1] in alphanum
):
163 #def stripstrings(data):
164 # return re.sub('\".*?\"', 'STRING', data)
166 def get_identifiers(data
):
169 regexp
= re
.compile("[^a-zA-Z0-9_][a-zA-Z_][a-zA-Z0-9_]+[^a-zA-Z0-9_]")
172 m
= regexp
.search(data
, start
)
177 name
= data
[m
.start()+1:m
.end()-1]
191 print '<link href="/style.css" rel="stylesheet" type="text/css" />'
197 print '<div id="outer">'
199 print '<div id="top_left"><div id="top_right"><div id="top_mid">'
200 print '<a href="/"><img src="/images/twlogo.png" alt="teeworlds logo" /></a>'
201 print '</div></div></div>'
203 print '<div id="menu_left"><div id="menu_right"><div id="menu_mid">'
204 print '</div></div></div>'
206 print '<div id="tlc"><div id="trc"><div id="tb"> </div></div></div>'
207 print '<div id="lb"><div id="rb"><div id="mid">'
208 print '<div id="container">'
210 print '<p class="topic_text">'
211 print '<h1>Code Refactoring Progress</h1>'
212 print '''This is generated by a script that find identifiers in the code
213 that doesn't conform to the code standard. Right now it only shows headers
214 because they need to be fixed before we can do the rest of the source.
215 This is a ROUGH estimate of the progress'''
218 print '<p class="topic_text">'
220 #print "<tr><td><b>%</b></td><td><b>#</b></td><td><b>File</b></td><td><b>Offenders</b></td></tr>"
227 for (root
,dirs
,files
) in os
.walk("src"):
228 for filename
in files
:
229 filename
= os
.path
.join(root
, filename
)
230 if "/." in filename
or "/external/" in filename
or "/base/" in filename
or "/generated/" in filename
:
232 if "src/osxlaunch/client.h" in filename
: # ignore this file, ObjC file
234 if "e_config_variables.h" in filename
: # ignore config files
236 if "src/game/variables.hpp" in filename
: # ignore config files
239 if not (".hpp" in filename
or ".h" in filename
or ".cpp" in filename
):
244 #if not "src/engine/client/ec_client.cpp" in filename:
248 f
.CheckFile(filename
)
249 num_errors
= len(f
.GetErrors())
250 total_errors
+= num_errors
253 print '<tr style="background: #e0e0e0"><td colspan="2">%s, %d errors</td></tr>' % (filename
, num_errors
),
254 for line
, msg
in f
.GetErrors():
255 print '<tr"><td>%d</td><td>%s</td></tr>' % (line
, msg
)
263 text
= cstrip(file(filename
).readlines()) # remove all preprocessor stuff and comments
264 #text = stripstrings(text) # remove strings (does not solve all cases however)
267 idents
= get_identifiers(text
)
273 if len(name
) <= 2: # skip things that are too small
275 if name
in cpp_keywords
: # skip keywords
277 if name
in allowed_words
: # skip allowed keywords
280 total
+= idents
[name
]
281 if name
!= name
.lower(): # strip names that are not only lower case
283 offender_list
[name
] = idents
[name
]
285 print "[%d] %s"%(idents
[name
], name
)
286 offenders
+= idents
[name
]
289 grand_offenders
+= offenders
294 line_order
= -line_order
297 done
= int((1-(offenders
/ float(total
))) * 100)
301 if done
!= 100 and gen_html
:
312 line_color
= "#f0efd5"
314 line_color
= "#ffffff"
318 for name
in offender_list
:
320 offender_string
+= "[%d]%s " % (offender_list
[name
], name
)
323 offender_string
+= "<br/>"
325 print '<tr style="background: %s">' % line_color
,
326 print '<td style="text-align: right; background: %s"><b>%d%%</b></td><td style="text-align: center">%d</td><td>%s</td>' % (color
, done
, offenders
, filename
),
327 print '<td style="text-align: right">%s</td>' % offender_string
334 print "<h1>%d errors</h1>" % total_errors
338 print "<h1>%.1f%% Identifiers done</h1>" % ((1-(grand_offenders
/ float(grand_total
))) * 100)
339 print "%d left of %d" % (grand_offenders
, grand_total
)
340 print "<h1>%.1f%% Files done</h1>" % ((complete_files
/ float(total_files
)) * 100)
341 print "%d left of %d" % (total_files
-complete_files
, total_files
)
344 print "<div style='clear:both;'></div>"
346 print '</div></div></div>'
348 print '<div id="blc"><div id="brc"><div id="bb"> </div></div></div>'