Chinaunix
标题:
分享个emacs中查找SYSCALL_DEFINE定义的系统调用的函数
[打印本页]
作者:
csern
时间:
2011-02-28 22:55
标题:
分享个emacs中查找SYSCALL_DEFINE定义的系统调用的函数
最近迷上了emacs,看代码时使用的gnu global的gtags插件,毕竟是自家产的,配合起来使用还是挺舒服的,在输入要查找的函数变量定义时可以用tab补齐,
可是发现查找内核代码中使用SYSCALL_DEFINE定义的系统调用时没什么好的办法,最初只能用
$ find . -name "*.[ch]" | xargs grep -E "^SYSCALL_DEFINE[0-6]*\(socketcall.*\)$"
复制代码
之类的grep,但是总是先grep后打开也不是长久之计,而且速度真的很慢。
后来直接在emacs中使用gtags-find-pattern来使用正则表达式查找,这倒是能在emacs中直接定位了,但是内部还是调用的grep,所以速度还是很慢,
而直接使用gtags-find-tag查找SYSCALL_DEFINE0,SYSCALL_DEFINE1之类的定义非常快,因为它使用的已建立好的tag文件,根据这个想法写了一个函数,
原理就是先查找SYSCALL_DEFINE系列宏的定义,然后再删除掉不匹配的行,使用起来速度是非常快的,再定一个快捷键,以后就不为这个发愁了。
(add-hook 'gtags-mode-hook
(lambda ()
(define-key gtags-mode-map (kbd "M-.") 'gtags-find-tag)
(define-key gtags-mode-map (kbd "M-, s") 'gtags-find-symbol)
(define-key gtags-mode-map (kbd "M-, r") 'gtags-find-rtag)
(define-key gtags-mode-map (kbd "M-, f") 'gtags-find-file)
(define-key gtags-mode-map (kbd "M-, p") 'gtags-find-pattern)
(define-key gtags-mode-map (kbd "M-, k") 'sec-gtags-find-kernel-syscall)
(define-key gtags-mode-map (kbd "M-*") 'gtags-pop-stack)
(setq gtags-path-style 'absolute)))
(defun sec-gtags-find-kernel-syscall (&optional other-win)
"*Find linux kernel system call quickly.
However, you can use `gtags-find-pattern' with regexp `^SYSCALL_DEFINE[0-6]*\(XXX.*\) to find the
syscall which defined with `SYSCALL_DEFINE' family macro, but this is very slow.
In this function, we use a efficiency way to do this job:
-- 1. find the define of all the `SYSCALL_DEFINE' family macro, and put them in a buffer, this only
waste little time.
-- 2. kill the lines which not match our regexp."
(interactive)
(let (tagname prompt input)
;; Get the tagname we want to find.
(setq tagname (gtags-current-token))
(if tagname
(setq prompt (concat "Find syscall: (default " tagname ") "))
(setq prompt "Find syscall: "))
(setq input (completing-read prompt 'gtags-completing-gsyms
nil nil nil gtags-history-list))
(if (not (equal "" input)) (setq tagname input))
(gtags-push-context)
;; Find begin.
(let (option save prefix buffer lines)
(setq save (current-buffer))
;; Use always ctags-x format.
(setq option "-x")
(setq prefix "(SYSCALL)")
;; Load tag
(if gtags-select-buffer-single
(progn
;; Delete "*GTAGS SELECT*" buffer info from gtags-buffer-stack and gtags-point-stack.
(let (now-gtags-buffer-stack now-buffer now-gtags-point-stack now-point)
(setq now-gtags-buffer-stack (reverse gtags-buffer-stack))
(setq now-gtags-point-stack (reverse gtags-point-stack))
(setq gtags-buffer-stack nil)
(setq gtags-point-stack nil)
(while now-gtags-buffer-stack
(setq now-buffer (car now-gtags-buffer-stack))
(setq now-point (car now-gtags-point-stack))
(if (and (buffer-name now-buffer) (not (string-match "*GTAGS SELECT*" (buffer-name now-buffer))))
(progn
(setq gtags-buffer-stack (cons now-buffer gtags-buffer-stack))
(setq gtags-point-stack (cons now-point gtags-point-stack))))
(setq now-gtags-buffer-stack (cdr now-gtags-buffer-stack))
(setq now-gtags-point-stack (cdr now-gtags-point-stack))))
;; Kill "*GTAGS SELECT*" buffer.
(let (now-buffer-list now-buffer)
(setq now-buffer-list (buffer-list))
(while now-buffer-list
(setq now-buffer (car now-buffer-list))
(if (string-match "*GTAGS SELECT*" (buffer-name now-buffer))
(kill-buffer now-buffer))
(setq now-buffer-list (cdr now-buffer-list))))))
;; Select "*GTAGS SELECT*" buffer.
(setq buffer (generate-new-buffer (generate-new-buffer-name (concat "*GTAGS SELECT* " prefix tagname))))
(set-buffer buffer)
;; Path style is defined in gtags-path-style:
;; - root : relative from the root of the project (Default)
;; - relative : relative from the current directory
;; - absolute : absolute (relative from the system root directory)
(cond
((equal gtags-path-style 'absolute)
(setq option (concat option "a")))
((equal gtags-path-style 'root)
(let (rootdir)
(if gtags-rootdir
(setq root-dir gtags-rootdir)
(setq rootdir (gtags-get-rootpath)))
(if rootdir (cd rootdir)))))
(message "Searching %s ..." tagname)
(if (not (= 0 (call-process "global" nil t nil option "SYSCALL_DEFINE[0-6]*")))
;; Some error occured.
(progn (message (buffer-substring (point-min)(1- (point-max))))
(gtags-pop-context))
;; Call process success.
(keep-lines (concat "^.*SYSCALL_DEFINE[0-6]*\(" tagname ".*\)$") (point-min) (point-max))
(goto-char (point-min))
(setq lines (count-lines (point-min) (point-max)))
(cond
((= 0 lines)
(message "%s: syscall not found" tagname)
(gtags-pop-context)
(kill-buffer buffer)
(set-buffer save))
((= 1 lines)
(message "Searching %s ... Done" tagname)
(gtags-select-it t other-win))
(t
(if (null other-win)
(switch-to-buffer buffer)
(switch-to-buffer-other-window buffer))
(gtags-select-mode)))))))
复制代码
作者:
logicBaby
时间:
2011-03-02 09:28
(x)cscope+emacs
不用这么多配置,好使的很!
作者:
crazyshell
时间:
2011-03-02 09:48
cscope足矣
作者:
csern
时间:
2011-03-02 09:54
回复
2#
logicBaby
cscope也不能直接定位SYSCALL_DEFINE定义的系统调用函数吧,当时用vim+cscope的时候也是靠:cs f e 加正则搜索的,另外如果用emacs,建议试一下global,它在查找时的tab补全是很方便的。比如要查找个函数,只记得函数名是以br开头的了,输入后tab一下就会提示出所有以br开头的可供选择的函数了,还有一些特性是相当不错的。
作者:
csern
时间:
2011-03-02 09:55
回复
3#
crazyshell
cscope可以直接定位这样的定义么
欢迎光临 Chinaunix (http://bbs.chinaunix.net/)
Powered by Discuz! X3.2