OSDN Git Service

original
[gb-231r1-is01/Gingerbread_2.3.3_r1_IS01.git] / bionic / libc / tools / bionic_utils.py
1 # common python utility routines for the Bionic tool scripts
2
3 import sys, os, commands, string
4
5 # support Bionic architectures, add new ones as appropriate
6 #
7 bionic_archs = [ "arm", "x86" ]
8
9 # basic debugging trace support
10 # call D_setlevel to set the verbosity level
11 # and D(), D2(), D3(), D4() to add traces
12 #
13 verbose = 1
14
15 def D(msg):
16     global verbose
17     if verbose > 0:
18         print msg
19
20 def D2(msg):
21     global verbose
22     if verbose >= 2:
23         print msg
24
25 def D3(msg):
26     global verbose
27     if verbose >= 3:
28         print msg
29
30 def D4(msg):
31     global verbose
32     if verbose >= 4:
33         print msg
34
35 def D_setlevel(level):
36     global verbose
37     verbose = level
38
39
40 def find_dir_of(path):
41     '''return the directory name of 'path', or "." if there is none'''
42     # remove trailing slash
43     if len(path) > 1 and path[-1] == '/':
44         path = path[:-1]
45
46     # find parent directory name
47     d = os.path.dirname(path)
48     if d == "":
49         return "."
50     else:
51         return d
52
53 #  other stuff
54 #
55 #
56 def find_file_from_upwards(from_path,target_file):
57     """find a file in the current directory or its parents. if 'from_path' is None,
58        seach from the current program's directory"""
59     path = from_path
60     if path == None:
61         path = find_dir_of(sys.argv[0])
62         D("this script seems to be located in: %s" % path)
63
64     while 1:
65         if path == "":
66             path = "."
67
68         file = path + "/" + target_file
69         D("probing "+file)
70
71         if os.path.isfile(file):
72             D("found %s in %s" % (target_file, path))
73             return file
74
75         if path == ".":
76             break
77
78         path = os.path.dirname(path)
79
80     path = ""
81     while 1:
82         path = "../" + path
83         file = path + target_file
84         D("probing "+file)
85
86         if os.path.isfile(file):
87             D("found %s in %s" % (target_file, path))
88             return file
89
90
91     return None
92
93 def find_bionic_root():
94     '''find the root of the Bionic source tree. we check for the SYSCALLS.TXT file
95        from the location of the current program's directory.'''
96
97     # note that we can't use find_file_from_upwards() since we can't use os.path.abspath
98     # that's because in some cases the p4 client is in a symlinked directory, and this
99     # function will return the real path instead, which later creates problems when
100     # p4 commands are issued
101     #
102     file = find_file_from_upwards(None, "SYSCALLS.TXT")
103     if file:
104         return os.path.dirname(file)
105     else:
106         return None
107
108 def find_kernel_headers():
109     """try to find the directory containing the kernel headers for this machine"""
110     status, version = commands.getstatusoutput( "uname -r" )  # get Linux kernel version
111     if status != 0:
112         D("could not execute 'uname -r' command properly")
113         return None
114
115     # get rid of the "-xenU" suffix that is found in Xen virtual machines
116     if len(version) > 5 and version[-5:] == "-xenU":
117         version = version[:-5]
118
119     path = "/usr/src/linux-headers-" + version
120     D("probing %s for kernel headers" % (path+"/include"))
121     ret = os.path.isdir( path )
122     if ret:
123         D("found kernel headers in: %s" % (path + "/include"))
124         return path
125     return None
126
127
128 # parser for the SYSCALLS.TXT file
129 #
130 class SysCallsTxtParser:
131     def __init__(self):
132         self.syscalls = []
133         self.lineno   = 0
134
135     def E(msg):
136         print "%d: %s" % (self.lineno, msg)
137
138     def parse_line(self, line):
139         """ parse a syscall spec line.
140
141         line processing, format is
142            return type    func_name[:syscall_name[:call_id]] ( [paramlist] )   (syscall_number[,syscall_number_x86])|stub
143         """
144         pos_lparen = line.find('(')
145         E          = self.E
146         if pos_lparen < 0:
147             E("missing left parenthesis in '%s'" % line)
148             return
149
150         pos_rparen = line.rfind(')')
151         if pos_rparen < 0 or pos_rparen <= pos_lparen:
152             E("missing or misplaced right parenthesis in '%s'" % line)
153             return
154
155         return_type = line[:pos_lparen].strip().split()
156         if len(return_type) < 2:
157             E("missing return type in '%s'" % line)
158             return
159
160         syscall_func = return_type[-1]
161         return_type  = string.join(return_type[:-1],' ')
162         call_id = -1
163
164         pos_colon = syscall_func.find(':')
165         if pos_colon < 0:
166             syscall_name = syscall_func
167         else:
168             if pos_colon == 0 or pos_colon+1 >= len(syscall_func):
169                 E("misplaced colon in '%s'" % line)
170                 return
171
172             # now find if there is a call_id for a dispatch-type syscall
173             # after the optional 2nd colon
174             pos_colon2 = syscall_func.find(':', pos_colon + 1)
175             if pos_colon2 < 0:
176                 syscall_name = syscall_func[pos_colon+1:]
177                 syscall_func = syscall_func[:pos_colon]
178             else:
179                 if pos_colon2+1 >= len(syscall_func):
180                     E("misplaced colon2 in '%s'" % line)
181                     return
182                 syscall_name = syscall_func[(pos_colon+1):pos_colon2]
183                 call_id = int(syscall_func[pos_colon2+1:])
184                 syscall_func = syscall_func[:pos_colon]
185
186         if pos_rparen > pos_lparen+1:
187             syscall_params = line[pos_lparen+1:pos_rparen].split(',')
188             params         = string.join(syscall_params,',')
189         else:
190             syscall_params = []
191             params         = "void"
192
193         number = line[pos_rparen+1:].strip()
194         if number == "stub":
195             syscall_id  = -1
196             syscall_id2 = -1
197             syscall_id3 = -1
198         else:
199             try:
200                 if number[0] == '#':
201                     number = number[1:].strip()
202                 numbers = string.split(number,',')
203                 syscall_id  = int(numbers[0])
204                 syscall_id2 = syscall_id
205                 syscall_id3 = syscall_id
206                 if len(numbers) > 1:
207                     syscall_id2 = int(numbers[1])
208                     syscall_id3 = syscall_id2
209                 if len(numbers) > 2:
210                     syscall_id3 = int(numbers[2])
211             except:
212                 E("invalid syscall number in '%s'" % line)
213                 return
214
215         print str(syscall_id) + ':' + str(syscall_id2) + ':' + str(syscall_id3)
216
217         t = { "id"     : syscall_id,
218               "id2"    : syscall_id2,
219               "id3"    : syscall_id3,
220               "cid"    : call_id,
221               "name"   : syscall_name,
222               "func"   : syscall_func,
223               "params" : syscall_params,
224               "decl"   : "%-15s  %s (%s);" % (return_type, syscall_func, params) }
225
226         self.syscalls.append(t)
227
228     def parse_file(self, file_path):
229         D2("parse_file: %s" % file_path)
230         fp = open(file_path)
231         for line in fp.xreadlines():
232             self.lineno += 1
233             line = line.strip()
234             if not line: continue
235             if line[0] == '#': continue
236             self.parse_line(line)
237
238         fp.close()
239
240
241 class Output:
242     def  __init__(self,out=sys.stdout):
243         self.out = out
244
245     def write(self,msg):
246         self.out.write(msg)
247
248     def writeln(self,msg):
249         self.out.write(msg)
250         self.out.write("\n")
251
252 class StringOutput:
253     def __init__(self):
254         self.line = ""
255
256     def write(self,msg):
257         self.line += msg
258         D2("write '%s'" % msg)
259
260     def writeln(self,msg):
261         self.line += msg + '\n'
262         D2("write '%s\\n'"% msg)
263
264     def get(self):
265         return self.line
266
267
268 def create_file_path(path):
269     dirs = []
270     while 1:
271         parent = os.path.dirname(path)
272         if parent == "/":
273             break
274         dirs.append(parent)
275         path = parent
276
277     dirs.reverse()
278     for dir in dirs:
279         #print "dir %s" % dir
280         if os.path.isdir(dir):
281             continue
282         os.mkdir(dir)
283
284 def walk_source_files(paths,callback,args,excludes=[]):
285     """recursively walk a list of paths and files, only keeping the source files in directories"""
286     for path in paths:
287         if not os.path.isdir(path):
288             callback(path,args)
289         else:
290             for root, dirs, files in os.walk(path):
291                 #print "w-- %s (ex: %s)" % (repr((root,dirs)), repr(excludes))
292                 if len(excludes):
293                     for d in dirs[:]:
294                         if d in excludes:
295                             dirs.remove(d)
296                 for f in files:
297                     r, ext = os.path.splitext(f)
298                     if ext in [ ".h", ".c", ".cpp", ".S" ]:
299                         callback( "%s/%s" % (root,f), args )
300
301 def cleanup_dir(path):
302     """create a directory if needed, and ensure that it is totally empty
303        by removing any existing content in it"""
304     if not os.path.exists(path):
305         os.mkdir(path)
306     else:
307         for root, dirs, files in os.walk(path, topdown=False):
308             if root.endswith("kernel_headers/"):
309                 # skip 'kernel_headers'
310                 continue
311             for name in files:
312                 os.remove(os.path.join(root, name))
313             for name in dirs:
314                 os.rmdir(os.path.join(root, name))