3 # python script to search through doxygen_sqlite3.db
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.
20 Define="macro definition"
24 Enumeration="enumeration"
44 ###############################################################################
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
53 dbname = "doxygen_sqlite3.db"
55 if not os.path.isfile(dbname):
56 raise BaseException("No such file %s" % dbname )
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)
63 ###############################################################################
65 def __init__(self,cn,name,row_type=str):
68 self.row_type=row_type
71 if self.row_type is int:
74 if g_use_regexp == True:
75 return " REGEXP (?,%s)" %row
79 def fileName(self,file_id):
80 if self.cn.execute("SELECT COUNT(*) FROM path WHERE rowid=?",[file_id]).fetchone()[0] > 1:
81 sys.stderr.write("WARNING: non-uniq fileid [%s]. Considering only the first match." % file_id)
83 for r in self.cn.execute("SELECT * FROM path WHERE rowid=?",[file_id]).fetchall():
88 def fileId(self,name):
89 if self.cn.execute("SELECT COUNT(*) FROM path WHERE"+self.match("name"),[name]).fetchone()[0] > 1:
90 sys.stderr.write("WARNING: non-uniq file name [%s]. Considering only the first match." % name)
92 for r in self.cn.execute("SELECT rowid FROM path WHERE"+self.match("name"),[name]).fetchall():
96 ###############################################################################
99 cur = self.cn.cursor()
100 cur.execute("SELECT rowid FROM memberdef WHERE"+self.match("name"),[self.name])
101 rowids = cur.fetchall()
106 rowid = rowids[0]['rowid']
107 cur = self.cn.cursor()
108 #TODO:SELECT rowid from refid where refid=refid
109 for info in cur.execute("SELECT * FROM xrefs WHERE dst_rowid=?", [rowid]):
111 cur = self.cn.cursor()
112 for i2 in cur.execute("SELECT * FROM memberdef WHERE rowid=?",[info['src_rowid']]):
113 item['name']=i2['name']
114 item['src']=info['src_rowid']
115 # Below no longer directly supported on this entry; can be found from either memberdef
116 #item['file']=self.fileName(info['file_id'])
117 #item['line']=info['line']
121 ###############################################################################
124 c=self.cn.execute('SELECT * FROM memberdef WHERE'+self.match("name")+' AND kind=?',[self.name,MemberType.Function])
125 for r in c.fetchall():
127 item['name'] = r['name']
128 item['definition'] = r['definition']
129 item['argsstring'] = r['argsstring']
130 item['file'] = self.fileName(r['file_id'])
131 item['line'] = r['line']
132 item['detaileddescription'] = r['detaileddescription']
135 ###############################################################################
138 for r in self.cn.execute("SELECT rowid,name FROM local_file WHERE"+self.match("name"),[self.name]).fetchall():
140 item['name'] = r['name']
141 item['id'] = r['rowid']
145 ###############################################################################
148 c=self.cn.execute('SELECT * FROM memberdef WHERE'+self.match("name")+' AND kind=?',[self.name,MemberType.Define])
149 for r in c.fetchall():
151 item['name'] = r['name']
153 item['argsstring'] = r['argsstring']
154 item['definition'] = r['initializer']
155 item['file'] = self.fileName(r['file_id'])
156 item['line'] = r['line']
159 ###############################################################################
162 c=self.cn.execute('SELECT * FROM memberdef WHERE'+self.match("name")+' AND kind=?',[self.name,MemberType.Typedef])
163 for r in c.fetchall():
165 item['name'] = r['name']
166 item['definition'] = r['definition']
167 item['file'] = self.fileName(r['file_id'])
168 item['line'] = r['line']
171 ###############################################################################
174 c=self.cn.execute('SELECT * FROM memberdef WHERE'+self.match("name")+' AND kind=?',[self.name,MemberType.Variable])
175 for r in c.fetchall():
177 item['name'] = r['name']
178 item['definition'] = r['definition']
179 item['file'] = self.fileName(r['file_id'])
180 item['line'] = r['line']
183 ###############################################################################
186 c=self.cn.execute('SELECT rowid FROM memberdef WHERE'+self.match("name"),[self.name])
187 for r in c.fetchall():
188 #a=("SELECT * FROM param where id=(SELECT param_id FROM memberdef_param where memberdef_id=?",[memberdef_id])
193 ###############################################################################
196 c=self.cn.execute('SELECT * FROM compounddef WHERE'+self.match("name"),[self.name])
197 for r in c.fetchall():
199 item['name'] = r['name']
202 ###############################################################################
205 fid = self.fileId(self.name)
206 c=self.cn.execute('SELECT * FROM includes WHERE dst_id=?',[fid])
207 for r in c.fetchall():
209 item['name'] = self.fileName(r['src_id'])
212 ###############################################################################
215 fid = self.fileId(self.name)
216 c=self.cn.execute('SELECT * FROM includes WHERE src_id=?',[fid])
217 for r in c.fetchall():
219 item['name'] = self.fileName(r['dst_id'])
222 ###############################################################################
225 c=self.cn.execute('SELECT * FROM memberdef WHERE'+self.match("scope"),[self.name])
226 for r in c.fetchall():
228 item['name'] = r['name']
229 item['definition'] = r['definition']
230 item['argsstring'] = r['argsstring']
231 item['file'] = self.fileName(r['file_id'])
232 item['line'] = r['line']
233 #item['documentation'] = r['documentation']
236 ###############################################################################
237 def baseClasses(self):
239 c=self.cn.execute('SELECT compounddef.name FROM compounddef JOIN compoundref ON compounddef.rowid=compoundref.base_rowid WHERE compoundref.derived_rowid IN (SELECT rowid FROM compounddef WHERE'+self.match("name")+')',[self.name])
240 for r in c.fetchall():
242 item['name'] = r['name']
245 ###############################################################################
246 def subClasses(self):
248 c=self.cn.execute('SELECT compounddef.name FROM compounddef JOIN compoundref ON compounddef.rowid=compoundref.derived_rowid WHERE compoundref.base_rowid IN (SELECT rowid FROM compounddef WHERE'+self.match("name")+')',[self.name])
249 for r in c.fetchall():
251 item['name'] = r['name']
254 ###############################################################################
256 request_processors = {
257 MemberType.Function: f.function,
258 MemberType.File: f.file,
259 MemberType.Define: f.macro,
260 MemberType.Variable: f.variable,
261 MemberType.Typedef: f.typedef,
262 RequestType.References: f.references,
263 RequestType.Struct: f.struct,
264 RequestType.Includers: f.includers,
265 RequestType.Includees: f.includees,
266 RequestType.Members: f.members,
267 RequestType.BaseClasses: f.baseClasses,
268 RequestType.SubClasses: f.subClasses
270 return request_processors[kind]()
271 ###############################################################################
273 # the -H option isn't documented. It's one of the more recent additions, but it's treating refids as if they would be a string. I'm just taking a stab at updating it for now, converting to use rowid, and making other edits necessary to get it to run.
274 def processHref(cn,ref):
277 # is it in memberdef ?
279 if ( cn.execute("SELECT count(*) from %s WHERE rowid=?"%table,[ref] ).fetchone()[0] > 0 ):
280 for r in cn.execute("SELECT kind,rowid FROM %s WHERE rowid=?" % table,[ref]).fetchall():
281 f=Finder(cn,r['rowid'],int)
282 j=process(f,str(r['kind']))
284 # is it in compounddef ?
286 if ( cn.execute("SELECT count(*) from %s WHERE rowid=?"%table,[ref]).fetchone()[0] > 0 ):
287 for r in cn.execute("SELECT rowid FROM %s WHERE rowid=?"%table,[ref] ).fetchall():
288 f=Finder(cn,r[0],int)
289 j=process(f,RequestType.Struct)
292 ###############################################################################
296 print('Content-Type: application/json\n')
298 fieldStorage = cgi.FieldStorage()
299 form = dict((key, fieldStorage.getvalue(key)) for key in fieldStorage.keys())
304 print('{"result": null, "error": "no refid given"}')
307 cn=openDb('doxygen_sqlite3.db')
309 j = processHref(cn,ref)
311 print(json.dumps({"result":j,"error":None}))
312 ###############################################################################
314 sys.stderr.write("""Usage: search.py [Options]
317 -d <D> Use database <D> for queries.
318 -f <F> Search for definition of function <F>.
319 -m <M> Search for definition of macro <M>.
320 -r <F> Search for references to function <F>.
321 -t <T> Search for definition of type <T>.
322 -v <V> Search for definition of variable <V>.
323 -I <I> What files are including <I>.
324 -i <i> What files are included by <i>.
325 -B <C> Get the base classes of class <C>.
326 -M <C> Get all members of class <C>.
327 -S <C> Get the sub classes of class <C>.
328 -R Consider the search <term> to be a regex.
330 ###############################################################################
333 opts, args = getopt.getopt(argv, "hr:RI:i:d:f:m:t:v:H:M:B:S:F:",["help"])
334 except getopt.GetoptError:
344 if a in ('-h', '--help'):
351 kind=RequestType.References
356 kind=RequestType.Includers
358 kind=RequestType.Includees
360 kind=RequestType.Members
362 kind=RequestType.BaseClasses
364 kind=RequestType.SubClasses
366 kind=MemberType.Function
369 # seems to fit with the lower case "search" patterns?
372 kind=MemberType.Define
374 kind=MemberType.Typedef
376 kind=MemberType.Variable
384 j=processHref(cn,ref)
387 print(json.dumps(j,indent=4))
391 if 'REQUEST_METHOD' in os.environ:
396 if __name__ == '__main__':