1 1.1 mrg #! /usr/bin/python2 2 1.1 mrg import os 3 1.1 mrg import sys 4 1.1 mrg import shlex 5 1.1 mrg import re 6 1.1 mrg 7 1.1 mrg from headerutils import * 8 1.1 mrg import Queue 9 1.1 mrg 10 1.1 mrg file_list = list () 11 1.1 mrg usage = False 12 1.1 mrg 13 1.1 mrg ignore_conditional = False 14 1.1 mrg 15 1.1 mrg order = [ 16 1.1 mrg "system.h", 17 1.1 mrg "coretypes.h", 18 1.1 mrg "backend.h", 19 1.1 mrg "target.h", 20 1.1 mrg "rtl.h", 21 1.1 mrg "c-family/c-target.h", 22 1.1 mrg "c-family/c-target-def.h", 23 1.1 mrg "tree.h", 24 1.1 mrg "cp/cp-tree.h", 25 1.1 mrg "c-family/c-common.h", # these must come before diagnostic.h 26 1.1 mrg "c/c-tree.h", 27 1.1 mrg "fortran/gfortran.h", 28 1.1 mrg "gimple.h", 29 1.1 mrg "cfghooks.h", 30 1.1 mrg "df.h", 31 1.1 mrg "tm_p.h", 32 1.1 mrg "gimple-iterators.h", 33 1.1 mrg "ssa.h", 34 1.1 mrg "expmed.h", 35 1.1 mrg "optabs.h", 36 1.1 mrg "regs.h", 37 1.1 mrg "ira.h", 38 1.1 mrg "ira-int.h", 39 1.1 mrg "gimple-streamer.h" 40 1.1 mrg 41 1.1 mrg ] 42 1.1 mrg 43 1.1 mrg exclude_special = [ "bversion.h", "obstack.h", "insn-codes.h", "hooks.h" ] 44 1.1 mrg 45 1.1 mrg # includes is a dictionary indexed by a header files basename. 46 1.1 mrg # it consists of a 2 element tuple: 47 1.1 mrg # [0] - Name of header file which included this header. 48 1.1 mrg # [1] - vector of header file names included by this file. 49 1.1 mrg 50 1.1 mrg includes = { } 51 1.1 mrg 52 1.1 mrg # when a header is included multiple times, indexing this dictionary will 53 1.1 mrg # return a vector of all the headers which included it. 54 1.1 mrg dups = { } 55 1.1 mrg 56 1.1 mrg # When creating the master list, do not descend into these files for what 57 1.1 mrg # they include. Simply put the file itself in the list. This is primarily 58 1.1 mrg # required because the front end files inlcude orders tend to be at odds with 59 1.1 mrg # the order of middle end files, and its impossible to synchronize them.\ 60 1.1 mrg # They are ordered such that everything resolves properly. 61 1.1 mrg exclude_processing = [ "tree-vectorizer.h" , "c-target.h", "c-target-def.h", "cp-tree.h", "c-common.h", "c-tree.h", "gfortran.h" ] 62 1.1 mrg 63 1.1 mrg master_list = list () 64 1.1 mrg # where include file comes from in src 65 1.1 mrg h_from = { } 66 1.1 mrg 67 1.1 mrg # create the master ordering list... this is the desired order of headers 68 1.1 mrg def create_master_list (fn, verbose): 69 1.1 mrg if fn not in exclude_processing: 70 1.1 mrg for x in includes[fn][1]: 71 1.1 mrg create_master_list (x, verbose) 72 1.1 mrg if not fn in master_list: 73 1.1 mrg # Don't put diagnostic*.h into the ordering list. It is special since 74 1.1 mrg # various front ends have to set GCC_DIAG_STYLE before including it. 75 1.1 mrg # for each file, we'll tailor where it belongs by looking at the include 76 1.1 mrg # list and determine its position appropriately. 77 1.1 mrg if fn != "diagnostic.h" and fn != "diagnostic-core.h": 78 1.1 mrg master_list.append (fn) 79 1.1 mrg if (verbose): 80 1.1 mrg print fn + " included by: " + includes[fn][0] 81 1.1 mrg 82 1.1 mrg 83 1.1 mrg 84 1.1 mrg def print_dups (): 85 1.1 mrg if dups: 86 1.1 mrg print "\nduplicated includes" 87 1.1 mrg for i in dups: 88 1.1 mrg string = "dup : " + i + " : " 89 1.1 mrg string += includes[i][0] 90 1.1 mrg for i2 in dups[i]: 91 1.1 mrg string += ", "+i2 92 1.1 mrg print string 93 1.1 mrg 94 1.1 mrg 95 1.1 mrg def process_known_dups (): 96 1.1 mrg # rtl.h gets tagged as a duplicate includer for all of coretypes.h, but that 97 1.1 mrg # is really for only generator files 98 1.1 mrg rtl_remove = includes["coretypes.h"][1] + ["statistics.h", "vec.h"] 99 1.1 mrg if dups: 100 1.1 mrg for i in rtl_remove: 101 1.1 mrg if dups[i] and "rtl.h" in dups[i]: 102 1.1 mrg dups[i].remove("rtl.h") 103 1.1 mrg if not dups[i]: 104 1.1 mrg dups.pop (i, None) 105 1.1 mrg 106 1.1 mrg # make sure diagnostic.h is the owner of diagnostic-core.h 107 1.1 mrg if includes["diagnostic-core.h"][0] != "diagnostic.h": 108 1.1 mrg dups["diagnostic-core.h"].append (includes["diagnostic-core.h"][0]) 109 1.1 mrg includes["diagnostic-core.h"] = ("diagnostic.h", includes["diagnostic-core.h"][1]) 110 1.1 mrg 111 1.1 mrg # This function scans back thorugh the list of headers which included other 112 1.1 mrg # headers to determine what file in HEADER_LIST brought 'HEADER' in. 113 1.1 mrg def indirectly_included (header, header_list): 114 1.1 mrg nm = os.path.basename (header) 115 1.1 mrg while nm and includes.get(nm): 116 1.1 mrg if includes[nm][0] in header_list: 117 1.1 mrg return includes[nm][0] 118 1.1 mrg nm = includes[nm][0] 119 1.1 mrg 120 1.1 mrg # diagnostic.h and diagnostic-core.h may not show up because we removed them 121 1.1 mrg # from the header list to manually position in an appropriate place. They have 122 1.1 mrg # specific requirements that they need to occur after certain FE files which 123 1.1 mrg # may overide the definition of GCC_DIAG_STYLE. 124 1.1 mrg # Check the dup list for whete they may have been included from and return 125 1.1 mrg # that header. 126 1.1 mrg if header == "diagnostic-core.h": 127 1.1 mrg if dups.get("diagnostic-core.h"): 128 1.1 mrg for f in dups["diagnostic-core.h"]: 129 1.1 mrg if f in header_list: 130 1.1 mrg return f 131 1.1 mrg else: 132 1.1 mrg if header in header_list: 133 1.1 mrg return header 134 1.1 mrg # Now check if diagnostics is included indirectly anywhere 135 1.1 mrg header = "diagnostic.h" 136 1.1 mrg 137 1.1 mrg if header == "diagnostic.h": 138 1.1 mrg if dups.get("diagnostic.h"): 139 1.1 mrg for f in dups["diagnostic.h"]: 140 1.1 mrg if f in header_list: 141 1.1 mrg return f 142 1.1 mrg else: 143 1.1 mrg if header in header_list: 144 1.1 mrg return header 145 1.1 mrg 146 1.1 mrg return "" 147 1.1 mrg 148 1.1 mrg 149 1.1 mrg # This function will take a list of headers from a source file and return 150 1.1 mrg # the desired new new order of the canonical headers in DESIRED_ORDER. 151 1.1 mrg def get_new_order (src_h, desired_order): 152 1.1 mrg new_order = list () 153 1.1 mrg for h in desired_order: 154 1.1 mrg if h in master_list: 155 1.1 mrg # Create the list of nested headers which included this file. 156 1.1 mrg iclist = list () 157 1.1 mrg ib = includes[h][0] 158 1.1 mrg while ib: 159 1.1 mrg iclist.insert(0, ib) 160 1.1 mrg ib = includes[ib][0] 161 1.1 mrg if iclist: 162 1.1 mrg for x in iclist: 163 1.1 mrg # If header is in the source code, and we are allowed to look inside 164 1.1 mrg if x in src_h and x not in exclude_processing: 165 1.1 mrg if x not in new_order and x[:10] != "diagnostic" and h not in exclude_special: 166 1.1 mrg new_order.append (x) 167 1.1 mrg break; 168 1.1 mrg else: 169 1.1 mrg if h not in new_order: 170 1.1 mrg new_order.append (h) 171 1.1 mrg 172 1.1 mrg f = "" 173 1.1 mrg if "diagnostic.h" in src_h: 174 1.1 mrg f = "diagnostic.h" 175 1.1 mrg elif "diagnostic-core.h" in src_h: 176 1.1 mrg f = "diagnostic-core.h" 177 1.1 mrg 178 1.1 mrg 179 1.1 mrg # If either diagnostic header was directly included in the main file, check to 180 1.1 mrg # see if its already included indirectly, or whether we need to add it to the 181 1.1 mrg # end of the canonically orders headers. 182 1.1 mrg if f: 183 1.1 mrg ii = indirectly_included (f, src_h) 184 1.1 mrg if not ii or ii == f: 185 1.1 mrg new_order.append (f) 186 1.1 mrg 187 1.1 mrg return new_order 188 1.1 mrg 189 1.1 mrg 190 1.1 mrg 191 1.1 mrg # stack of files to process 192 1.1 mrg process_stack = list () 193 1.1 mrg 194 1.1 mrg def process_one (info): 195 1.1 mrg i = info[0] 196 1.1 mrg owner = info[1] 197 1.1 mrg name = os.path.basename(i) 198 1.1 mrg if os.path.exists (i): 199 1.1 mrg if includes.get(name) == None: 200 1.1 mrg l = find_unique_include_list (i) 201 1.1 mrg # create a list which has just basenames in it 202 1.1 mrg new_list = list () 203 1.1 mrg for x in l: 204 1.1 mrg new_list.append (os.path.basename (x)) 205 1.1 mrg process_stack.append((x, name)) 206 1.1 mrg includes[name] = (owner, new_list) 207 1.1 mrg elif owner: 208 1.1 mrg if dups.get(name) == None: 209 1.1 mrg dups[name] = [ owner ] 210 1.1 mrg else: 211 1.1 mrg dups[name].append (owner) 212 1.1 mrg else: 213 1.1 mrg # seed tm.h with options.h since it is a build file and won't be seen. 214 1.1 mrg if not includes.get(name): 215 1.1 mrg if name == "tm.h": 216 1.1 mrg includes[name] = (owner, [ "options.h" ]) 217 1.1 mrg includes["options.h"] = ("tm.h", list ()) 218 1.1 mrg else: 219 1.1 mrg includes[name] = (owner, list ()) 220 1.1 mrg 221 1.1 mrg 222 1.1 mrg show_master = False 223 1.1 mrg 224 1.1 mrg for arg in sys.argv[1:]: 225 1.1 mrg if arg[0:1] == "-": 226 1.1 mrg if arg[0:2] == "-h": 227 1.1 mrg usage = True 228 1.1 mrg elif arg[0:2] == "-i": 229 1.1 mrg ignore_conditional = True 230 1.1 mrg elif arg[0:2] == "-v": 231 1.1 mrg show_master = True 232 1.1 mrg else: 233 1.1 mrg print "Error: unrecognized option " + arg 234 1.1 mrg elif os.path.exists(arg): 235 1.1 mrg file_list.append (arg) 236 1.1 mrg else: 237 1.1 mrg print "Error: file " + arg + " Does not exist." 238 1.1 mrg usage = True 239 1.1 mrg 240 1.1 mrg if not file_list and not show_master: 241 1.1 mrg usage = True 242 1.1 mrg 243 1.1 mrg if not usage and not os.path.exists ("coretypes.h"): 244 1.1 mrg usage = True 245 1.1 mrg print "Error: Must run command in main gcc source directory containing coretypes.h\n" 246 1.1 mrg 247 1.1 mrg # process diagnostic.h first.. it's special since GCC_DIAG_STYLE can be 248 1.1 mrg # overridden by languages, but must be done so by a file included BEFORE it. 249 1.1 mrg # so make sure it isn't seen as included by one of those files by making it 250 1.1 mrg # appear to be included by the src file. 251 1.1 mrg process_stack.insert (0, ("diagnostic.h", "")) 252 1.1 mrg 253 1.1 mrg # Add the list of files in reverse order since it is processed as a stack later 254 1.1 mrg for i in order: 255 1.1 mrg process_stack.insert (0, (i, "") ) 256 1.1 mrg 257 1.1 mrg # build up the library of what header files include what other files. 258 1.1 mrg while process_stack: 259 1.1 mrg info = process_stack.pop () 260 1.1 mrg process_one (info) 261 1.1 mrg 262 1.1 mrg # Now create the master ordering list 263 1.1 mrg for i in order: 264 1.1 mrg create_master_list (os.path.basename (i), show_master) 265 1.1 mrg 266 1.1 mrg # handle warts in the duplicate list 267 1.1 mrg process_known_dups () 268 1.1 mrg desired_order = master_list 269 1.1 mrg 270 1.1 mrg if show_master: 271 1.1 mrg print " Canonical order of gcc include files: " 272 1.1 mrg for x in master_list: 273 1.1 mrg print x 274 1.1 mrg print " " 275 1.1 mrg 276 1.1 mrg if usage: 277 1.1 mrg print "gcc-order-headers [-i] [-v] file1 [filen]" 278 1.1 mrg print " Ensures gcc's headers files are included in a normalized form with" 279 1.1 mrg print " redundant headers removed. The original files are saved in filename.bak" 280 1.1 mrg print " Outputs a list of files which changed." 281 1.1 mrg print " -i ignore conditional compilation." 282 1.1 mrg print " Use after examining the file to be sure includes within #ifs are safe" 283 1.1 mrg print " Any headers within conditional sections will be ignored." 284 1.1 mrg print " -v Show the canonical order of known headers" 285 1.1 mrg sys.exit(0) 286 1.1 mrg 287 1.1 mrg 288 1.1 mrg didnt_do = list () 289 1.1 mrg 290 1.1 mrg for fn in file_list: 291 1.1 mrg nest = 0 292 1.1 mrg src_h = list () 293 1.1 mrg src_line = { } 294 1.1 mrg 295 1.1 mrg master_list = list () 296 1.1 mrg 297 1.1 mrg includes = { } 298 1.1 mrg dups = { } 299 1.1 mrg 300 1.1 mrg iinfo = process_ii_src (fn) 301 1.1 mrg src = ii_src (iinfo) 302 1.1 mrg include_list = ii_include_list (iinfo) 303 1.1 mrg 304 1.1 mrg if ii_include_list_cond (iinfo): 305 1.1 mrg if not ignore_conditional: 306 1.1 mrg print fn + ": Cannot process due to conditional compilation of includes" 307 1.1 mrg didnt_do.append (fn) 308 1.1 mrg src = list () 309 1.1 mrg 310 1.1 mrg if not src: 311 1.1 mrg continue 312 1.1 mrg 313 1.1 mrg process_stack = list () 314 1.1 mrg # prime the stack with headers in the main ordering list so we get them in 315 1.1 mrg # this order. 316 1.1 mrg for d in order: 317 1.1 mrg if d in include_list: 318 1.1 mrg process_stack.insert (0, (d, "")) 319 1.1 mrg 320 1.1 mrg for d in include_list: 321 1.1 mrg nm = os.path.basename(d) 322 1.1 mrg src_h.append (nm) 323 1.1 mrg iname = d 324 1.1 mrg iname2 = os.path.dirname (fn) + "/" + d 325 1.1 mrg if not os.path.exists (d) and os.path.exists (iname2): 326 1.1 mrg iname = iname2 327 1.1 mrg if iname not in process_stack: 328 1.1 mrg process_stack.insert (0, (iname, "")) 329 1.1 mrg src_line[nm] = ii_src_line(iinfo)[d] 330 1.1 mrg if src_line[nm].find("/*") != -1 and src_line[nm].find("*/") == -1: 331 1.1 mrg # this means we have a multi line comment, abort!' 332 1.1 mrg print fn + ": Cannot process due to a multi-line comment :" 333 1.1 mrg print " " + src_line[nm] 334 1.1 mrg if fn not in didnt_do: 335 1.1 mrg didnt_do.append (fn) 336 1.1 mrg src = list () 337 1.1 mrg 338 1.1 mrg if not src: 339 1.1 mrg continue 340 1.1 mrg 341 1.1 mrg # Now create the list of includes as seen by the source file. 342 1.1 mrg while process_stack: 343 1.1 mrg info = process_stack.pop () 344 1.1 mrg process_one (info) 345 1.1 mrg 346 1.1 mrg for i in include_list: 347 1.1 mrg create_master_list (os.path.basename (i), False) 348 1.1 mrg 349 1.1 mrg new_src = list () 350 1.1 mrg header_added = list () 351 1.1 mrg new_order = list () 352 1.1 mrg for line in src: 353 1.1 mrg d = find_pound_include (line, True, True) 354 1.1 mrg if not d or d[-2:] != ".h": 355 1.1 mrg new_src.append (line) 356 1.1 mrg else: 357 1.1 mrg if d == order[0] and not new_order: 358 1.1 mrg new_order = get_new_order (src_h, desired_order) 359 1.1 mrg for i in new_order: 360 1.1 mrg new_src.append (src_line[i]) 361 1.1 mrg # if not seen, add it. 362 1.1 mrg if i not in header_added: 363 1.1 mrg header_added.append (i) 364 1.1 mrg else: 365 1.1 mrg nm = os.path.basename(d) 366 1.1 mrg if nm not in header_added: 367 1.1 mrg iby = indirectly_included (nm, src_h) 368 1.1 mrg if not iby: 369 1.1 mrg new_src.append (line) 370 1.1 mrg header_added.append (nm) 371 1.1 mrg 372 1.1 mrg if src != new_src: 373 1.1 mrg os.rename (fn, fn + ".bak") 374 1.1 mrg fl = open(fn,"w") 375 1.1 mrg for line in new_src: 376 1.1 mrg fl.write (line) 377 1.1 mrg fl.close () 378 1.1 mrg print fn 379 1.1 mrg 380 1.1 mrg 381 1.1 mrg if didnt_do: 382 1.1 mrg print "\n\n Did not process the following files due to conditional dependencies:" 383 1.1 mrg str = "" 384 1.1 mrg for x in didnt_do: 385 1.1 mrg str += x + " " 386 1.1 mrg print str 387 1.1 mrg print "\n" 388 1.1 mrg print "Please examine to see if they are safe to process, and re-try with -i. " 389 1.1 mrg print "Safeness is determined by checking whether any of the reordered headers are" 390 1.1 mrg print "within a conditional and could be hauled out of the conditional, thus changing" 391 1.1 mrg print "what the compiler will see." 392 1.1 mrg print "Multi-line comments after a #include can also cause failuer, they must be turned" 393 1.1 mrg print "into single line comments or removed." 394 1.1 mrg 395 1.1 mrg 396 1.1 mrg 397 1.1 mrg 398