#!/usr/bin/python # python script to search through doxygen_sqlite3.db # # Permission to use, copy, modify, and distribute this software and its # documentation under the terms of the GNU General Public License is hereby # granted. No representations are made about the suitability of this software # for any purpose. It is provided "as is" without express or implied warranty. # See the GNU General Public License for more details. # import sqlite3 import sys import os import getopt import json import re class MemberType: Define="0" Function="1" Variable="2" Typedef="3" Enumeration="4" EnumValue="5" Signal="6" Slot="7" Friend="8" DCOP="9" Property="10" Event="11" File="12" class RequestType: References="9901" Struct="9902" Includers="9903" Includees="9904" Members="9905" BaseClasses="9906" SubClasses="9907" g_use_regexp=False ############################################################################### # case-insensitive sqlite regexp function def re_fn(expr, item): reg = re.compile(expr, re.I) return reg.search(item) is not None def openDb(dbname): if dbname == None: dbname = "doxygen_sqlite3.db" if not os.path.isfile(dbname): raise BaseException("No such file %s" % dbname ) conn = sqlite3.connect(dbname) conn.execute('PRAGMA temp_store = MEMORY;') conn.row_factory = sqlite3.Row conn.create_function("REGEXP", 2, re_fn) return conn ############################################################################### class Finder: def __init__(self,cn,name,row_type=str): self.cn=cn self.name=name self.row_type=row_type def match(self,row): if self.row_type is int: return " id=?" else: if g_use_regexp == True: return " REGEXP (?,%s)" %row else: return " %s=?" %row def fileName(self,id_file): if self.cn.execute("SELECT COUNT(*) FROM files WHERE rowid=?",[id_file]).fetchone()[0] > 1: print >>sys.stderr,"WARNING: non-uniq fileid [%s]. Considering only the first match." % id_file for r in self.cn.execute("SELECT * FROM files WHERE rowid=?",[id_file]).fetchall(): return r['name'] return "" def fileId(self,name): if self.cn.execute("SELECT COUNT(*) FROM files WHERE"+self.match("name"),[name]).fetchone()[0] > 1: print >>sys.stderr,"WARNING: non-uniq file name [%s]. Considering only the first match." % name for r in self.cn.execute("SELECT rowid FROM files WHERE"+self.match("name"),[name]).fetchall(): return r[0] return -1 ############################################################################### def references(self): o=[] cur = self.cn.cursor() cur.execute("SELECT refid FROM memberdef WHERE"+self.match("name"),[self.name]) refids = cur.fetchall() if len(refids) == 0: return o refid = refids[0]['refid'] cur = self.cn.cursor() #TODO:SELECT rowid from refids where refid=refid for info in cur.execute("SELECT * FROM xrefs WHERE refid_dst LIKE '%"+refid+"%'"): item={} cur = self.cn.cursor() for i2 in cur.execute("SELECT * FROM memberdef WHERE refid=?",[info['src']]): item['name']=i2['name'] item['src']=info['src'] item['file']=self.fileName(info['id_file']) item['line']=info['line'] o.append(item) return o ############################################################################### def function(self): o=[] c=self.cn.execute('SELECT * FROM memberdef WHERE'+self.match("name")+' AND kind=?',[self.name,MemberType.Function]) for r in c.fetchall(): item={} item['name'] = r['name'] item['definition'] = r['definition'] item['argsstring'] = r['argsstring'] item['file'] = self.fileName(r['id_file']) item['line'] = r['line'] item['detaileddescription'] = r['detaileddescription'] o.append(item) return o ############################################################################### def file(self): o=[] for r in self.cn.execute("SELECT rowid,* FROM files WHERE"+self.match("name"),[self.name]).fetchall(): item={} item['name'] = r['name'] item['id'] = r['rowid'] o.append(item) return o ############################################################################### def macro(self): o=[] c=self.cn.execute('SELECT * FROM memberdef WHERE'+self.match("name")+' AND kind=?',[self.name,MemberType.Define]) for r in c.fetchall(): item={} item['name'] = r['name'] if r['argsstring']: item['argsstring'] = r['argsstring'] item['definition'] = r['initializer'] item['file'] = self.fileName(r['id_file']) item['line'] = r['line'] o.append(item) return o ############################################################################### def typedef(self): o=[] c=self.cn.execute('SELECT * FROM memberdef WHERE'+self.match("name")+' AND kind=?',[self.name,MemberType.Typedef]) for r in c.fetchall(): item={} item['name'] = r['name'] item['definition'] = r['definition'] item['file'] = self.fileName(r['id_file']) item['line'] = r['line'] o.append(item) return o ############################################################################### def variable(self): o=[] c=self.cn.execute('SELECT * FROM memberdef WHERE'+self.match("name")+' AND kind=?',[self.name,MemberType.Variable]) for r in c.fetchall(): item={} item['name'] = r['name'] item['definition'] = r['definition'] item['file'] = self.fileName(r['id_file']) item['line'] = r['line'] o.append(item) return o ############################################################################### def params(self): o=[] c=self.cn.execute('SELECT id FROM memberdef WHERE'+self.match("name"),[self.name]) for r in c.fetchall(): #a=("SELECT * FROM params where id=(SELECT id_param FROM memberdef_params where id_memberdef=?",[id_memberdef]) item={} item['id'] = r['id'] o.append(item) return o ############################################################################### def struct(self): o=[] c=self.cn.execute('SELECT * FROM compounddef WHERE'+self.match("name"),[self.name]) for r in c.fetchall(): item={} item['name'] = r['name'] o.append(item) return o ############################################################################### def includers(self): o=[] fid = self.fileId(self.name) c=self.cn.execute('SELECT * FROM includes WHERE id_dst=?',[fid]) for r in c.fetchall(): item={} item['name'] = self.fileName(r['id_src']) o.append(item) return o ############################################################################### def includees(self): o=[] fid = self.fileId(self.name) c=self.cn.execute('SELECT * FROM includes WHERE id_src=?',[fid]) for r in c.fetchall(): item={} item['name'] = self.fileName(r['id_dst']) o.append(item) return o ############################################################################### def members(self): o=[] c=self.cn.execute('SELECT * FROM memberdef WHERE'+self.match("scope"),[self.name]) for r in c.fetchall(): item={} item['name'] = r['name'] item['definition'] = r['definition'] item['argsstring'] = r['argsstring'] item['file'] = self.fileName(r['id_file']) item['line'] = r['line'] #item['documentation'] = r['documentation'] o.append(item) return o ############################################################################### def baseClasses(self): o=[] c=self.cn.execute('SELECT base FROM basecompoundref WHERE'+self.match("derived"),[self.name]) for r in c.fetchall(): item={} item['name'] = r['base'] o.append(item) return o ############################################################################### def subClasses(self): o=[] c=self.cn.execute('SELECT derived FROM basecompoundref WHERE'+self.match("base"),[self.name]) for r in c.fetchall(): item={} item['name'] = r['derived'] o.append(item) return o ############################################################################### def process(f,kind): request_processors = { MemberType.Function: f.function, MemberType.File: f.file, MemberType.Define: f.macro, MemberType.Variable: f.variable, MemberType.Typedef: f.typedef, RequestType.References: f.references, RequestType.Struct: f.struct, RequestType.Includers: f.includers, RequestType.Includees: f.includees, RequestType.Members: f.members, RequestType.BaseClasses: f.baseClasses, RequestType.SubClasses: f.subClasses } return request_processors[kind]() ############################################################################### def processHref(cn,ref): j={} # is it in memberdef ? table="memberdef" if ( cn.execute("SELECT count(*) from %s WHERE refid=?"%table,[ref] ).fetchone()[0] > 0 ): for r in cn.execute("SELECT kind,id FROM %s WHERE refid='%s'" % (table,ref) ).fetchall(): f=Finder(cn,r['id'],int) j=process(f,str(r['kind'])) # is it in compounddef ? table="compounddef" if ( cn.execute("SELECT count(*) from %s WHERE refid=?"%table,[ref]).fetchone()[0] > 0 ): for r in cn.execute("SELECT id FROM %s WHERE refid=?"%table,[ref] ).fetchall(): f=Finder(cn,r['id'],int) j=process(f,RequestType.Struct) return j ############################################################################### def serveCgi(): import cgi print 'Content-Type: application/json\n' fieldStorage = cgi.FieldStorage() form = dict((key, fieldStorage.getvalue(key)) for key in fieldStorage.keys()) if 'href' in form: ref = form['href'] else: print '{"result": null, "error": "no refid given"}' sys.exit(0) cn=openDb('doxygen_sqlite3.db') j = processHref(cn,ref) print json.dumps({"result":j,"error":None}) ############################################################################### def usage(): print >>sys.stderr,"""Usage: search.py [Options] Options: -h, --help -d Use database for queries. -f Search for definition of function . -m Search for definition of macro . -r Search for references to function . -t Search for definition of type . -v Search for definition of variable . -I What files are including . -i What files are included by . -B Get the base classes of class . -M Get all members of class . -S Get the sub classes of class . -R Consider the search to be a regex. """ ############################################################################### def serveCli(argv): try: opts, args = getopt.getopt(argv, "hr:RI:i:d:f:m:t:v:H:M:B:S:F:",["help"]) except getopt.GetoptError: usage() sys.exit(1) ref=None dbname=None j={} global g_use_regexp for a, o in opts: if a in ('-h', '--help'): usage() sys.exit(0) elif a in ('-d'): dbname=o continue elif a in ('-r'): kind=RequestType.References elif a in ('-R'): g_use_regexp=True continue elif a in ('-I'): kind=RequestType.Includers elif a in ('-i'): kind=RequestType.Includees elif a in ('-M'): kind=RequestType.Members elif a in ('-B'): kind=RequestType.BaseClasses elif a in ('-S'): kind=RequestType.SubClasses elif a in ('-f'): kind=MemberType.Function elif a in ('-F'): kind=MemberType.File elif a in ('-m'): kind=MemberType.Define elif a in ('-t'): kind=MemberType.Typedef elif a in ('-v'): kind=MemberType.Variable elif a in ('-H'): ref = o cn=openDb(dbname) f=Finder(cn,o) if ref != None: j=processHref(cn,ref) else: j=process(f,kind) print json.dumps(j,indent=4) def main(argv): if 'REQUEST_METHOD' in os.environ: serveCgi() else: serveCli(argv) if __name__ == '__main__': main(sys.argv[1:])