1 #!/usr/bin/env python
2
3 import os, re, sys
4
5 class Cexploder():
6 Body = re.compile("{[^{}]*}", re.DOTALL|re.MULTILINE)
7 Func = re.compile("(\w+\s+)*\w+\s*\(.*?\)", re.DOTALL| re.MULTILINE)
8 MultiLineComment = re.compile("/\*.*?\*/", re.DOTALL|re.MULTILINE)
9 OneLineComment = re.compile("//.*?$", re.DOTALL|re.MULTILINE)
10 CppDirectives = re.compile("^\s*#.*?$", re.DOTALL|re.MULTILINE)
11 #^\s*#(.*?(\\\n)*)+\n
12
13 def __init__(self, File=''):
14 f = open(File, 'r')
15 self.data = f.read()
16 f.close()
17
18 def GetPrototypes(self):
19 FuncList = []
20 pdata = self.data
21 pdata = self.OneLineComment.sub('', pdata)
22 pdata = self.MultiLineComment.sub('', pdata)
23 pdata = self.CppDirectives.sub('', pdata)
24
25 while self.Body.search(pdata) != None:
26 pdata = self.Body.sub('', pdata)
27
28 fiter = self.Func.finditer(pdata)
29 for i in fiter:
30 FuncList.append( pdata[i.start() : i.end()] )
31
32 return FuncList
33
34 c = Cexploder(sys.argv[1])
35 f = c.GetPrototypes()
36 for i in f:
37 print i
This is my drop back to the open source comunity. It is devoted to Python, the language I find myself using quite often to just-do-the-job. My small trips and tricks while i'm using it, how i use it and what for. And things like that.
Friday, April 27, 2007
More on reg exps. Parsing a C or C++ file with regexps in Python
Ok, so while i'm on the regexp wave. It's plain dumb but works fine. I know i could have used ctags or smth else, but for the sake of it. Also I googled for an example like this one but found nothing. It's always a good idea to have smth like this i case you need to generate prototypes for a long C file or nomatter what.
Thursday, April 26, 2007
Regular expressions for fun and profit!
So the year is 2007 the century 21-th, but still there are ppl who deny using regular expressions to do the job. Why? I don't know. May be they just don't know how to do it, may be they think it's slow, or they just never heard of it. But it makes me sick looking at lame pseudo parsers their awkward logic and tons of stupid useless code around for something as simple as digging a file for a pattern. I've seen guys spending a day writing code that can be replaced with just one line using a regular expression, and why? Do they gain something out of this? Performance? Speed? No, they usualy do this for a lame script to automate something and they don't care much if it's gonna take 10mS ot a second. The truth is they realy don't know how much easier it just because they have never done it before.
So for all of them here's a example of a quick and dirty script I used to generate a report. It simply goes through every file in a directory and looks for the following pattern "/*#.*?#*/". It's a bracket structure taken as a comment within C files. It's simple and i use it to write stuff about something that later might end up in a report. Sometimes i write in there something like "See line 1923" or "Line 192" wich ofcourse means a reference to that line, that's why i made my script look for such patterns and if one exists it'll dump it.
So enough goofing around this is the script:
So you see in less than 100 lines I did it all. Parsing, referencing, generating a report in html. It took me less than 2 hours to finish this.
So for all of them here's a example of a quick and dirty script I used to generate a report. It simply goes through every file in a directory and looks for the following pattern "/*#.*?#*/". It's a bracket structure taken as a comment within C files. It's simple and i use it to write stuff about something that later might end up in a report. Sometimes i write in there something like "See line 1923" or "Line 192" wich ofcourse means a reference to that line, that's why i made my script look for such patterns and if one exists it'll dump it.
So enough goofing around this is the script:
1 #!/usr/bin/env python
2
3 import os, re, sys
4
5 Cover = re.compile("/\*\#.*?\#\*/", re.DOTALL|re.MULTILINE)
6 SeeAlso = re.compile("(see|line)+.*?\d+", re.DOTALL|re.MULTILINE|re.IGNORECASE)
7 Number = re.compile("\d+")
8
9 class Result:
10 pass
11
12 def GetLinesAround(Data = '', Line = 0, LinesAround = 5):
13 ret = ''
14 d = Data.split('\n')
15
16 if Line >= LinesAround/2:
17 upper = Line - LinesAround/2
18 else:
19 upper = 0;
20
21 lower = Line + LinesAround/2 + 1
22 if lower > d.__len__():
23 lower = d.__len__()
24
25 try:
26 d = d[upper : lower]
27 except Exception:
28 return ret
29
30 for s in d:
31 ret = ret + str(s) + '\n'
32
33 return ret
34
35 def GenUtReport(File = '', RelativePath=''):
36 f = open(File, 'r')
37 data = f.read()
38 f.close()
39
40 ret = []
41
42 utIter = Cover.finditer(data)
43 for i in utIter:
44 res = Result()
45
46 avLine = data[0:i.start()].count('\n') + (data[i.start():i.end()].count('\n')/2)
47
48 res.fInfo = "File: " + str(RelativePath) + " Line: " + str(avLine)
49 res.utInfo = data[i.start():i.end()].split(':')[1].replace('#*/', '')
50 res.codeAroundUt = GetLinesAround(data, avLine)
51
52 res.seeAlsoInfo = []
53 seeIter = SeeAlso.finditer(res.utInfo)
54 for si in seeIter:
55 seeLine = Number.findall(res.utInfo[si.start():si.end()])
56 if seeLine != None:
57 seeLine = seeLine[0]
58 res.seeAlsoInfo.append( ( seeLine, 10, GetLinesAround(data, int(seeLine), 10) ) )
59
60 ret.append(res)
61
62 return ret
63
64 def PrityPrint(ret = []):
65 tmpStr = ''
66
67 for res in ret:
68 tmpStr = tmpStr + "<tr>"
69 tmpStr = tmpStr + "<td>" + res.fInfo + "</td>"
70 tmpStr = tmpStr + "<td>" + res.utInfo + "</td>"
71 tmpStr = tmpStr + "<td>" + res.codeAroundUt + "</td>"
72 tmpStr = tmpStr + "<td>"
73 for i in res.seeAlsoInfo:
74 tmpStr = tmpStr + "See Also. Code around LINE: " + i[0] + " (+/-)"+ str(i[1]/2) +"\n\n"+ str(i[2])
75 tmpStr = tmpStr + "</td>"
76 tmpStr = tmpStr + "</tr>"
77
78 return tmpStr.replace('\n', '<br>')
79
80 tmpStr = """<html><head></head><body><table border="1">
81 <tr>
82 <td><b>Filename, Line number</b></td>
83 <td><b>UT not covered reason</b></td>
84 <td><b>Related code</b></td>
85 <td><b>See also</b></td>
86 </tr>"""
87
88 for r, d, f in os.walk(sys.argv[1]):
89 for file in f:
90 tmpStr = tmpStr + PrityPrint(GenUtReport( os.path.join(r, file) , file))
91
92 tmpStr = tmpStr + "</table></body></html>"
93 print tmpStr
So you see in less than 100 lines I did it all. Parsing, referencing, generating a report in html. It took me less than 2 hours to finish this.
Tuesday, March 6, 2007
FuzzXml
Ok si i was playing around the other day with a Jabber server written in java. I don't quite remember the name but it had a nice web configuration interface. I remember thinking "why not just throw some garbage at this little server of ours?" Yeah sounds like a nice idea! Lets proceede in python of course. First we know jabber is based on XML, second we know it can work without encryption. How much easier could it be? I made a list of all the xml files i could find in my home dir. From all the browsing on the net for this year and a half since i got this laptop i had a hell of alot of them. I did "cat" them all into one big.blob, then refined it with "strings" and the resulting pile of XML stored as good.blob.
serj@tokamak:~$ du -h good.blob
2.4M good.blob
Now all i need is a bit of python to make this work.
The idea is simple. Connect to the server build some random string of XML-ish garbage and send it back. And like this as fast as you can. And yeah lets spawn a couple of more in parallel.
As you can see i also included a server who can handle a client a time and send bad XML. I decided to test not just the server but the clients also.
The results? Well after about 10-30 seconds the java Jabber server eat about 1.2G ram and 98%cpu for more than 20 minutes (at least i killed it after 20 mins). The clients that i tested were examples from the XmlRpc++ library. The did handle the server without problems.
serj@tokamak:~$ du -h good.blob
2.4M good.blob
Now all i need is a bit of python to make this work.
#!/usr/bin/env python
import sys
import time
import random
import socket
import string
import threading
def fuzzFile(file, iter, chunkLen):
f = open(file, 'r')
data = f.read()
f.close()
retStr = ""
for i in range(0, int(iter)):
x = random.randint(0,data.__len__());
retStr = retStr + str( data[ x : x+random.randint(0, int(chunkLen)) ] ) + "\n\n"
for i in range( 0, int(random.randint(0, 3)) ):
retStr = retStr + "\n"
return retStr
class FuzzAServer(threading.Thread):
def __init__(self, addr, port, file, iter, chunkLen):
threading.Thread.__init__(self, name="Producer")
self.addr = addr;
self.port = port;
self.file = file;
self.iter = iter;
self.chunkLen = chunkLen;
def run(self):
while 1:
try:
sox = socket.socket ( socket.AF_INET, socket.SOCK_STREAM )
sox.connect((self.addr,int(self.port)))
while sox.send(fuzzFile(self.file, self.iter, self.chunkLen)):
pass
sox.close()
except Exception, err:
print err
time.sleep(10)
class FuzzAClient(threading.Thread):
def __init__(self, addr, port, file, iter, chunkLen):
threading.Thread.__init__(self, name="Producer")
self.addr = addr;
self.port = int(port);
self.file = file;
self.iter = iter;
self.chunkLen = chunkLen;
def run(self):
while 1:
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((self.addr, self.port))
s.listen(1)
conn, addr = s.accept()
print 'Connected by', addr
while 1:
data = conn.recv(1024)
print data,
if not data:
break
data = fuzzFile(self.file, self.iter, self.chunkLen)
print data
conn.send(data)
conn.close()
except Exception, err:
print err
s.shutdown(2)
s.close()
for i in range(0, 1000):
t = FuzzAServer(sys.argv[1], sys.argv[2], sys.argv[3], sys.argv[4], sys.argv[5])
t.start()
# print "thread ", i
The idea is simple. Connect to the server build some random string of XML-ish garbage and send it back. And like this as fast as you can. And yeah lets spawn a couple of more in parallel.
As you can see i also included a server who can handle a client a time and send bad XML. I decided to test not just the server but the clients also.
The results? Well after about 10-30 seconds the java Jabber server eat about 1.2G ram and 98%cpu for more than 20 minutes (at least i killed it after 20 mins). The clients that i tested were examples from the XmlRpc++ library. The did handle the server without problems.
Subscribe to:
Posts (Atom)