7 from file_types
import *
10 'assert.h' : 'cassert',
14 'limits.h' : 'climits',
15 'locale.h' : 'clocale',
17 'setjmp.h' : 'csetjmp',
18 'signal.h' : 'csignal',
19 'stdarg.h' : 'cstdarg',
20 'stddef.h' : 'cstddef',
22 'stdlib.h' : 'cstdlib',
23 'string.h' : 'cstring',
26 'wctype.h' : 'cwctype',
29 include_re
= re
.compile(r
'([#%])(include|import).*[<"](.*)[">]')
30 def include_key(line
):
31 '''Mark directories with a leading space so directories
32 are sorted before files'''
34 match
= include_re
.match(line
)
36 keyword
= match
.group(2)
37 include
= match
.group(3)
39 # Everything but the file part needs to have a space prepended
40 parts
= include
.split('/')
41 if len(parts
) == 2 and parts
[0] == 'dnet':
42 # Don't sort the dnet includes with respect to each other, but
43 # make them sorted with respect to non dnet includes. Python
44 # guarantees that sorting is stable, so just clear the
45 # basename part of the filename.
47 parts
[0:-1] = [ ' ' + s
for s
in parts
[0:-1] ]
52 class SortIncludes(object):
53 # different types of includes for different sorting of headers
54 # <Python.h> - Python header needs to be first if it exists
55 # <*.h> - system headers (directories before files)
57 # <*.(hh|hxx|hpp|H)> - C++ Headers (directories before files)
58 # "*" - M5 headers (directories before files)
60 ('python', '<>', r
'^(#include)[ \t]+<(Python.*\.h)>(.*)'),
61 ('c', '<>', r
'^(#include)[ \t]<(.+\.h)>(.*)'),
62 ('stl', '<>', r
'^(#include)[ \t]+<([0-9A-z_]+)>(.*)'),
63 ('cc', '<>', r
'^(#include)[ \t]+<([0-9A-z_]+\.(hh|hxx|hpp|H))>(.*)'),
64 ('m5cc', '""', r
'^(#include)[ \t]"(.+\.h{1,2})"(.*)'),
65 ('swig0', '<>', r
'^(%import)[ \t]<(.+)>(.*)'),
66 ('swig1', '<>', r
'^(%include)[ \t]<(.+)>(.*)'),
67 ('swig2', '""', r
'^(%import)[ \t]"(.+)"(.*)'),
68 ('swig3', '""', r
'^(%include)[ \t]"(.+)"(.*)'),
72 includes_re
= tuple((a
, b
, re
.compile(c
)) for a
,b
,c
in includes_re
)
78 # clear all stored headers
80 for include_type
,_
,_
in self
.includes_re
:
81 self
.includes
[include_type
] = []
84 '''dump the includes'''
86 for include
,_
,_
in self
.includes_re
:
87 if not self
.includes
[include
]:
91 # print a newline between groups of
96 # print out the includes in the current group
97 # and sort them according to include_key()
99 for l
in sorted(self
.includes
[include
],
105 def __call__(self
, lines
, filename
, language
):
107 leading_blank
= False
115 # if we're not in an include block, spit out the
116 # newline otherwise, skip it since we're going to
117 # control newlines withinin include block
121 # Try to match each of the include types
122 for include_type
,(ldelim
,rdelim
),include_re
in self
.includes_re
:
123 match
= include_re
.match(line
)
127 # if we've got a match, clean up the #include line,
128 # fix up stl headers and store it in the proper category
129 groups
= match
.groups()
133 if include_type
== 'c' and language
== 'C++':
134 stl_inc
= cpp_c_headers
.get(include
, None)
139 line
= keyword
+ ' ' + ldelim
+ include
+ rdelim
+ extra
141 self
.includes
[include_type
].append(line
)
143 # We've entered a block, don't keep track of blank
144 # lines while in a block
149 # this line did not match a #include
150 assert not include_re
.match(line
)
152 # if we're not in a block and we didn't match an include
153 # to enter a block, just emit the line and continue
158 # We've exited an include block.
159 for block_line
in self
.dump_block():
162 # if there are any newlines after the include block,
163 # emit a single newline (removing extras)
171 # emit the line that ended the block
175 # We've exited an include block.
176 for block_line
in self
.dump_block():
181 # default language types to try to apply our sorting rules to
182 default_languages
= frozenset(('C', 'C++', 'isa', 'python', 'scons', 'swig'))
186 options
= optparse
.OptionParser()
187 add_option
= options
.add_option
188 add_option('-d', '--dir_ignore', metavar
="DIR[,DIR]", type='string',
189 default
=','.join(default_dir_ignore
),
190 help="ignore directories")
191 add_option('-f', '--file_ignore', metavar
="FILE[,FILE]", type='string',
192 default
=','.join(default_file_ignore
),
194 add_option('-l', '--languages', metavar
="LANG[,LANG]", type='string',
195 default
=','.join(default_languages
),
197 add_option('-n', '--dry-run', action
='store_true',
198 help="don't overwrite files")
202 def parse_args(parser
):
203 opts
,args
= parser
.parse_args()
205 opts
.dir_ignore
= frozenset(opts
.dir_ignore
.split(','))
206 opts
.file_ignore
= frozenset(opts
.file_ignore
.split(','))
207 opts
.languages
= frozenset(opts
.languages
.split(','))
211 if __name__
== '__main__':
213 opts
, args
= parse_args(parser
)
216 for filename
,language
in find_files(base
, languages
=opts
.languages
,
217 file_ignore
=opts
.file_ignore
, dir_ignore
=opts
.dir_ignore
):
219 print "%s: %s" % (filename
, language
)
221 update_file(filename
, filename
, language
, SortIncludes())