1 ;;; cocci.el --- a major mode for editing semantic patches
3 ;; Copyright (C) 2010 Nicolas Palix <npalix@diku.dk>
4 ;; Copyright (C) 2006-2007 Yoann Padioleau
6 ;; Please imagine a long and boring gnu-style copyright notice
7 ;; appearing just here.
10 ;; Emacs Lisp Archive Entry
11 ;; Author: Padioleau Yoann <yoann.padioleau@gmail.com>,
13 ;; Keywords: coccinelle patch refactoring program transformation
14 ;; URL: http://coccinelle.lip6.fr/
19 ;; Copy this file in your ~/.emacs.d directory
21 ;; Add the following lines to your ~/.emacs or equivalent:
22 ;; (load "~/.emacs.d/cocci.el")
23 ;; (setq auto-mode-alist
24 ;; (cons '("\\.cocci$" . cocci-mode) auto-mode-alist))
25 ;; (autoload 'cocci-mode "cocci"
26 ;; "Major mode for editing cocci code." t)
28 ;; You can also use cocci-mode to edit the files containing the
30 ;; (setq auto-mode-alist
31 ;; (cons '("\\.iso$" . cocci-mode) auto-mode-alist))
36 ;; 2010-04-02 Nico: Fix 'script' with 'depends on'. Add 'when forall', 'when any'
37 ;; 2010-02-01 Nico: Add support for 'disable', 'using', scripting, 'virtual' rules
38 ;; 2009-11-05 Nico: Cleanups, Change shortcut % to C-M-% (% is used in Python rule)
39 ;; Some cleanups done by Rene Rydhof Hansen
43 (defun join-sep (sep xs
)
44 (mapconcat 'identity xs sep
))
54 (defface cocci-number-face
55 '((((background light
)) (:foreground
"black"))
56 (((background dark
)) (:foreground
"yellow3")))
57 "Used for Cocci numbers")
59 (defface cocci-punctuation-face
60 '((((background light
)) (:foreground
"black"))
61 (((background dark
)) (:foreground
"cyan")))
62 "Used for punctuation")
64 (defface cocci-problem-face
65 '((((background light
)) (:background
"deep pink"))
66 (((background dark
)) (:background
"deep pink")))
67 "Highlighting potential problems")
69 (defface cocci-special-face
70 '((((background light
)) (:foreground
"blue"))
71 (((background dark
)) (:foreground
"red")))
74 (defface cocci-rulename-face
75 '((((background light
)) (:foreground
"DarkSlateGray"))
76 (((background dark
)) (:foreground
"DarkSlateGray4")))
77 "Highlighting the rule names")
79 (defface cocci-minus-face
80 '((((background light
)) (:foreground
"red"))
81 (((background dark
)) (:foreground
"SeaGreen3")))
82 "Highlighting lines to be removed")
84 (defface cocci-plus-face
85 '((((background light
)) (:foreground
"dark green"))
86 (((background dark
)) (:foreground
"salmon")))
87 "Highlighting lines to be added")
89 (defface cocci-match-face
90 '((((background light
)) (:foreground
"violet red"))
91 (((background dark
)) (:foreground
"purple")))
92 "Highlighting lines to be matched (sgrep)")
94 (defface cocci-script-face
95 '((((background light
)) (:foreground
"red"))
96 (((background dark
)) (:foreground
"SeaGreen3")))
97 "Highlighting script language name")
100 ;; can look in lexer_cocci.mll for new identifiers
102 (defconst cocci-c-keywords-list
103 '("if" "else" "while" "do" "for" "return"
106 "static" "extern" "const" "volatile"
111 (defconst cocci-declaration-keywords-list
112 '("identifier" "type" "parameter" "constant" "expression" "statement"
113 "function" "local" "list"
121 "declarer" "iterator"
125 "char" "short" "int" "float" "double" "long"
130 (defconst cocci-iso-keywords-list
131 '("Expression" "Statement" "Type"
132 "Declaration" "TopLevel" "ArgExpression"
137 (defconst c-preprocessor-directives-list
139 "if" "ifdef" "elif" "else" "endif" "ifndef"
145 (setq cocci-font-lock-keywords
147 ; For virtual rule declarations
148 ("^[ \t]*\\(virtual\\)\\b\\(.*\\)"
149 (1 'cocci-special-face
)
150 (2 'cocci-rulename-face
)
153 ; blink possible errors, when - or + is not in first column
154 ("^[ \t]+[-+]" .
'cocci-problem-face
)
157 ("^\\??\\+.*" .
'cocci-plus-face
)
158 ("^\\??-.*" .
'cocci-minus-face
)
160 ("^\\*.*" .
'cocci-match-face
)
161 ;("^\\??\\+.*?//" . 'cocci-plus-face)
167 ("#\\(include\\) *\\(.*\\)"
168 (1 'font-lock-builtin-face
)
169 (2 'font-lock-string-face
)
173 ("//.*" .
'font-lock-comment-face
)
176 ("\"[^\"]*\"" .
'font-lock-string-face
)
179 ("@[ \t]*@" .
'cocci-special-face
)
180 ; this rule may seems redundant with the following one, but
181 ; without it, @@ int x; @@ would color the int x with rulename-face.
182 ; by using this rule, we color the @@ and so prevent the
183 ; next rule to be applied (cf font-lock semantic when have not the
186 ("\\(@\\)\\(.*\\)\\(@\\)"
187 (1 'cocci-special-face
)
188 (2 'cocci-rulename-face
)
189 (3 'cocci-special-face
)
192 ("@.*\\b\\(extends\\|\\(depends[ \t]*on\\)\\)\\b.*@"
193 (1 'cocci-special-face t
))
195 ("@.*\\b\\(disable\\)\\b.*@"
196 (1 'cocci-special-face t
))
198 ("@.*\\b\\(using\\)\\b.*@"
199 (1 'cocci-special-face t
))
201 ("@.*\\b\\(initialize\\)[ \t]*:[ \t]*\\(.*\\)[ \t]*@"
202 (1 'cocci-special-face t
)
203 (2 'cocci-script-face t
)
206 ("@.*\\b\\(script\\)[ \t]*:[ \t]*\\([^ ]*\\)[ \t]*.*@"
207 (1 'cocci-special-face t
)
208 (2 'cocci-script-face t
)
211 ("@.*\\b\\(finalize\\)[ \t]*:[ \t]*\\(.*\\)[ \t]*@"
212 (1 'cocci-special-face t
)
213 (2 'cocci-script-face t
)
216 ;old: does not work, not easy to handle the rule1, rule2, rule3 list.
217 ; ("@[ \t]*\\(\\(\\w+\\)[ \t,]*\\)*[ \t]*@"
218 ; ("\\(@\\)[ \t]*\\(\\w+\\)[ \t]*\\(@\\)"
219 ; ("\\(@\\)[ \t]*\\(\\w+\\)[ \t]+\\(extends\\)[ \t]+\\(\\w+\\)[ \t]*\\(@\\)"
220 ; ("\\(@\\)[ \t]*\\(\\w+\\)[ \t]+\\(depends\\)[ \t]+\\(on\\)[ \t]+\\(\\(\\w+\\)[ ,\t]*\\)+\\(@\\)"
223 ; inherited variable, fontifying rulename
225 "\\b\\(" (regexp-opt cocci-declaration-keywords-list
) "\\)\\b"
227 (2 'cocci-rulename-face
))
231 (1 'cocci-rulename-face
))
233 ; just for pad, metavariables in maj
234 ("\\b[A-Z][0-9]?\\b" . font-lock-variable-name-face
)
236 ; todo: do also for other variable, do as in font-lock.el
237 ; with font-lock-match-c-style-declaration-item-and-skip-to-next
239 ; special cocci operators
240 ("\\.\\.\\." .
'font-lock-keyword-face
)
241 ("^[()|]" .
'font-lock-keyword-face
)
243 ; escaped version of cocci operators
244 ("\\\\[()|]" .
'font-lock-keyword-face
)
246 ("\\bwhen[ \t]+!=" .
'font-lock-keyword-face
)
247 ("\\bWHEN[ \t]+!=" .
'font-lock-keyword-face
)
248 ("\\bwhen[ \t]+=" .
'font-lock-keyword-face
)
249 ("\\bWHEN[ \t]+=" .
'font-lock-keyword-face
)
250 ("\\bwhen[ \t]+forall" .
'font-lock-keyword-face
)
251 ("\\bWHEN[ \t]+forall" .
'font-lock-keyword-face
)
252 ("\\bwhen[ \t]+any" .
'font-lock-keyword-face
)
253 ("\\bWHEN[ \t]+any" .
'font-lock-keyword-face
)
256 ("<=>" .
'font-lock-keyword-face
)
257 ("=>" .
'font-lock-keyword-face
)
259 (,(concat "\\b\\(" (regexp-opt cocci-iso-keywords-list
) "\\)\\b") .
262 ("\\<[0-9]+\\>" .
'cocci-number-face
)
265 (list "(" ")" ";" "," "{" "}" "\\[" "\\]")) .
'cocci-punctuation-face
)
269 (,(concat "\\b\\(" (regexp-opt cocci-c-keywords-list
) "\\)\\b") .
270 'font-lock-keyword-face
)
272 ; cocci declaration keywords
273 (,(concat "\\b\\(" (regexp-opt cocci-declaration-keywords-list
) "\\)\\b") .
274 'font-lock-type-face
)
277 (,(concat "^#[ \t]*\\(" (regexp-opt c-preprocessor-directives-list
)
278 "\\)\\>[ \t!]*\\(\\sw+\\)?")
279 (1 'font-lock-builtin-face
))
282 ; "Expressions to highlight in cocci-mode.")
285 ;; define a mode-specific abbrev table for those who use such things
286 (defvar cocci-mode-abbrev-table nil
287 "Abbrev table used while in cocci mode.")
288 (define-abbrev-table 'cocci-mode-abbrev-table nil
)
291 (defvar cocci-mode-map nil
292 "Keymap used in `cocci-mode'.")
293 (unless cocci-mode-map
294 (setq cocci-mode-map
(make-sparse-keymap))
295 (define-key cocci-mode-map
[(meta control
*)] 'switch-between-cocci-c
)
296 (define-key cocci-mode-map
"%" 'cocci-replace-modifiers
)
298 ;(define-key cocci-mode-map "\C-c" 'compile)
302 (defvar cocci-mode-syntax-table nil
303 "Syntax table used while in cocci mode.")
304 (unless cocci-mode-syntax-table
305 (setq cocci-mode-syntax-table
(make-syntax-table))
307 ; _ is part of a word.
308 (modify-syntax-entry ?\_
"w" cocci-mode-syntax-table
)
310 ; change mode for ", bad interaction with font-lock
311 (modify-syntax-entry ?
\" "w" cocci-mode-syntax-table
)
317 ;; helper functions for the cocci programmer
319 (defun cocci-replace-modifiers (beg end str
)
322 (let ((str (read-string "New modifier string (+, -, space): "
324 (list (region-beginning) (region-end) str
)))
326 ;(interactive "rsNew modifier string (+, -, space): ")
327 (replace-regexp "^[-+]?" str nil beg end
)
330 ;Used internally while developping coccinelle.
331 ;Allow to switch between the corresponding SP and C file.
332 ;todo: handle the _verxxx naming convention.
333 (defun switch-between-cocci-c ()
336 (cond ((string-match ".c$" (buffer-name))
337 (replace-match ".cocci" t t
(buffer-name)))
338 ((string-match ".cocci$" (buffer-name))
339 (replace-match ".c" t t
(buffer-name)))
342 (if (get-buffer target
)
343 (switch-to-buffer target
)
345 (read-file-name "file: " nil nil t target
)))))
347 (eval-after-load "cc-mode"
349 (define-key c-mode-map
[(meta control
*)] 'switch-between-cocci-c
))
354 (defvar cocci-mode-hook nil
355 "Hook called by `cocci-mode'")
359 "Major mode for editing cocci code.
360 Special commands: \\{cocci-mode-map}
361 Turning on cocci-mode runs the hook `cocci-mode-hook'."
363 (kill-all-local-variables)
364 (make-local-variable 'font-lock-defaults
)
365 (make-local-variable 'comment-start
)
366 (make-local-variable 'comment-end
)
367 (make-local-variable 'compile-command
)
369 (use-local-map cocci-mode-map
)
370 (set-syntax-table cocci-mode-syntax-table
)
371 (setq mode-name
"cocci"
372 major-mode
'cocci-mode
373 local-abbrev-table cocci-mode-abbrev-table
374 font-lock-defaults
'(cocci-font-lock-keywords)
378 (easy-menu-add cocci-menu
)
380 (run-hooks 'cocci-mode-hook
)
386 (easy-menu-define cocci-menu cocci-mode-map
"Cocci menu"
388 ["Switch to corresponding C file" switch-between-cocci-c t
]
389 ["Replace modifiers" cocci-replace-modifiers t
]
394 ; put cursor before a parse error coccinelle message and it will
395 ; open the corresponding file and go to corresponding line.
396 (fset 'cocci-goto-next-error
397 [?\C-s ?F ?i ?l ?e right right ?\C- ?\C-s ?
" left ?\M-w ?\C-x ?\C-f S-insert return ?\C-\M-l C-right right C-S-right C-insert ?\C-\M-l ?\M-g S-insert return])
401 (provide 'cocci-mode
)
403 ;;; cocci.el ends here