def gen_syscalls(sct_file, x32=False): """ Generate an Array of syscalls sct_file: File handle of the name table x32: the name table is 32 bit syscalls? """ tags = CTags('tags') entry = TagEntry() sys_calls = [] i = 0 for line in sct_file: if line.startswith("#"): continue parts = line.split() if (len(parts) > 3 and parts[0] >= '0'): name = parts[3].encode("utf-8") if tags.find(entry, name, ctags.TAG_FULLMATCH | ctags.TAG_OBSERVECASE): found_sym = False while (not found_sym): if (entry["kind"].decode("utf-8") == "prototype"): found_sym = True details = { "number": { "int": i, "hex": ("%0#4x" % (i)) }, "name": name, "parameters": entry[b"signature"] } if (entry[b"signature"] != "(void)"): sig = entry[b"signature"].decode("utf-8").strip( '()').split(',') else: sig = [] regs = {} details["parameters_details"] = [] if (len(sig) < (7 if x32 else 8)): for param in sig: par = param.strip() par_def = "" if (param.find("struct") != -1): type_match = re.search( "struct (\w+)", param) if (type_match): par_entry = TagEntry() if (tags.find( par_entry, type_match.group(1).encode( "utf-8"), ctags.TAG_FULLMATCH | ctags.TAG_OBSERVECASE)): if (par_entry[b'kind'] == "struct" ): par_def = { 'file': par_entry['file'], 'line': int(par_entry['lineNumber'] ) } details["parameters_details"].append({ 'type': par, 'def': par_def }) else: details["parameters_details"].append({ "type": "param addr*", "def": par_def }) remaining = (5 if x32 else 6) - \ len(details["parameters_details"]) for x in range(0, remaining): details["parameters_details"].append("") pattern = "SYSCALL_DEFINE%d(%s" % ( len(sig), name.decode("utf-8").replace("sys_", "")) search = "SYSCALL_DEFINE%d" % (len(sig)) if tags.find( entry, search.encode("utf-8"), ctags.TAG_FULLMATCH | ctags.TAG_OBSERVECASE): found = False while (not found): if (entry["pattern"].decode("utf-8").find( pattern) >= 2): # details['found'] = entry['pattern'] details["definition"] = { "file": entry["file"], "lineno": int(entry['lineNumber']) } found = True break if (not tags.findNext(entry)): details["definition"] = { "file": "", "lineno": "" } break else: details["definition"] = {"file": "", "lineno": ""} sys_calls.append(details) else: if (not tags.findNext(entry)): sys_calls.append([i].append([""] * (7 if x32 else 8))) break i += 1 else: details = { "number": { "int": i, "hex": ("%0#4x" % (i)) }, "name": "not implemented", "parameters": "", "parameters_details": {}, "definition": { "file": "", "lineno": "" } } sys_calls.append(details) i += 1 return sys_calls
def parse_ctags(tagFile): tf = CTags(tagFile) e = TagEntry() results = [] s = tf.first(e) while s: eP = {'name': e['name'], 'file': e['file'], 'pattern': e['pattern'], 'lineNumber': e['lineNumber'], 'kind': e['kind'], 'fileScope': e['fileScope']} results.append(eP) s = tf.next(e) return sorted(results, cmp = lambda x, y: cmp(x['file'].lower(), y['file'].lower()) if x['file'] != y['file'] else cmp(x['lineNumber'], y['lineNumber']))
def parse_ctags(): '''Returns a list of all the functions and their arguments found by ctags''' try: tf = CTags('tags') except: print "Unable to find tags file!" sys.exit(-1) entry = TagEntry() l = [] if 0 == tf.first(entry): return [] while True: l.append(parse_pattern(entry['pattern'])) if 0 == tf.next(entry): break return l
def run(self, paths=None): """ Run command - open search for definition window """ # check ctags is exists ctags_file = self.get_ctags_file(self.get_path(paths)) if ctags_file is None or not os.path.exists(ctags_file): return [] # check ctags is prepared - prepare if needed global ctags if ctags is None: ctags = CTags(tags_file=ctags_file, debug=is_debug) # get all definitions of selected word self._definitions = ctags.get_definitions() if not self._definitions: # return sublime.status_message("Can't find '%s'" % symbol) return # else show definitions list definitions = [[d[3][2:-4].strip(), "%d: %s" % (d[2], self.prettify_path(d[1]))] for d in self._definitions] self.window.show_quick_panel(definitions, self.select_definition)
def on_query_completions(self, view, prefix, locations): """ Extend autocomplete results with ctags """ # skip non-python files if not view.match_selector(0, "source.python"): return [] # check ctags is exists ctags_file = self.get_ctags_file(view.file_name()) if ctags_file is None or not os.path.exists(ctags_file): return [] # check ctags is prepared - prepare if needed global ctags if ctags is None: ctags = CTags(tags_file=ctags_file, debug=is_debug) # pt = locations[0] - len(prefix) - 1 # ch = view.substr(sublime.Region(pt, pt + 1)) # is_dot = (ch == '.') # do autocomplete work return ctags.autocomplete(prefix)
def run(self, edit): """ Run command - jump to word under cursor definition """ # skip non-python files if not self.view.match_selector(0, "source.python"): return # check ctags is exists ctags_file = self.get_ctags_file(self.view.file_name()) if ctags_file is None or not os.path.exists(ctags_file): return [] # check ctags is prepared - prepare if needed global ctags if ctags is None: ctags = CTags(tags_file=ctags_file, debug=is_debug) # get word under cursor symbol = self.view.substr(self.view.word(self.view.sel()[0])) # get all definitions of selected word self._definitions = ctags.get_definitions(symbol) if not self._definitions: return sublime.status_message("Can't find '%s'" % symbol) # check settings instant_jump = settings.get("instant_jump_to_definition", False) if len(self._definitions) == 1 and instant_jump: # instant jump to definition if such setting and only one result self.select_definition(0) else: # else show definitions list definitions = [[d[3][2:-4].strip(), "%d: %s" % (d[2], self.prettify_path(d[1]))] for d in self._definitions] self.view.window().show_quick_panel(definitions, self.select_definition)
def _getFunctionLines(self, file_layout_src, file_commit): ''' computes the line numbers of each function in the file ''' ''' - Input - file_name: original name of the file, used only to determine the programming language (ie. file.c is a c-language file) file_layout_scr: dictionary with key=line number value = line of code file_commit: fileCommit instance where the results will be stored - Description - The file_layout is used to construct a source code file that can be parsed by ctags to generate a ctags file. The ctags file is then accessed to extract the function tags and line numbers to be save in the fileCommit object ''' # grab the file extension to determine the language of the file fileExt = os.path.splitext(file_commit.filename)[1] # temporary file where we write transient data needed for ctags srcFile = tempfile.NamedTemporaryFile(suffix=fileExt) tagFile = tempfile.NamedTemporaryFile() # generate a source code file from the file_layout_src dictionary # and save it to a temporary location for line in file_layout_src: srcFile.write(line) srcFile.flush() # run ctags analysis on the file to create a tags file cmd = "ctags-exuberant -f {0} --fields=nk {1}".format( tagFile.name, srcFile.name).split() output = execute_command(cmd).splitlines() # parse ctags try: tags = CTags(tagFile.name) except: log.critical("failure to load ctags file") raise Error("failure to load ctags file") # locate line numbers and structure names entry = TagEntry() funcLines = {} # select the language structures we are interested in identifying # f = functions, s = structs, c = classes, n = namespace # p = function prototype, g = enum, d = macro, t= typedef, u = union structures = ["f", "s", "c", "n", "p", "g", "d", "t", "u"] # TODO: investigate other languages and how ctags assigns the structure # tags, we may need more languages specific assignments in # addition to java and c# files, use "ctags --list-kinds" to # see all tag meanings per language if fileExt in (".java", ".j", ".jav", ".cs", ".js"): structures.append("m") # methods structures.append("i") # interface elif fileExt in (".php"): structures.append("i") # interface structures.append("j") # functions elif fileExt in (".py"): structures.append("m") # class members while (tags.next(entry)): if entry['kind'] in structures: funcLines[int(entry['lineNumber'])] = entry['name'] # clean up temporary files srcFile.close() tagFile.close() # save result to the file commit instance file_commit.setFunctionLines(funcLines)
def update_type_map(type_map, ctags_fname): logger.debug("processing %s ...", ctags_fname) tag = CTags(ctags_fname.encode()) tag.setSortType(ctags.TAG_SORTED) entry = TagEntry() # First traverse all entries status = tag.first(entry) while status: name = entry["name"].decode() kind = entry["kind"].decode() typeref = (entry[b"typeref"] or b"").decode() pattern = entry["pattern"].decode() # TODO: Check multiple declaration if name in type_map: status = tag.next(entry) continue # TODO: handle macro properly. currently, assume macros are integers. # Also, skip allocation. if kind == "macro" or "=" in pattern: status = tag.next(entry) continue if kind in ["func", "proc", "function", "procedure", "method"]: ret_type = "func" elif kind.startswith("enum"): ret_type = "enum" elif kind == "union": ret_type = "union" elif kind.startswith("struct"): ret_type = "struct" elif kind.startswith("class"): ret_type = "struct" elif kind == "label": ret_type = ret_type elif kind in ["label", "typedef", "member", "variable"]: if typeref: ret_type = typeref.split(":")[0] else: ret_type = pattern[:pattern.rindex(name)].rstrip() else: status = tag.next(entry) continue ret_type = sanitize(ret_type) if "(" in ret_type: ret_type = "func" if "*" in ret_type: ret_type + " *" type_map[name] = ret_type status = tag.next(entry) # Now check until no update exists while True: is_updated = False status = tag.first(entry) while status: name = entry["name"].decode() kind = entry["kind"].decode() typeref = (entry[b"typeref"] or b"").decode() pattern = entry["pattern"].decode() # No need to handle a macro as it is already replaced by a constant. # Also, skip allocation. if kind == "macro" or "=" in pattern: status = tag.next(entry) continue if name not in type_map: ret_type = "int" else: ret_type = type_map[name] ret_type = ret_type.split()[0] # remove pointer for here while ret_type in type_map and ret_type != type_map[ret_type]: ret_type = ret_type.split()[0] # remove pointer for here ret_type = type_map[ret_type] if ret_type not in type_map: ret_type = "int" # use a single '*' for denoting a pointer if "*" not in ret_type and "*" in type_map[name]: ret_type = ret_type + " *" if ret_type != type_map[name]: type_map[name] = ret_type is_updated = True status = tag.next(entry) if is_updated == False: break return None
dest="debug1", help="open debug1 log", action="store_true", default=False) parser.add_option("--d2", "--debug2", dest="debug2", help="open debug2 log", action="store_true", default=False) (options, args) = parser.parse_args() try: tagFile = CTags('TAGS') except Exception: sys.exit(1) # 在命令行输入 # ctags --c++-kinds=p --fields=+iaS --extra=+q -R # from parser import * if options.debug: set_level(1) elif options.debug1: set_level(2) elif options.debug2: set_level(3)
def entities(): tagFile = CTags('TAGS') entry = TagEntry() while tagFile.next(entry): yield entry
import os try: ctags = sys.argv[1] projectdir = sys.argv[2] except IndexError: print "Need a exurbitant ctags binary and a project dir" sys.exit(1) stat, output = c.getstatusoutput("%s -f /tmp/ctags-blub -R %s" % (ctags, projectdir)) if stat != 0: print "Error when running ctags: %s" % output sys.exit(1) try: tagfile = CTags("/tmp/ctags-blub") except: print "Error when reading ctags file" sys.exit(1) # collect all tags for a sorted tag fileCollection = dict() entry = TagEntry() status = tagfile.first(entry) fileCollection[entry['file']] = [(entry['name'], entry['kind'], entry['lineNumber'], entry['pattern'])] while tagfile.next(entry): addEntry = [(entry['name'], entry['kind'], entry['lineNumber'], entry['pattern'])] try: fileCollection[entry['file']] += addEntry except KeyError:
from __future__ import print_function import sys import ctags from ctags import CTags, TagEntry try: tagFile = CTags(b"tags") except: sys.exit(1) entry = TagEntry() status = tagFile.setSortType(ctags.TAG_SORTED) status = tagFile.first(entry) print(tagFile["name"]) print(tagFile["author"]) print(tagFile["format"]) if status: print(entry["name"]) print(entry["kind"]) if tagFile.find(entry, b"find", ctags.TAG_PARTIALMATCH | ctags.TAG_IGNORECASE): print("found") print(entry["lineNumber"]) print(entry["pattern"]) print(entry["kind"]) status = tagFile.findNext(entry) if status:
import ctags, sys from ctags import CTags, TagEntry import pygraphviz as pgv try: tagFile = CTags('tags') except: sys.exit(1) entry = TagEntry() patterns = {} files = {} # TAG_PARTIALMATCH - begin with # TAG_FULLMATCH - full length matching # TAG_IGNORECASE - disable binary search # TAG_OBSERVECASE - case sensitive and allowed binary search to perform # Find the next tag matching the name and options supplied to the # most recent call to tagFile.find(). (replace the entry if found) status = tagFile.next(entry) while status: fileName, pattern = entry['file'], entry['name'] if fileName not in files: files[fileName] = [pattern] else: files[fileName] += [pattern] if pattern not in patterns: patterns[pattern] = [fileName] else: patterns[pattern] += [fileName]
#!/usr/bin/env python import ctags from ctags import CTags, TagEntry import sys try: tagFile = CTags('tags') except: print 'Error on open tags' sys.exit(1) entry = TagEntry() if len(sys.argv) == 2: if tagFile.find(entry, sys.argv[1], ctags.TAG_FULLMATCH): print entry['file'], entry['lineNumber'] else: print 'Symbol', sys.argv[1], 'not found' else: stat = tagFile.first(entry) while stat: print entry['name'], entry['file'], entry['lineNumber'], entry['kind'] stat = tagFile.next(entry)
from __future__ import print_function import ctags from ctags import CTags, TagEntry import sys try: tagFile = CTags(b'tags') except: sys.exit(1) entry = TagEntry() status = tagFile.setSortType(ctags.TAG_SORTED) status = tagFile.first(entry) print(tagFile['name']) print(tagFile['author']) print(tagFile['format']) if status: print(entry['name']) print(entry['kind']) if tagFile.find(entry, b'find', ctags.TAG_PARTIALMATCH | ctags.TAG_IGNORECASE): print('found') print(entry['lineNumber']) print(entry['pattern']) print(entry['kind']) status = tagFile.findNext(entry) if status: print(entry['lineNumber'])
import ctags, re, simplejson, sys, os from ctags import CTags, TagEntry # file generated by ctags --fields=afmikKlnsStz --c-kinds=+pc -R tags = CTags('tags') entry = TagEntry() sct_file = open('arch/x86/kernel/syscall_table_32.S', 'r') sys_calls = [] i = 0 for line in sct_file: name = re.search(".long (\w*)", line) if(name): name = name.group(1) is_ptregs = False if(name == "sys_ni_syscall"): sys_calls.append([i, "not implemented", "", "%0#4x"%(i), "", "", "", "", "", "", ""]) i += 1 continue # take care of ptregs elif(name.find('ptregs_') == 0): name = name.replace("ptregs_", "sys_") is_ptregs = True if tags.find(entry, name, ctags.TAG_FULLMATCH | ctags.TAG_OBSERVECASE): found_sym = False while(not found_sym): if(entry['kind'] == 'prototype'): found_sym = True details = [i, name, entry['signature']]
def _getFunctionLines(self, file_layout_src, file_commit): ''' computes the line numbers of each function in the file ''' ''' - Input - file_name: original name of the file, used only to determine the programming language (ie. file.c is a c-language file) file_layout_scr: dictionary with key=line number value = line of code file_commit: fileCommit instance where the results will be stored - Description - The file_layout is used to construct a source code file that can be parsed by ctags to generate a ctags file. The ctags file is then accessed to extract the function tags and line numbers to be save in the fileCommit object ''' # grab the file extension to determine the language of the file fileExt = os.path.splitext(file_commit.filename)[1] # temporary file where we write transient data needed for ctags srcFile = tempfile.NamedTemporaryFile(suffix=fileExt) tagFile = tempfile.NamedTemporaryFile() # generate a source code file from the file_layout_src dictionary # and save it to a temporary location for line in file_layout_src: srcFile.write(line) srcFile.flush() # run ctags analysis on the file to create a tags file cmd = "ctags-exuberant -f {0} --fields=nk {1}".format(tagFile.name, srcFile.name).split() output = execute_command(cmd).splitlines() # parse ctags try: tags = CTags(tagFile.name) except: log.critical("failure to load ctags file") raise Error("failure to load ctags file") # locate line numbers and structure names entry = TagEntry() funcLines = {} # select the language structures we are interested in identifying # f = functions, s = structs, c = classes, n = namespace # p = function prototype, g = enum, d = macro, t= typedef, u = union structures = ["f", "s", "c", "n", "p", "g", "d", "t", "u"] # TODO: investigate other languages and how ctags assigns the structure # tags, we may need more languages specific assignments in # addition to java and c# files, use "ctags --list-kinds" to # see all tag meanings per language if fileExt in (".java", ".j", ".jav", ".cs", ".js"): structures.append("m") # methods structures.append("i") # interface elif fileExt in (".php"): structures.append("i") # interface structures.append("j") # functions elif fileExt in (".py"): structures.append("m") # class members while(tags.next(entry)): if entry['kind'] in structures: funcLines[int(entry['lineNumber'])] = entry['name'] # clean up temporary files srcFile.close() tagFile.close() # save result to the file commit instance file_commit.setFunctionLines(funcLines)
import ctags, re, simplejson, sys, os from ctags import CTags, TagEntry # file generated by ctags --fields=afmikKlnsStz --c-kinds=+pc -R tags = CTags('tags') entry = TagEntry() sct_file = open('arch/x86/kernel/syscall_table_32.S', 'r') sys_calls = [] i = 0 for line in sct_file: name = re.search(".long (\w*)", line) if (name): name = name.group(1) is_ptregs = False if (name == "sys_ni_syscall"): sys_calls.append([ i, "not implemented", "", "%0#4x" % (i), "", "", "", "", "", "", "" ]) i += 1 continue # take care of ptregs elif (name.find('ptregs_') == 0): name = name.replace("ptregs_", "sys_") is_ptregs = True if tags.find(entry, name, ctags.TAG_FULLMATCH | ctags.TAG_OBSERVECASE): found_sym = False while (not found_sym):
def _find_github_tag(phenny, fname, types=("c", "f", "t")): import ctags from ctags import CTags, TagEntry t = CTags(phenny.config.tagfile) e = TagEntry() if not t.find(e, fname, ctags.TAG_PARTIALMATCH): phenny.say("Could not find any tags matching %s" % fname) return tags = [getTag(e)] while t.findNext(e): if e["kind"] in types: tags.append(getTag(e)) newtags = [] for e in tags: if e not in newtags: newtags.append(e) phenny.say("Found %s possible matches. Displaying %s" % (len(newtags), min(len(newtags), 5))) for entry in tags[:5]: url = "https://github.com/%s/tree/%s/%s" % (phenny.config.github_project, "master", entry["file"]) if entry["lineNumber"]: url += "#%s" % entry["lineNumber"] url = shorten(url) phenny.say("%s (%s) found in %s: %s" % (entry["pattern"], entry["kind"], entry["file"], url))
def generate(sysent_path, ctags_path, output_path): syscall_data = {} print(">>> Processing syscallent.h file...", file=sys.stderr, end=' ') with open(sysent_path, "r") as fin: for line in fin: line = line.strip() m = re.match(sysent_pattern, line) syscall = {} if m: syscall['num'] = int(m.group(1).strip()) data = re.split(r'[",\t ]+', m.group(2).strip()) syscall['name'] = data[3] syscall['flags'] = fix_flags(data[1]) syscall['complete'] = False syscall_data[syscall['num']] = syscall print("done.", file=sys.stderr) print(">>> Processing kernel ctags to get the function signatures...", file=sys.stderr, end=' ') tags = CTags(ctags_path) entry = TagEntry() i = 0 for k, syscall in syscall_data.items(): if tags.find(entry, "sys_%s" % syscall['name'], ctags.TAG_FULLMATCH | ctags.TAG_OBSERVECASE): while entry['kind'] != 'prototype': if not tags.findNext(entry): print("Could not find signature for {}".format(syscall['name']), file=sys.stderr) break sig = process_signature(entry['signature']) syscall['signature_str'] = sig_to_str(sig) syscall['args'] = "\n".join([arg_template.format(**x) for x in sig]) syscall['file_info'] = "{}:{}".format(entry['file'], entry['lineNumber']) syscall['complete'] = 'true' else: print("Could not find signature for {}".format(syscall['name']), file=sys.stderr) syscall['signature_str'] = "?" syscall['args'] = '' syscall['file_info'] = '?' syscall['complete'] = 'false' print("done.", file=sys.stderr) with open(output_path, "w") as fout: fout.write(out_start.format(includes="\n".join(includes))) i = 0 for syscall in sorted(syscall_data.values(), key=lambda x: x['num']): if syscall['num'] != i: raise Exception("There's a gap in syscall table.") fout.write(item_template.format(**syscall)) i += 1 fout.write(out_end)