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