OSDN Git Service

original
[gb-231r1-is01/Gingerbread_2.3.3_r1_IS01.git] / bionic / libc / kernel / tools / utils.py
1 # common python utility routines for the Bionic tool scripts
2
3 import sys, os, commands, string, commands
4
5 # basic debugging trace support
6 # call D_setlevel to set the verbosity level
7 # and D(), D2(), D3(), D4() to add traces
8 #
9 verbose = 0
10
11 def panic(msg):
12     sys.stderr.write( find_program_name() + ": error: " )
13     sys.stderr.write( msg )
14     sys.exit(1)
15
16 def D(msg):
17     global verbose
18     if verbose > 0:
19         print msg
20
21 def D2(msg):
22     global verbose
23     if verbose >= 2:
24         print msg
25
26 def D3(msg):
27     global verbose
28     if verbose >= 3:
29         print msg
30
31 def D4(msg):
32     global verbose
33     if verbose >= 4:
34         print msg
35
36 def D_setlevel(level):
37     global verbose
38     verbose = level
39
40
41 #  other stuff
42 #
43 #
44 def find_program_name():
45     return os.path.basename(sys.argv[0])
46
47 def find_program_dir():
48     return os.path.dirname(sys.argv[0])
49
50 def find_file_from_upwards(from_path,target_file):
51     """find a file in the current directory or its parents. if 'from_path' is None,
52        seach from the current program's directory"""
53     path = from_path
54     if path == None:
55         path = os.path.realpath(sys.argv[0])
56         path = os.path.dirname(path)
57         D("this script seems to be located in: %s" % path)
58
59     while 1:
60         D("probing "+path)
61         if path == "":
62             file = target_file
63         else:
64             file = path + "/" + target_file
65
66         if os.path.isfile(file):
67             D("found %s in %s" % (target_file, path))
68             return file
69
70         if path == "":
71             return None
72
73         path = os.path.dirname(path)
74
75 def find_bionic_root():
76     file = find_file_from_upwards(None, "SYSCALLS.TXT")
77     if file:
78         return os.path.dirname(file)
79     else:
80         return None
81
82 def find_kernel_headers():
83     """try to find the directory containing the kernel headers for this machine"""
84     status, version = commands.getstatusoutput( "uname -r" )  # get Linux kernel version
85     if status != 0:
86         D("could not execute 'uname -r' command properly")
87         return None
88
89     # get rid of the "-xenU" suffix that is found in Xen virtual machines
90     if len(version) > 5 and version[-5:] == "-xenU":
91         version = version[:-5]
92
93     path = "/usr/src/linux-headers-" + version
94     D("probing %s for kernel headers" % (path+"/include"))
95     ret = os.path.isdir( path )
96     if ret:
97         D("found kernel headers in: %s" % (path + "/include"))
98         return path
99     return None
100
101
102 # parser for the SYSCALLS.TXT file
103 #
104 class SysCallsTxtParser:
105     def __init__(self):
106         self.syscalls = []
107         self.lineno   = 0
108
109     def E(msg):
110         print "%d: %s" % (self.lineno, msg)
111
112     def parse_line(self, line):
113         pos_lparen = line.find('(')
114         E          = self.E
115         if pos_lparen < 0:
116             E("missing left parenthesis in '%s'" % line)
117             return
118
119         pos_rparen = line.rfind(')')
120         if pos_rparen < 0 or pos_rparen <= pos_lparen:
121             E("missing or misplaced right parenthesis in '%s'" % line)
122             return
123
124         return_type = line[:pos_lparen].strip().split()
125         if len(return_type) < 2:
126             E("missing return type in '%s'" % line)
127             return
128
129         syscall_func = return_type[-1]
130         return_type  = string.join(return_type[:-1],' ')
131
132         pos_colon = syscall_func.find(':')
133         if pos_colon < 0:
134             syscall_name = syscall_func
135         else:
136             if pos_colon == 0 or pos_colon+1 >= len(syscall_func):
137                 E("misplaced colon in '%s'" % line)
138                 return
139             syscall_name = syscall_func[pos_colon+1:]
140             syscall_func = syscall_func[:pos_colon]
141
142         if pos_rparen > pos_lparen+1:
143             syscall_params = line[pos_lparen+1:pos_rparen].split(',')
144             params         = string.join(syscall_params,',')
145         else:
146             syscall_params = []
147             params         = "void"
148
149         number = line[pos_rparen+1:].strip()
150         if number == "stub":
151             syscall_id  = -1
152             syscall_id2 = -1
153         else:
154             try:
155                 if number[0] == '#':
156                     number = number[1:].strip()
157                 numbers = string.split(number,',')
158                 syscall_id  = int(numbers[0])
159                 syscall_id2 = syscall_id
160                 if len(numbers) > 1:
161                     syscall_id2 = int(numbers[1])
162             except:
163                 E("invalid syscall number in '%s'" % line)
164                 return
165
166         t = { "id"     : syscall_id,
167               "id2"    : syscall_id2,
168               "name"   : syscall_name,
169               "func"   : syscall_func,
170               "params" : syscall_params,
171               "decl"   : "%-15s  %s (%s);" % (return_type, syscall_func, params) }
172
173         self.syscalls.append(t)
174
175     def parse_file(self, file_path):
176         fp = open(file_path)
177         for line in fp.xreadlines():
178             self.lineno += 1
179             line = line.strip()
180             if not line: continue
181             if line[0] == '#': continue
182             self.parse_line(line)
183
184         fp.close()
185
186
187 class Output:
188     def  __init__(self,out=sys.stdout):
189         self.out = out
190
191     def write(self,msg):
192         self.out.write(msg)
193
194     def writeln(self,msg):
195         self.out.write(msg)
196         self.out.write("\n")
197
198 class StringOutput:
199     def __init__(self):
200         self.line = ""
201
202     def write(self,msg):
203         self.line += msg
204         D2("write '%s'" % msg)
205
206     def writeln(self,msg):
207         self.line += msg + '\n'
208         D2("write '%s\\n'"% msg)
209
210     def get(self):
211         return self.line
212
213
214 def create_file_path(path):
215     dirs = []
216     while 1:
217         parent = os.path.dirname(path)
218         #print "parent: %s <- %s" % (parent, path)
219         if parent == "/" or parent == "":
220             break
221         dirs.append(parent)
222         path = parent
223
224     dirs.reverse()
225     for dir in dirs:
226         #print "dir %s" % dir
227         if os.path.isdir(dir):
228             continue
229         os.mkdir(dir)
230
231 def walk_source_files(paths,callback,args,excludes=[]):
232     """recursively walk a list of paths and files, only keeping the source files in directories"""
233     for path in paths:
234         if not os.path.isdir(path):
235             callback(path,args)
236         else:
237             for root, dirs, files in os.walk(path):
238                 #print "w-- %s (ex: %s)" % (repr((root,dirs)), repr(excludes))
239                 if len(excludes):
240                     for d in dirs[:]:
241                         if d in excludes:
242                             dirs.remove(d)
243                 for f in files:
244                     r, ext = os.path.splitext(f)
245                     if ext in [ ".h", ".c", ".cpp", ".S" ]:
246                         callback( "%s/%s" % (root,f), args )
247
248 def cleanup_dir(path):
249     """create a directory if needed, and ensure that it is totally empty
250        by removing any existing content in it"""
251     if not os.path.exists(path):
252         os.mkdir(path)
253     else:
254         for root, dirs, files in os.walk(path, topdown=False):
255             if root.endswith("kernel_headers/"):
256                 # skip 'kernel_headers'
257                 continue
258             for name in files:
259                 os.remove(os.path.join(root, name))
260             for name in dirs:
261                 os.rmdir(os.path.join(root, name))
262
263 def update_file( path, newdata ):
264     """update a file on disk, only if its content has changed"""
265     if os.path.exists( path ):
266         try:
267             f = open( path, "r" )
268             olddata = f.read()
269             f.close()
270         except:
271             D("update_file: cannot read existing file '%s'" % path)
272             return 0
273
274         if oldata == newdata:
275             D2("update_file: no change to file '%s'" % path )
276             return 0
277
278         update = 1
279     else:
280         try:
281             create_file_path(path)
282         except:
283             D("update_file: cannot create path to '%s'" % path)
284             return 0
285
286     f = open( path, "w" )
287     f.write( newdata )
288     f.close()
289
290     return 1
291
292
293 class BatchFileUpdater:
294     """a class used to edit several files at once"""
295     def __init__(self):
296         self.old_files = set()
297         self.new_files = set()
298         self.new_data  = {}
299
300     def readFile(self,path):
301         #path = os.path.realpath(path)
302         if os.path.exists(path):
303             self.old_files.add(path)
304
305     def readDir(self,path):
306         #path = os.path.realpath(path)
307         for root, dirs, files in os.walk(path):
308             for f in files:
309                 dst = "%s/%s" % (root,f)
310                 self.old_files.add(dst)
311
312     def editFile(self,dst,data):
313         """edit a destination file. if the file is not mapped from a source,
314            it will be added. return 0 if the file content wasn't changed,
315            1 if it was edited, or 2 if the file is new"""
316         #dst = os.path.realpath(dst)
317         result = 1
318         if os.path.exists(dst):
319             f = open(dst, "r")
320             olddata = f.read()
321             f.close()
322             if olddata == data:
323                 self.old_files.remove(dst)
324                 return 0
325         else:
326             result = 2
327
328         self.new_data[dst] = data
329         self.new_files.add(dst)
330         return result
331
332     def getChanges(self):
333         """determine changes, returns (adds, deletes, edits)"""
334         adds    = set()
335         edits   = set()
336         deletes = set()
337
338         for dst in self.new_files:
339             if not (dst in self.old_files):
340                 adds.add(dst)
341             else:
342                 edits.add(dst)
343
344         for dst in self.old_files:
345             if not dst in self.new_files:
346                 deletes.add(dst)
347
348         return (adds, deletes, edits)
349
350     def _writeFile(self,dst,data=None):
351         if not os.path.exists(os.path.dirname(dst)):
352             create_file_path(dst)
353         if data == None:
354             data = self.new_data[dst]
355         f = open(dst, "w")
356         f.write(self.new_data[dst])
357         f.close()
358
359     def updateFiles(self):
360         adds, deletes, edits = self.getChanges()
361
362         for dst in sorted(adds):
363             self._writeFile(dst)
364
365         for dst in sorted(edits):
366             self._writeFile(dst)
367
368         for dst in sorted(deletes):
369             os.remove(dst)
370
371     def updateP4Files(self):
372         adds, deletes, edits = self.getChanges()
373
374         if len(adds):
375             files = string.join(sorted(adds)," ")
376             D( "%d new files will be p4 add-ed" % len(adds) )
377             for dst in adds:
378                 self._writeFile(dst)
379             D2("P4 ADDS: %s" % files)
380             o = commands.getoutput( "p4 add " + files )
381             D2( o )
382
383         if len(edits):
384             files = string.join(sorted(edits)," ")
385             D( "%d files will be p4 edit-ed" % len(edits) )
386             D2("P4 EDITS: %s" % files)
387             o = commands.getoutput( "p4 edit " + files )
388             D2( o )
389             for dst in edits:
390                 self._writeFile(dst)
391
392         if len(deletes):
393             files = string.join(sorted(deletes)," ")
394             D( "%d files will be p4 delete-d" % len(deletes) )
395             D2("P4 DELETES: %s" % files)
396             o = commands.getoutput( "p4 delete " + files )
397             D2( o )