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-02-01 Nico: Add support for 'disable', 'using', scripting, 'virtual' rules
37 ;; 2009-11-05 Nico: Cleanups, Change shortcut % to C-M-% (% is used in Python rule)
38 ;; Some cleanups done by Rene Rydhof Hansen
42 (defun join-sep (sep xs
)
43 (mapconcat 'identity xs sep
))
53 (defface cocci-number-face
54 '((((background light
)) (:foreground
"black"))
55 (((background dark
)) (:foreground
"yellow3")))
56 "Used for Cocci numbers")
58 (defface cocci-punctuation-face
59 '((((background light
)) (:foreground
"black"))
60 (((background dark
)) (:foreground
"cyan")))
61 "Used for punctuation")
63 (defface cocci-problem-face
64 '((((background light
)) (:background
"deep pink"))
65 (((background dark
)) (:background
"deep pink")))
66 "Highlighting potential problems")
68 (defface cocci-special-face
69 '((((background light
)) (:foreground
"blue"))
70 (((background dark
)) (:foreground
"red")))
73 (defface cocci-rulename-face
74 '((((background light
)) (:foreground
"DarkSlateGray"))
75 (((background dark
)) (:foreground
"DarkSlateGray4")))
76 "Highlighting the rule names")
78 (defface cocci-minus-face
79 '((((background light
)) (:foreground
"red"))
80 (((background dark
)) (:foreground
"SeaGreen3")))
81 "Highlighting lines to be removed")
83 (defface cocci-plus-face
84 '((((background light
)) (:foreground
"dark green"))
85 (((background dark
)) (:foreground
"salmon")))
86 "Highlighting lines to be added")
88 (defface cocci-match-face
89 '((((background light
)) (:foreground
"violet red"))
90 (((background dark
)) (:foreground
"purple")))
91 "Highlighting lines to be matched (sgrep)")
94 ;; can look in lexer_cocci.mll for new identifiers
96 (defconst cocci-c-keywords-list
97 '("if" "else" "while" "do" "for" "return"
100 "static" "extern" "const" "volatile"
105 (defconst cocci-declaration-keywords-list
106 '("identifier" "type" "parameter" "constant" "expression" "statement"
107 "function" "local" "list"
115 "declarer" "iterator"
119 "char" "short" "int" "float" "double" "long"
124 (defconst cocci-iso-keywords-list
125 '("Expression" "Statement" "Type"
126 "Declaration" "TopLevel" "ArgExpression"
131 (defconst c-preprocessor-directives-list
133 "if" "ifdef" "elif" "else" "endif" "ifndef"
139 (setq cocci-font-lock-keywords
141 ; For virtual rule declarations
142 ("^[ \t]*\\(virtual\\)\\b\\(.*\\)"
143 (1 'cocci-special-face
)
144 (2 'cocci-rulename-face
)
147 ; blink possible errors, when - or + is not in first column
148 ("^[ \t]+[-+]" .
'cocci-problem-face
)
151 ("^\\??\\+.*" .
'cocci-plus-face
)
152 ("^\\??-.*" .
'cocci-minus-face
)
154 ("^\\*.*" .
'cocci-match-face
)
155 ;("^\\??\\+.*?//" . 'cocci-plus-face)
161 ("#\\(include\\) *\\(.*\\)"
162 (1 'font-lock-builtin-face
)
163 (2 'font-lock-string-face
)
167 ("//.*" .
'font-lock-comment-face
)
170 ("\"[^\"]*\"" .
'font-lock-string-face
)
173 ("@[ \t]*@" .
'cocci-special-face
)
174 ; this rule may seems redundant with the following one, but
175 ; without it, @@ int x; @@ would color the int x with rulename-face.
176 ; by using this rule, we color the @@ and so prevent the
177 ; next rule to be applied (cf font-lock semantic when have not the
180 ("\\(@\\)\\(.*\\)\\(@\\)"
181 (1 'cocci-special-face
)
182 (2 'cocci-rulename-face
)
183 (3 'cocci-special-face
)
186 ("@.*\\b\\(extends\\|\\(depends[ \t]*on\\)\\)\\b.*@"
187 (1 'cocci-special-face t
))
189 ("@.*\\b\\(disable\\)\\b.*@"
190 (1 'cocci-special-face t
))
192 ("@.*\\b\\(using\\)\\b.*@"
193 (1 'cocci-special-face t
))
195 ("@.*\\b\\(initialize\\)[ \t]*:[ \t]*\\(.*\\)[ \t]*@"
196 (1 'cocci-special-face t
)
197 (2 'cocci-script-face t
)
200 ("@.*\\b\\(script\\)[ \t]*:[ \t]*\\(.*\\)[ \t]*@"
201 (1 'cocci-special-face t
)
202 (2 'cocci-script-face t
)
205 ("@.*\\b\\(finalize\\)[ \t]*:[ \t]*\\(.*\\)[ \t]*@"
206 (1 'cocci-special-face t
)
207 (2 'cocci-script-face t
)
210 ;old: does not work, not easy to handle the rule1, rule2, rule3 list.
211 ; ("@[ \t]*\\(\\(\\w+\\)[ \t,]*\\)*[ \t]*@"
212 ; ("\\(@\\)[ \t]*\\(\\w+\\)[ \t]*\\(@\\)"
213 ; ("\\(@\\)[ \t]*\\(\\w+\\)[ \t]+\\(extends\\)[ \t]+\\(\\w+\\)[ \t]*\\(@\\)"
214 ; ("\\(@\\)[ \t]*\\(\\w+\\)[ \t]+\\(depends\\)[ \t]+\\(on\\)[ \t]+\\(\\(\\w+\\)[ ,\t]*\\)+\\(@\\)"
217 ; inherited variable, fontifying rulename
219 "\\b\\(" (regexp-opt cocci-declaration-keywords-list
) "\\)\\b"
221 (2 'cocci-rulename-face
))
225 (1 'cocci-rulename-face
))
227 ; just for pad, metavariables in maj
228 ("\\b[A-Z][0-9]?\\b" . font-lock-variable-name-face
)
230 ; todo: do also for other variable, do as in font-lock.el
231 ; with font-lock-match-c-style-declaration-item-and-skip-to-next
233 ; special cocci operators
234 ("\\.\\.\\." .
'font-lock-keyword-face
)
235 ("^[()|]" .
'font-lock-keyword-face
)
237 ; escaped version of cocci operators
238 ("\\\\[()|]" .
'font-lock-keyword-face
)
240 ("\\bwhen[ \t]+!=" .
'font-lock-keyword-face
)
241 ("\\bWHEN[ \t]+!=" .
'font-lock-keyword-face
)
242 ("\\bwhen[ \t]+=" .
'font-lock-keyword-face
)
243 ("\\bWHEN[ \t]+=" .
'font-lock-keyword-face
)
246 ("<=>" .
'font-lock-keyword-face
)
247 ("=>" .
'font-lock-keyword-face
)
249 (,(concat "\\b\\(" (regexp-opt cocci-iso-keywords-list
) "\\)\\b") .
252 ("\\<[0-9]+\\>" .
'cocci-number-face
)
255 (list "(" ")" ";" "," "{" "}" "\\[" "\\]")) .
'cocci-punctuation-face
)
259 (,(concat "\\b\\(" (regexp-opt cocci-c-keywords-list
) "\\)\\b") .
260 'font-lock-keyword-face
)
262 ; cocci declaration keywords
263 (,(concat "\\b\\(" (regexp-opt cocci-declaration-keywords-list
) "\\)\\b") .
264 'font-lock-type-face
)
267 (,(concat "^#[ \t]*\\(" (regexp-opt c-preprocessor-directives-list
)
268 "\\)\\>[ \t!]*\\(\\sw+\\)?")
269 (1 'font-lock-builtin-face
))
272 ; "Expressions to highlight in cocci-mode.")
275 ;; define a mode-specific abbrev table for those who use such things
276 (defvar cocci-mode-abbrev-table nil
277 "Abbrev table used while in cocci mode.")
278 (define-abbrev-table 'cocci-mode-abbrev-table nil
)
281 (defvar cocci-mode-map nil
282 "Keymap used in `cocci-mode'.")
283 (unless cocci-mode-map
284 (setq cocci-mode-map
(make-sparse-keymap))
285 (define-key cocci-mode-map
[(meta control
*)] 'switch-between-cocci-c
)
286 (define-key cocci-mode-map
"%" 'cocci-replace-modifiers
)
288 ;(define-key cocci-mode-map "\C-c" 'compile)
292 (defvar cocci-mode-syntax-table nil
293 "Syntax table used while in cocci mode.")
294 (unless cocci-mode-syntax-table
295 (setq cocci-mode-syntax-table
(make-syntax-table))
297 ; _ is part of a word.
298 (modify-syntax-entry ?\_
"w" cocci-mode-syntax-table
)
300 ; change mode for ", bad interaction with font-lock
301 (modify-syntax-entry ?
\" "w" cocci-mode-syntax-table
)
307 ;; helper functions for the cocci programmer
309 (defun cocci-replace-modifiers (beg end str
)
312 (let ((str (read-string "New modifier string (+, -, space): "
314 (list (region-beginning) (region-end) str
)))
316 ;(interactive "rsNew modifier string (+, -, space): ")
317 (replace-regexp "^[-+]?" str nil beg end
)
320 ;Used internally while developping coccinelle.
321 ;Allow to switch between the corresponding SP and C file.
322 ;todo: handle the _verxxx naming convention.
323 (defun switch-between-cocci-c ()
326 (cond ((string-match ".c$" (buffer-name))
327 (replace-match ".cocci" t t
(buffer-name)))
328 ((string-match ".cocci$" (buffer-name))
329 (replace-match ".c" t t
(buffer-name)))
332 (if (get-buffer target
)
333 (switch-to-buffer target
)
335 (read-file-name "file: " nil nil t target
)))))
337 (eval-after-load "cc-mode"
339 (define-key c-mode-map
[(meta control
*)] 'switch-between-cocci-c
))
344 (defvar cocci-mode-hook nil
345 "Hook called by `cocci-mode'")
349 "Major mode for editing cocci code.
350 Special commands: \\{cocci-mode-map}
351 Turning on cocci-mode runs the hook `cocci-mode-hook'."
353 (kill-all-local-variables)
354 (make-local-variable 'font-lock-defaults
)
355 (make-local-variable 'comment-start
)
356 (make-local-variable 'comment-end
)
357 (make-local-variable 'compile-command
)
359 (use-local-map cocci-mode-map
)
360 (set-syntax-table cocci-mode-syntax-table
)
361 (setq mode-name
"cocci"
362 major-mode
'cocci-mode
363 local-abbrev-table cocci-mode-abbrev-table
364 font-lock-defaults
'(cocci-font-lock-keywords)
368 (easy-menu-add cocci-menu
)
370 (run-hooks 'cocci-mode-hook
)
376 (easy-menu-define cocci-menu cocci-mode-map
"Cocci menu"
378 ["Switch to corresponding C file" switch-between-cocci-c t
]
379 ["Replace modifiers" cocci-replace-modifiers t
]
384 ; put cursor before a parse error coccinelle message and it will
385 ; open the corresponding file and go to corresponding line.
386 (fset 'cocci-goto-next-error
387 [?\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])
391 (provide 'cocci-mode
)
393 ;;; cocci.el ends here