xref: /netbsd-src/external/gpl3/gcc.old/dist/contrib/header-tools/headerutils.py (revision 36ac495d2b3ea2b9d96377b2143ebfedac224b92)
1*36ac495dSmrg#! /usr/bin/python2
2*36ac495dSmrgimport os.path
3*36ac495dSmrgimport sys
4*36ac495dSmrgimport shlex
5*36ac495dSmrgimport re
6*36ac495dSmrgimport subprocess
7*36ac495dSmrgimport shutil
8*36ac495dSmrgimport pickle
9*36ac495dSmrg
10*36ac495dSmrgimport multiprocessing
11*36ac495dSmrg
12*36ac495dSmrgdef find_pound_include (line, use_outside, use_slash):
13*36ac495dSmrg  inc = re.findall (ur"^\s*#\s*include\s*\"(.+?)\"", line)
14*36ac495dSmrg  if len(inc) == 1:
15*36ac495dSmrg    nm = inc[0]
16*36ac495dSmrg    if use_outside or os.path.exists (nm):
17*36ac495dSmrg      if use_slash or '/' not in nm:
18*36ac495dSmrg        return nm
19*36ac495dSmrg  return ""
20*36ac495dSmrg
21*36ac495dSmrgdef find_system_include (line):
22*36ac495dSmrg  inc = re.findall (ur"^\s*#\s*include\s*<(.+?)>", line)
23*36ac495dSmrg  if len(inc) == 1:
24*36ac495dSmrg    return inc[0]
25*36ac495dSmrg  return ""
26*36ac495dSmrg
27*36ac495dSmrgdef find_pound_define (line):
28*36ac495dSmrg  inc = re.findall (ur"^\s*#\s*define ([A-Za-z0-9_]+)", line)
29*36ac495dSmrg  if len(inc) != 0:
30*36ac495dSmrg    if len(inc) > 1:
31*36ac495dSmrg      print "What? more than 1 match in #define??"
32*36ac495dSmrg      print inc
33*36ac495dSmrg      sys.exit(5)
34*36ac495dSmrg    return inc[0];
35*36ac495dSmrg  return ""
36*36ac495dSmrg
37*36ac495dSmrgdef is_pound_if (line):
38*36ac495dSmrg  inc = re.findall ("^\s*#\s*if\s", line)
39*36ac495dSmrg  if not inc:
40*36ac495dSmrg    inc = re.findall ("^\s*#\s*if[n]?def\s", line)
41*36ac495dSmrg  if inc:
42*36ac495dSmrg    return True
43*36ac495dSmrg  return False
44*36ac495dSmrg
45*36ac495dSmrgdef is_pound_endif (line):
46*36ac495dSmrg  inc = re.findall ("^\s*#\s*endif", line)
47*36ac495dSmrg  if inc:
48*36ac495dSmrg    return True
49*36ac495dSmrg  return False
50*36ac495dSmrg
51*36ac495dSmrgdef find_pound_if (line):
52*36ac495dSmrg  inc = re.findall (ur"^\s*#\s*if\s+(.*)", line)
53*36ac495dSmrg  if len(inc) == 0:
54*36ac495dSmrg    inc = re.findall (ur"^\s*#\s*elif\s+(.*)", line)
55*36ac495dSmrg  if len(inc) > 0:
56*36ac495dSmrg    inc2 = re.findall (ur"defined\s*\((.+?)\)", inc[0])
57*36ac495dSmrg    inc3 = re.findall (ur"defined\s+([a-zA-Z0-9_]+)", inc[0])
58*36ac495dSmrg    for yy in inc3:
59*36ac495dSmrg      inc2.append (yy)
60*36ac495dSmrg    return inc2
61*36ac495dSmrg  else:
62*36ac495dSmrg    inc = re.findall (ur"^\s*#\s*ifdef\s(.*)", line)
63*36ac495dSmrg    if len(inc) == 0:
64*36ac495dSmrg      inc = re.findall (ur"^\s*#\s*ifndef\s(.*)", line)
65*36ac495dSmrg    if len(inc) > 0:
66*36ac495dSmrg      inc2 = re.findall ("[A-Za-z_][A-Za-z_0-9]*", inc[0])
67*36ac495dSmrg      return inc2
68*36ac495dSmrg  if len(inc) == 0:
69*36ac495dSmrg    return list ()
70*36ac495dSmrg  print "WTF. more than one line returned for find_pound_if"
71*36ac495dSmrg  print inc
72*36ac495dSmrg  sys.exit(5)
73*36ac495dSmrg
74*36ac495dSmrg
75*36ac495dSmrg# IINFO - this is a vector of include information. It consists of 7 elements.
76*36ac495dSmrg# [0] - base name of the file
77*36ac495dSmrg# [1] - path leading to this file.
78*36ac495dSmrg# [2] - orderd list of all headers directly included by this file.
79*36ac495dSmrg# [3] - Ordered list of any headers included within condionally compiled code.
80*36ac495dSmrg#       headers files are expected to have all includes one level deep due to
81*36ac495dSmrg#       the omnipresent guards at the top of the file.
82*36ac495dSmrg# [4] - List of all macros which are consumed (used) within this file.
83*36ac495dSmrg# [5] - list of all macros which may be defined in this file.
84*36ac495dSmrg# [6] - The source code for this file, if cached.
85*36ac495dSmrg# [7] - line number info for any headers in the source file.  Indexed by base
86*36ac495dSmrg#       name, returning the line the include is on.
87*36ac495dSmrg
88*36ac495dSmrgempty_iinfo =  ("", "", list(), list(), list(), list(), list())
89*36ac495dSmrg
90*36ac495dSmrg# This function will process a file and extract interesting information.
91*36ac495dSmrg# DO_MACROS indicates whether macros defined and used should be recorded.
92*36ac495dSmrg# KEEP_SRC indicates the source for the file should be cached.
93*36ac495dSmrgdef process_include_info (filen, do_macros, keep_src):
94*36ac495dSmrg  header = False
95*36ac495dSmrg  if not os.path.exists (filen):
96*36ac495dSmrg    return empty_iinfo
97*36ac495dSmrg
98*36ac495dSmrg  sfile = open (filen, "r");
99*36ac495dSmrg  data = sfile.readlines()
100*36ac495dSmrg  sfile.close()
101*36ac495dSmrg
102*36ac495dSmrg  # Ignore the initial #ifdef HEADER_H in header files
103*36ac495dSmrg  if filen[-2:] == ".h":
104*36ac495dSmrg    nest = -1
105*36ac495dSmrg    header = True
106*36ac495dSmrg  else:
107*36ac495dSmrg    nest = 0
108*36ac495dSmrg
109*36ac495dSmrg  macout = list ()
110*36ac495dSmrg  macin = list()
111*36ac495dSmrg  incl = list()
112*36ac495dSmrg  cond_incl = list()
113*36ac495dSmrg  src_line = { }
114*36ac495dSmrg  guard = ""
115*36ac495dSmrg
116*36ac495dSmrg  for line in (data):
117*36ac495dSmrg    if is_pound_if (line):
118*36ac495dSmrg      nest += 1
119*36ac495dSmrg    elif is_pound_endif (line):
120*36ac495dSmrg      nest -= 1
121*36ac495dSmrg
122*36ac495dSmrg    nm = find_pound_include (line, True, True)
123*36ac495dSmrg    if nm != "" and nm not in incl and nm[-2:] == ".h":
124*36ac495dSmrg      incl.append (nm)
125*36ac495dSmrg      if nest > 0:
126*36ac495dSmrg        cond_incl.append (nm)
127*36ac495dSmrg      if keep_src:
128*36ac495dSmrg        src_line[nm] = line
129*36ac495dSmrg      continue
130*36ac495dSmrg
131*36ac495dSmrg    if do_macros:
132*36ac495dSmrg      d = find_pound_define (line)
133*36ac495dSmrg      if d:
134*36ac495dSmrg        if d not in macout:
135*36ac495dSmrg          macout.append (d);
136*36ac495dSmrg          continue
137*36ac495dSmrg
138*36ac495dSmrg      d = find_pound_if (line)
139*36ac495dSmrg      if d:
140*36ac495dSmrg        # The first #if in a header file should be the guard
141*36ac495dSmrg        if header and len (d) == 1 and guard == "":
142*36ac495dSmrg          if d[0][-2:] == "_H":
143*36ac495dSmrg            guard = d
144*36ac495dSmrg          else:
145*36ac495dSmrg            guard = "Guess there was no guard..."
146*36ac495dSmrg        else:
147*36ac495dSmrg          for mac in d:
148*36ac495dSmrg            if mac != "defined" and mac not in macin:
149*36ac495dSmrg              macin.append (mac);
150*36ac495dSmrg
151*36ac495dSmrg  if not keep_src:
152*36ac495dSmrg    data = list()
153*36ac495dSmrg
154*36ac495dSmrg  return (os.path.basename (filen), os.path.dirname (filen), incl, cond_incl,
155*36ac495dSmrg          macin, macout, data, src_line)
156*36ac495dSmrg
157*36ac495dSmrg# Extract header info, but no macros or source code.
158*36ac495dSmrgdef process_ii (filen):
159*36ac495dSmrg  return process_include_info (filen, False, False)
160*36ac495dSmrg
161*36ac495dSmrg# Extract header information, and collect macro information.
162*36ac495dSmrgdef process_ii_macro (filen):
163*36ac495dSmrg  return process_include_info (filen, True, False)
164*36ac495dSmrg
165*36ac495dSmrg# Extract header information, cache the source lines.
166*36ac495dSmrgdef process_ii_src (filen):
167*36ac495dSmrg  return process_include_info (filen, False, True)
168*36ac495dSmrg
169*36ac495dSmrg# Extract header information, coolewc macro info and cache the source lines.
170*36ac495dSmrgdef process_ii_macro_src (filen):
171*36ac495dSmrg  return process_include_info (filen, True, True)
172*36ac495dSmrg
173*36ac495dSmrg
174*36ac495dSmrgdef ii_base (iinfo):
175*36ac495dSmrg  return iinfo[0]
176*36ac495dSmrg
177*36ac495dSmrgdef ii_path (iinfo):
178*36ac495dSmrg  return iinfo[1]
179*36ac495dSmrg
180*36ac495dSmrgdef ii_include_list (iinfo):
181*36ac495dSmrg  return iinfo[2]
182*36ac495dSmrg
183*36ac495dSmrgdef ii_include_list_cond (iinfo):
184*36ac495dSmrg  return iinfo[3]
185*36ac495dSmrg
186*36ac495dSmrgdef ii_include_list_non_cond (iinfo):
187*36ac495dSmrg  l = ii_include_list (iinfo)
188*36ac495dSmrg  for n in ii_include_list_cond (iinfo):
189*36ac495dSmrg    l.remove (n)
190*36ac495dSmrg  return l
191*36ac495dSmrg
192*36ac495dSmrgdef ii_macro_consume (iinfo):
193*36ac495dSmrg  return iinfo[4]
194*36ac495dSmrg
195*36ac495dSmrgdef ii_macro_define (iinfo):
196*36ac495dSmrg  return iinfo[5]
197*36ac495dSmrg
198*36ac495dSmrgdef ii_src (iinfo):
199*36ac495dSmrg  return iinfo[6]
200*36ac495dSmrg
201*36ac495dSmrgdef ii_src_line (iinfo):
202*36ac495dSmrg  return iinfo[7]
203*36ac495dSmrg
204*36ac495dSmrgdef ii_read (fname):
205*36ac495dSmrg  f = open (fname, 'rb')
206*36ac495dSmrg  incl = pickle.load (f)
207*36ac495dSmrg  consumes = pickle.load (f)
208*36ac495dSmrg  defines = pickle.load (f)
209*36ac495dSmrg  obj = (fname,fname,incl,list(), list(), consumes, defines, list(), list())
210*36ac495dSmrg  return obj
211*36ac495dSmrg
212*36ac495dSmrgdef ii_write (fname, obj):
213*36ac495dSmrg  f = open (fname, 'wb')
214*36ac495dSmrg  pickle.dump (obj[2], f)
215*36ac495dSmrg  pickle.dump (obj[4], f)
216*36ac495dSmrg  pickle.dump (obj[5], f)
217*36ac495dSmrg  f.close ()
218*36ac495dSmrg
219*36ac495dSmrg# execute a system command which returns file names
220*36ac495dSmrgdef execute_command (command):
221*36ac495dSmrg  files = list()
222*36ac495dSmrg  f = os.popen (command)
223*36ac495dSmrg  for x in f:
224*36ac495dSmrg    if x[0:2] == "./":
225*36ac495dSmrg      fn = x.rstrip()[2:]
226*36ac495dSmrg    else:
227*36ac495dSmrg      fn = x.rstrip()
228*36ac495dSmrg    files.append(fn)
229*36ac495dSmrg  return files
230*36ac495dSmrg
231*36ac495dSmrg# Try to locate a build directory from PATH
232*36ac495dSmrgdef find_gcc_bld_dir (path):
233*36ac495dSmrg  blddir = ""
234*36ac495dSmrg  # Look for blddir/gcc/tm.h
235*36ac495dSmrg  command = "find " + path + " -mindepth 2 -maxdepth 3 -name tm.h"
236*36ac495dSmrg  files = execute_command (command)
237*36ac495dSmrg  for y in files:
238*36ac495dSmrg    p = os.path.dirname (y)
239*36ac495dSmrg    if os.path.basename (p) == "gcc":
240*36ac495dSmrg      blddir = p
241*36ac495dSmrg      break
242*36ac495dSmrg  # If not found, try looking a bit deeper
243*36ac495dSmrg  # Dont look this deep initially because a lot of cross target builds may show
244*36ac495dSmrg  # up in the list before a native build... but those are better than nothing.
245*36ac495dSmrg  if not blddir:
246*36ac495dSmrg    command = "find " + path + " -mindepth 3 -maxdepth 5 -name tm.h"
247*36ac495dSmrg    files = execute_command (command)
248*36ac495dSmrg    for y in files:
249*36ac495dSmrg      p = os.path.dirname (y)
250*36ac495dSmrg      if os.path.basename (p) == "gcc":
251*36ac495dSmrg	blddir = p
252*36ac495dSmrg	break
253*36ac495dSmrg
254*36ac495dSmrg  return blddir
255*36ac495dSmrg
256*36ac495dSmrg
257*36ac495dSmrg# Find files matching pattern NAME, return in a list.
258*36ac495dSmrg# CURRENT is True if you want to include the current directory
259*36ac495dSmrg# DEEPER is True if you want to search 3 levels below the current directory
260*36ac495dSmrg# any files with testsuite diurectories are ignored
261*36ac495dSmrg
262*36ac495dSmrgdef find_gcc_files (name, current, deeper):
263*36ac495dSmrg  files = list()
264*36ac495dSmrg  command = ""
265*36ac495dSmrg  if current:
266*36ac495dSmrg    if not deeper:
267*36ac495dSmrg      command = "find -maxdepth 1 -name " + name + " -not -path \"./testsuite/*\""
268*36ac495dSmrg    else:
269*36ac495dSmrg      command = "find -maxdepth 4 -name " + name + " -not -path \"./testsuite/*\""
270*36ac495dSmrg  else:
271*36ac495dSmrg    if deeper:
272*36ac495dSmrg      command = "find -maxdepth 4 -mindepth 2 -name " + name + " -not -path \"./testsuite/*\""
273*36ac495dSmrg
274*36ac495dSmrg  if command != "":
275*36ac495dSmrg    files = execute_command (command)
276*36ac495dSmrg
277*36ac495dSmrg  return files
278*36ac495dSmrg
279*36ac495dSmrg# find the list of unique include names found in a file.
280*36ac495dSmrgdef find_unique_include_list_src (data):
281*36ac495dSmrg  found = list ()
282*36ac495dSmrg  for line in data:
283*36ac495dSmrg    d = find_pound_include (line, True, True)
284*36ac495dSmrg    if d and d not in found and d[-2:] == ".h":
285*36ac495dSmrg      found.append (d)
286*36ac495dSmrg  return found
287*36ac495dSmrg
288*36ac495dSmrg# find the list of unique include names found in a file.
289*36ac495dSmrgdef find_unique_include_list (filen):
290*36ac495dSmrg  data = open (filen).read().splitlines()
291*36ac495dSmrg  return find_unique_include_list_src (data)
292*36ac495dSmrg
293*36ac495dSmrg
294*36ac495dSmrg# Create the macin, macout, and incl vectors for a file FILEN.
295*36ac495dSmrg# macin are the macros that are used in #if* conditional expressions
296*36ac495dSmrg# macout are the macros which are #defined
297*36ac495dSmrg# incl is the list of incluide files encountered
298*36ac495dSmrg# returned as a tuple of the filename followed by the triplet of lists
299*36ac495dSmrg# (filen, macin, macout, incl)
300*36ac495dSmrg
301*36ac495dSmrgdef create_macro_in_out (filen):
302*36ac495dSmrg  sfile = open (filen, "r");
303*36ac495dSmrg  data = sfile.readlines()
304*36ac495dSmrg  sfile.close()
305*36ac495dSmrg
306*36ac495dSmrg  macout = list ()
307*36ac495dSmrg  macin = list()
308*36ac495dSmrg  incl = list()
309*36ac495dSmrg
310*36ac495dSmrg  for line in (data):
311*36ac495dSmrg    d = find_pound_define (line)
312*36ac495dSmrg    if d != "":
313*36ac495dSmrg      if d not in macout:
314*36ac495dSmrg        macout.append (d);
315*36ac495dSmrg      continue
316*36ac495dSmrg
317*36ac495dSmrg    d = find_pound_if (line)
318*36ac495dSmrg    if len(d) != 0:
319*36ac495dSmrg      for mac in d:
320*36ac495dSmrg        if mac != "defined" and mac not in macin:
321*36ac495dSmrg          macin.append (mac);
322*36ac495dSmrg      continue
323*36ac495dSmrg
324*36ac495dSmrg    nm = find_pound_include (line, True, True)
325*36ac495dSmrg    if nm != "" and nm not in incl:
326*36ac495dSmrg      incl.append (nm)
327*36ac495dSmrg
328*36ac495dSmrg  return (filen, macin, macout, incl)
329*36ac495dSmrg
330*36ac495dSmrg# create the macro information for filen, and create .macin, .macout, and .incl
331*36ac495dSmrg# files.  Return the created macro tuple.
332*36ac495dSmrgdef create_include_data_files (filen):
333*36ac495dSmrg
334*36ac495dSmrg  macros = create_macro_in_out (filen)
335*36ac495dSmrg  depends = macros[1]
336*36ac495dSmrg  defines = macros[2]
337*36ac495dSmrg  incls = macros[3]
338*36ac495dSmrg
339*36ac495dSmrg  disp_message = filen
340*36ac495dSmrg  if len (defines) > 0:
341*36ac495dSmrg    disp_message = disp_message + " " + str(len (defines)) + " #defines"
342*36ac495dSmrg  dfile = open (filen + ".macout", "w")
343*36ac495dSmrg  for x in defines:
344*36ac495dSmrg    dfile.write (x + "\n")
345*36ac495dSmrg  dfile.close ()
346*36ac495dSmrg
347*36ac495dSmrg  if len (depends) > 0:
348*36ac495dSmrg    disp_message = disp_message + " " + str(len (depends)) + " #if dependencies"
349*36ac495dSmrg  dfile = open (filen + ".macin", "w")
350*36ac495dSmrg  for x in depends:
351*36ac495dSmrg    dfile.write (x + "\n")
352*36ac495dSmrg  dfile.close ()
353*36ac495dSmrg
354*36ac495dSmrg  if len (incls) > 0:
355*36ac495dSmrg    disp_message = disp_message + " " + str(len (incls)) + " #includes"
356*36ac495dSmrg  dfile = open (filen + ".incl", "w")
357*36ac495dSmrg  for x in incls:
358*36ac495dSmrg    dfile.write (x + "\n")
359*36ac495dSmrg  dfile.close ()
360*36ac495dSmrg
361*36ac495dSmrg  return macros
362*36ac495dSmrg
363*36ac495dSmrg
364*36ac495dSmrg
365*36ac495dSmrg# extract data for include file name_h and enter it into the dictionary.
366*36ac495dSmrg# this does not change once read in.  use_requires is True if you want to
367*36ac495dSmrg# prime the values with already created .requires and .provides files.
368*36ac495dSmrgdef get_include_data (name_h, use_requires):
369*36ac495dSmrg  macin = list()
370*36ac495dSmrg  macout = list()
371*36ac495dSmrg  incl = list ()
372*36ac495dSmrg  if use_requires and os.path.exists (name_h + ".requires"):
373*36ac495dSmrg    macin = open (name_h + ".requires").read().splitlines()
374*36ac495dSmrg  elif os.path.exists (name_h + ".macin"):
375*36ac495dSmrg    macin = open (name_h + ".macin").read().splitlines()
376*36ac495dSmrg
377*36ac495dSmrg  if use_requires and os.path.exists (name_h + ".provides"):
378*36ac495dSmrg    macout  = open (name_h + ".provides").read().splitlines()
379*36ac495dSmrg  elif os.path.exists (name_h + ".macout"):
380*36ac495dSmrg    macout  = open (name_h + ".macout").read().splitlines()
381*36ac495dSmrg
382*36ac495dSmrg  if os.path.exists (name_h + ".incl"):
383*36ac495dSmrg    incl = open (name_h + ".incl").read().splitlines()
384*36ac495dSmrg
385*36ac495dSmrg  if len(macin) == 0 and len(macout) == 0 and len(incl) == 0:
386*36ac495dSmrg    return ()
387*36ac495dSmrg  data = ( name_h, macin, macout, incl )
388*36ac495dSmrg  return data
389*36ac495dSmrg
390*36ac495dSmrg# find FIND in src, and replace it with the list of headers in REPLACE.
391*36ac495dSmrg# Remove any duplicates of FIND in REPLACE, and if some of the REPLACE
392*36ac495dSmrg# headers occur earlier in the include chain, leave them.
393*36ac495dSmrg# Return the new SRC only if anything changed.
394*36ac495dSmrgdef find_replace_include (find, replace, src):
395*36ac495dSmrg  res = list()
396*36ac495dSmrg  seen = { }
397*36ac495dSmrg  anything = False
398*36ac495dSmrg  for line in src:
399*36ac495dSmrg    inc = find_pound_include (line, True, True)
400*36ac495dSmrg    if inc == find:
401*36ac495dSmrg      for y in replace:
402*36ac495dSmrg        if seen.get(y) == None:
403*36ac495dSmrg          res.append("#include \""+y+"\"\n")
404*36ac495dSmrg          seen[y] = True
405*36ac495dSmrg          if y != find:
406*36ac495dSmrg            anything = True
407*36ac495dSmrg# if find isnt in the replacement list, then we are deleting FIND, so changes.
408*36ac495dSmrg      if find not in replace:
409*36ac495dSmrg        anything = True
410*36ac495dSmrg    else:
411*36ac495dSmrg      if inc in replace:
412*36ac495dSmrg        if seen.get(inc) == None:
413*36ac495dSmrg          res.append (line)
414*36ac495dSmrg          seen[inc] = True
415*36ac495dSmrg      else:
416*36ac495dSmrg        res.append (line)
417*36ac495dSmrg
418*36ac495dSmrg  if (anything):
419*36ac495dSmrg    return res
420*36ac495dSmrg  else:
421*36ac495dSmrg    return list()
422*36ac495dSmrg
423*36ac495dSmrg
424*36ac495dSmrg# pass in a require and provide dictionary to be read in.
425*36ac495dSmrgdef read_require_provides (require, provide):
426*36ac495dSmrg  if not os.path.exists ("require-provide.master"):
427*36ac495dSmrg    print "require-provide.master file is not available. please run data collection."
428*36ac495dSmrg    sys.exit(1)
429*36ac495dSmrg  incl_list = open("require-provide.master").read().splitlines()
430*36ac495dSmrg  for f in incl_list:
431*36ac495dSmrg    if os.path.exists (f+".requires"):
432*36ac495dSmrg      require[os.path.basename (f)] = open (f + ".requires").read().splitlines()
433*36ac495dSmrg    else:
434*36ac495dSmrg      require[os.path.basename (f)] = list ()
435*36ac495dSmrg    if os.path.exists (f+".provides"):
436*36ac495dSmrg      provide[os.path.basename (f)] = open (f + ".provides").read().splitlines()
437*36ac495dSmrg    else:
438*36ac495dSmrg      provide [os.path.basename (f)] = list ()
439*36ac495dSmrg
440*36ac495dSmrg
441*36ac495dSmrgdef build_include_list (filen):
442*36ac495dSmrg  include_files = list()
443*36ac495dSmrg  sfile = open (filen, "r")
444*36ac495dSmrg  data = sfile.readlines()
445*36ac495dSmrg  sfile.close()
446*36ac495dSmrg  for line in data:
447*36ac495dSmrg    nm = find_pound_include (line, False, False)
448*36ac495dSmrg    if nm != "" and nm[-2:] == ".h":
449*36ac495dSmrg      if nm not in include_files:
450*36ac495dSmrg        include_files.append(nm)
451*36ac495dSmrg  return include_files
452*36ac495dSmrg
453*36ac495dSmrgdef build_reverse_include_list (filen):
454*36ac495dSmrg  include_files = list()
455*36ac495dSmrg  sfile = open (filen, "r")
456*36ac495dSmrg  data = sfile.readlines()
457*36ac495dSmrg  sfile.close()
458*36ac495dSmrg  for line in reversed(data):
459*36ac495dSmrg    nm = find_pound_include (line, False, False)
460*36ac495dSmrg    if nm != "":
461*36ac495dSmrg      if nm not in include_files:
462*36ac495dSmrg        include_files.append(nm)
463*36ac495dSmrg  return include_files
464*36ac495dSmrg
465*36ac495dSmrg# Get compilation return code, and compensate for a warning that we want to
466*36ac495dSmrg# consider an error when it comes to inlined templates.
467*36ac495dSmrgdef get_make_rc (rc, output):
468*36ac495dSmrg  rc = rc % 1280
469*36ac495dSmrg  if rc == 0:
470*36ac495dSmrg    # This is not considered an error during compilation of an individual file,
471*36ac495dSmrg    # but it will cause an error during link if it isn't defined.  If this
472*36ac495dSmrg    # warning is seen during compiling a file, make it a build error so we
473*36ac495dSmrg    # don't remove the header.
474*36ac495dSmrg    h = re.findall ("warning: inline function.*used but never defined", output)
475*36ac495dSmrg    if len(h) != 0:
476*36ac495dSmrg      rc = 1
477*36ac495dSmrg  return rc;
478*36ac495dSmrg
479*36ac495dSmrgdef get_make_output (build_dir, make_opt):
480*36ac495dSmrg  devnull = open('/dev/null', 'w')
481*36ac495dSmrg  at_a_time = multiprocessing.cpu_count() * 2
482*36ac495dSmrg  make = "make -j"+str(at_a_time)+ " "
483*36ac495dSmrg  if build_dir != "":
484*36ac495dSmrg    command = "cd " + build_dir +"; " + make + make_opt
485*36ac495dSmrg  else:
486*36ac495dSmrg    command = make + make_opt
487*36ac495dSmrg  process = subprocess.Popen(command, stdout=devnull, stderr=subprocess.PIPE, shell=True)
488*36ac495dSmrg  output = process.communicate();
489*36ac495dSmrg  rc = get_make_rc (process.returncode, output[1])
490*36ac495dSmrg  return (rc , output[1])
491*36ac495dSmrg
492*36ac495dSmrgdef spawn_makes (command_list):
493*36ac495dSmrg  devnull = open('/dev/null', 'w')
494*36ac495dSmrg  rc = (0,"", "")
495*36ac495dSmrg  proc_res = list()
496*36ac495dSmrg  text = "  Trying target builds : "
497*36ac495dSmrg  for command_pair in command_list:
498*36ac495dSmrg    tname = command_pair[0]
499*36ac495dSmrg    command = command_pair[1]
500*36ac495dSmrg    text += tname + ", "
501*36ac495dSmrg    c = subprocess.Popen(command, bufsize=-1, stdout=devnull, stderr=subprocess.PIPE, shell=True)
502*36ac495dSmrg    proc_res.append ((c, tname))
503*36ac495dSmrg
504*36ac495dSmrg  print text[:-2]
505*36ac495dSmrg
506*36ac495dSmrg  for p in proc_res:
507*36ac495dSmrg    output = p[0].communicate()
508*36ac495dSmrg    ret = (get_make_rc (p[0].returncode, output[1]), output[1], p[1])
509*36ac495dSmrg    if (ret[0] != 0):
510*36ac495dSmrg      # Just record the first one.
511*36ac495dSmrg      if rc[0] == 0:
512*36ac495dSmrg        rc = ret;
513*36ac495dSmrg  return rc
514*36ac495dSmrg
515*36ac495dSmrgdef get_make_output_parallel (targ_list, make_opt, at_a_time):
516*36ac495dSmrg  command = list()
517*36ac495dSmrg  targname = list()
518*36ac495dSmrg  if at_a_time == 0:
519*36ac495dSmrg    at_a_time = multiprocessing.cpu_count() * 2
520*36ac495dSmrg  proc_res = [0] * at_a_time
521*36ac495dSmrg  for x in targ_list:
522*36ac495dSmrg    if make_opt[-2:] == ".o":
523*36ac495dSmrg      s = "cd " + x[1] + "/gcc/; make " + make_opt
524*36ac495dSmrg    else:
525*36ac495dSmrg      s = "cd " + x[1] +"; make " + make_opt
526*36ac495dSmrg    command.append ((x[0],s))
527*36ac495dSmrg
528*36ac495dSmrg  num = len(command)
529*36ac495dSmrg  rc = (0,"", "")
530*36ac495dSmrg  loops = num // at_a_time
531*36ac495dSmrg
532*36ac495dSmrg  if (loops > 0):
533*36ac495dSmrg    for idx in range (loops):
534*36ac495dSmrg      ret = spawn_makes (command[idx*at_a_time:(idx+1)*at_a_time])
535*36ac495dSmrg      if ret[0] != 0:
536*36ac495dSmrg        rc = ret
537*36ac495dSmrg        break
538*36ac495dSmrg
539*36ac495dSmrg  if (rc[0] == 0):
540*36ac495dSmrg    leftover = num % at_a_time
541*36ac495dSmrg    if (leftover > 0):
542*36ac495dSmrg      ret = spawn_makes (command[-leftover:])
543*36ac495dSmrg      if ret[0] != 0:
544*36ac495dSmrg        rc = ret
545*36ac495dSmrg
546*36ac495dSmrg  return rc
547*36ac495dSmrg
548*36ac495dSmrg
549*36ac495dSmrgdef readwholefile (src_file):
550*36ac495dSmrg  sfile = open (src_file, "r")
551*36ac495dSmrg  src_data = sfile.readlines()
552*36ac495dSmrg  sfile.close()
553*36ac495dSmrg  return src_data
554*36ac495dSmrg
555