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