search.py
Go to the documentation of this file.
1 #!/usr/bin/python
2 
3 # python script to search through doxygen_sqlite3.db
4 #
5 # Permission to use, copy, modify, and distribute this software and its
6 # documentation under the terms of the GNU General Public License is hereby
7 # granted. No representations are made about the suitability of this software
8 # for any purpose. It is provided "as is" without express or implied warranty.
9 # See the GNU General Public License for more details.
10 #
11 
12 import sqlite3
13 import sys
14 import os
15 import getopt
16 import json
17 import re
18 
19 class MemberType:
20  Define="0"
21  Function="1"
22  Variable="2"
23  Typedef="3"
24  Enumeration="4"
25  EnumValue="5"
26  Signal="6"
27  Slot="7"
28  Friend="8"
29  DCOP="9"
30  Property="10"
31  Event="11"
32  File="12"
33 
35  References="9901"
36  Struct="9902"
37  Includers="9903"
38  Includees="9904"
39  Members="9905"
40  BaseClasses="9906"
41  SubClasses="9907"
42 
43 g_use_regexp=False
44 ###############################################################################
45 
46 # case-insensitive sqlite regexp function
47 def re_fn(expr, item):
48  reg = re.compile(expr, re.I)
49  return reg.search(item) is not None
50 
51 def openDb(dbname):
52  if dbname == None:
53  dbname = "doxygen_sqlite3.db"
54 
55  if not os.path.isfile(dbname):
56  raise BaseException("No such file %s" % dbname )
57 
58  conn = sqlite3.connect(dbname)
59  conn.execute('PRAGMA temp_store = MEMORY;')
60  conn.row_factory = sqlite3.Row
61  conn.create_function("REGEXP", 2, re_fn)
62  return conn
63 ###############################################################################
64 class Finder:
65  def __init__(self,cn,name,row_type=str):
66  self.cn=cn
67  self.name=name
68  self.row_type=row_type
69 
70  def match(self,row):
71  if self.row_type is int:
72  return " id=?"
73  else:
74  if g_use_regexp == True:
75  return " REGEXP (?,%s)" %row
76  else:
77  return " %s=?" %row
78 
79  def fileName(self,id_file):
80  if self.cn.execute("SELECT COUNT(*) FROM files WHERE rowid=?",[id_file]).fetchone()[0] > 1:
81  print >>sys.stderr,"WARNING: non-uniq fileid [%s]. Considering only the first match." % id_file
82 
83  for r in self.cn.execute("SELECT * FROM files WHERE rowid=?",[id_file]).fetchall():
84  return r['name']
85 
86  return ""
87 
88  def fileId(self,name):
89  if self.cn.execute("SELECT COUNT(*) FROM files WHERE"+self.match("name"),[name]).fetchone()[0] > 1:
90  print >>sys.stderr,"WARNING: non-uniq file name [%s]. Considering only the first match." % name
91 
92  for r in self.cn.execute("SELECT rowid FROM files WHERE"+self.match("name"),[name]).fetchall():
93  return r[0]
94 
95  return -1
96 ###############################################################################
97  def references(self):
98  o=[]
99  cur = self.cn.cursor()
100  cur.execute("SELECT refid FROM memberdef WHERE"+self.match("name"),[self.name])
101  refids = cur.fetchall()
102 
103  if len(refids) == 0:
104  return o
105 
106  refid = refids[0]['refid']
107  cur = self.cn.cursor()
108  #TODO:SELECT rowid from refids where refid=refid
109  for info in cur.execute("SELECT * FROM xrefs WHERE refid_dst LIKE '%"+refid+"%'"):
110  item={}
111  cur = self.cn.cursor()
112  for i2 in cur.execute("SELECT * FROM memberdef WHERE refid=?",[info['src']]):
113  item['name']=i2['name']
114  item['src']=info['src']
115  item['file']=self.fileName(info['id_file'])
116  item['line']=info['line']
117 
118  o.append(item)
119  return o
120 ###############################################################################
121  def function(self):
122  o=[]
123  c=self.cn.execute('SELECT * FROM memberdef WHERE'+self.match("name")+' AND kind=?',[self.name,MemberType.Function])
124  for r in c.fetchall():
125  item={}
126  item['name'] = r['name']
127  item['definition'] = r['definition']
128  item['argsstring'] = r['argsstring']
129  item['file'] = self.fileName(r['id_file'])
130  item['line'] = r['line']
131  item['detaileddescription'] = r['detaileddescription']
132  o.append(item)
133  return o
134 ###############################################################################
135  def file(self):
136  o=[]
137  for r in self.cn.execute("SELECT rowid,* FROM files WHERE"+self.match("name"),[self.name]).fetchall():
138  item={}
139  item['name'] = r['name']
140  item['id'] = r['rowid']
141  o.append(item)
142  return o
143 
144 ###############################################################################
145  def macro(self):
146  o=[]
147  c=self.cn.execute('SELECT * FROM memberdef WHERE'+self.match("name")+' AND kind=?',[self.name,MemberType.Define])
148  for r in c.fetchall():
149  item={}
150  item['name'] = r['name']
151  if r['argsstring']:
152  item['argsstring'] = r['argsstring']
153  item['definition'] = r['initializer']
154  item['file'] = self.fileName(r['id_file'])
155  item['line'] = r['line']
156  o.append(item)
157  return o
158 ###############################################################################
159  def typedef(self):
160  o=[]
161  c=self.cn.execute('SELECT * FROM memberdef WHERE'+self.match("name")+' AND kind=?',[self.name,MemberType.Typedef])
162  for r in c.fetchall():
163  item={}
164  item['name'] = r['name']
165  item['definition'] = r['definition']
166  item['file'] = self.fileName(r['id_file'])
167  item['line'] = r['line']
168  o.append(item)
169  return o
170 ###############################################################################
171  def variable(self):
172  o=[]
173  c=self.cn.execute('SELECT * FROM memberdef WHERE'+self.match("name")+' AND kind=?',[self.name,MemberType.Variable])
174  for r in c.fetchall():
175  item={}
176  item['name'] = r['name']
177  item['definition'] = r['definition']
178  item['file'] = self.fileName(r['id_file'])
179  item['line'] = r['line']
180  o.append(item)
181  return o
182 ###############################################################################
183  def params(self):
184  o=[]
185  c=self.cn.execute('SELECT id FROM memberdef WHERE'+self.match("name"),[self.name])
186  for r in c.fetchall():
187  #a=("SELECT * FROM params where id=(SELECT id_param FROM memberdef_params where id_memberdef=?",[id_memberdef])
188  item={}
189  item['id'] = r['id']
190  o.append(item)
191  return o
192 ###############################################################################
193  def struct(self):
194  o=[]
195  c=self.cn.execute('SELECT * FROM compounddef WHERE'+self.match("name"),[self.name])
196  for r in c.fetchall():
197  item={}
198  item['name'] = r['name']
199  o.append(item)
200  return o
201 ###############################################################################
202  def includers(self):
203  o=[]
204  fid = self.fileId(self.name)
205  c=self.cn.execute('SELECT * FROM includes WHERE id_dst=?',[fid])
206  for r in c.fetchall():
207  item={}
208  item['name'] = self.fileName(r['id_src'])
209  o.append(item)
210  return o
211 ###############################################################################
212  def includees(self):
213  o=[]
214  fid = self.fileId(self.name)
215  c=self.cn.execute('SELECT * FROM includes WHERE id_src=?',[fid])
216  for r in c.fetchall():
217  item={}
218  item['name'] = self.fileName(r['id_dst'])
219  o.append(item)
220  return o
221 ###############################################################################
222  def members(self):
223  o=[]
224  c=self.cn.execute('SELECT * FROM memberdef WHERE'+self.match("scope"),[self.name])
225  for r in c.fetchall():
226  item={}
227  item['name'] = r['name']
228  item['definition'] = r['definition']
229  item['argsstring'] = r['argsstring']
230  item['file'] = self.fileName(r['id_file'])
231  item['line'] = r['line']
232  #item['documentation'] = r['documentation']
233  o.append(item)
234  return o
235 ###############################################################################
236  def baseClasses(self):
237  o=[]
238  c=self.cn.execute('SELECT base FROM basecompoundref WHERE'+self.match("derived"),[self.name])
239  for r in c.fetchall():
240  item={}
241  item['name'] = r['base']
242  o.append(item)
243  return o
244 ###############################################################################
245  def subClasses(self):
246  o=[]
247  c=self.cn.execute('SELECT derived FROM basecompoundref WHERE'+self.match("base"),[self.name])
248  for r in c.fetchall():
249  item={}
250  item['name'] = r['derived']
251  o.append(item)
252  return o
253 ###############################################################################
254 def process(f,kind):
255  request_processors = {
256  MemberType.Function: f.function,
257  MemberType.File: f.file,
258  MemberType.Define: f.macro,
259  MemberType.Variable: f.variable,
260  MemberType.Typedef: f.typedef,
261  RequestType.References: f.references,
262  RequestType.Struct: f.struct,
263  RequestType.Includers: f.includers,
264  RequestType.Includees: f.includees,
265  RequestType.Members: f.members,
266  RequestType.BaseClasses: f.baseClasses,
267  RequestType.SubClasses: f.subClasses
268  }
269  return request_processors[kind]()
270 ###############################################################################
271 def processHref(cn,ref):
272  j={}
273 
274  # is it in memberdef ?
275  table="memberdef"
276  if ( cn.execute("SELECT count(*) from %s WHERE refid=?"%table,[ref] ).fetchone()[0] > 0 ):
277  for r in cn.execute("SELECT kind,id FROM %s WHERE refid='%s'" % (table,ref) ).fetchall():
278  f=Finder(cn,r['id'],int)
279  j=process(f,str(r['kind']))
280 
281  # is it in compounddef ?
282  table="compounddef"
283  if ( cn.execute("SELECT count(*) from %s WHERE refid=?"%table,[ref]).fetchone()[0] > 0 ):
284  for r in cn.execute("SELECT id FROM %s WHERE refid=?"%table,[ref] ).fetchall():
285  f=Finder(cn,r['id'],int)
286  j=process(f,RequestType.Struct)
287 
288  return j
289 ###############################################################################
290 def serveCgi():
291  import cgi
292 
293  print 'Content-Type: application/json\n'
294 
295  fieldStorage = cgi.FieldStorage()
296  form = dict((key, fieldStorage.getvalue(key)) for key in fieldStorage.keys())
297 
298  if 'href' in form:
299  ref = form['href']
300  else:
301  print '{"result": null, "error": "no refid given"}'
302  sys.exit(0)
303 
304  cn=openDb('doxygen_sqlite3.db')
305 
306  j = processHref(cn,ref)
307 
308  print json.dumps({"result":j,"error":None})
309 ###############################################################################
310 def usage():
311  print >>sys.stderr,"""Usage: search.py [Options]
312 Options:
313  -h, --help
314  -d <D> Use database <D> for queries.
315  -f <F> Search for definition of function <F>.
316  -m <M> Search for definition of macro <M>.
317  -r <F> Search for references to function <F>.
318  -t <T> Search for definition of type <T>.
319  -v <V> Search for definition of variable <V>.
320  -I <I> What files are including <I>.
321  -i <i> What files are included by <i>.
322  -B <C> Get the base classes of class <C>.
323  -M <C> Get all members of class <C>.
324  -S <C> Get the sub classes of class <C>.
325  -R Consider the search <term> to be a regex.
326 """
327 ###############################################################################
328 def serveCli(argv):
329  try:
330  opts, args = getopt.getopt(argv, "hr:RI:i:d:f:m:t:v:H:M:B:S:F:",["help"])
331  except getopt.GetoptError:
332  usage()
333  sys.exit(1)
334 
335  ref=None
336  dbname=None
337  j={}
338  global g_use_regexp
339 
340  for a, o in opts:
341  if a in ('-h', '--help'):
342  usage()
343  sys.exit(0)
344  elif a in ('-d'):
345  dbname=o
346  continue
347  elif a in ('-r'):
348  kind=RequestType.References
349  elif a in ('-R'):
350  g_use_regexp=True
351  continue
352  elif a in ('-I'):
353  kind=RequestType.Includers
354  elif a in ('-i'):
355  kind=RequestType.Includees
356  elif a in ('-M'):
357  kind=RequestType.Members
358  elif a in ('-B'):
359  kind=RequestType.BaseClasses
360  elif a in ('-S'):
361  kind=RequestType.SubClasses
362  elif a in ('-f'):
363  kind=MemberType.Function
364  elif a in ('-F'):
365  kind=MemberType.File
366  elif a in ('-m'):
367  kind=MemberType.Define
368  elif a in ('-t'):
369  kind=MemberType.Typedef
370  elif a in ('-v'):
371  kind=MemberType.Variable
372  elif a in ('-H'):
373  ref = o
374 
375  cn=openDb(dbname)
376  f=Finder(cn,o)
377  if ref != None:
378  j=processHref(cn,ref)
379  else:
380  j=process(f,kind)
381  print json.dumps(j,indent=4)
382 
383 
384 def main(argv):
385  if 'REQUEST_METHOD' in os.environ:
386  serveCgi()
387  else:
388  serveCli(argv)
389 
390 if __name__ == '__main__':
391  main(sys.argv[1:])
def subClasses(self)
Definition: search.py:245
def includers(self)
Definition: search.py:202
def fileId(self, name)
Definition: search.py:88
def references(self)
Definition: search.py:97
def openDb(dbname)
Definition: search.py:51
def serveCgi()
Definition: search.py:290
def macro(self)
Definition: search.py:145
def main(argv)
Definition: search.py:384
def process(f, kind)
Definition: search.py:254
def members(self)
Definition: search.py:222
def file(self)
Definition: search.py:135
def processHref(cn, ref)
Definition: search.py:271
def typedef(self)
Definition: search.py:159
def re_fn(expr, item)
Definition: search.py:47
def includees(self)
Definition: search.py:212
def variable(self)
Definition: search.py:171
def usage()
Definition: search.py:310
def params(self)
Definition: search.py:183
def fileName(self, id_file)
Definition: search.py:79
def baseClasses(self)
Definition: search.py:236
def match(self, row)
Definition: search.py:70
def function(self)
Definition: search.py:121
def serveCli(argv)
Definition: search.py:328
def __init__(self, cn, name, row_type=str)
Definition: search.py:65
def struct(self)
Definition: search.py:193
static QCString str