1 ;;; cocci.el --- a major mode for editing semantic patches
3 ;; Copyright (C) 2006-2007 Yoann Padioleau
5 ;; Please imagine a long and boring gnu-style copyright notice
6 ;; appearing just here.
9 ;; Emacs Lisp Archive Entry
10 ;; Author: Padioleau Yoann <yoann.padioleau@gmail.com>,
12 ;; Keywords: coccinelle patch refactoring program transformation
13 ;; URL: http://coccinelle.lip6.fr/
18 ;; Copy this file in your ~/.emacs.d directory
20 ;; Add the following lines to your ~/.emacs or equivalent:
21 ;; (load "~/.emacs.d/cocci.el")
22 ;; (setq auto-mode-alist
23 ;; (cons '("\\.cocci$" . cocci-mode) auto-mode-alist))
24 ;; (autoload 'cocci-mode "cocci"
25 ;; "Major mode for editing cocci code." t)
27 ;; You can also use cocci-mode to edit the files containing the
29 ;; (setq auto-mode-alist
30 ;; (cons '("\\.iso$" . cocci-mode) auto-mode-alist))
35 ;; 2009-11-05 Nico: Cleanups, Change shortcut % to C-M-% (% is used in Python rule)
36 ;; Some cleanups done by Rene Rydhof Hansen
40 (defun join-sep (sep xs
)
41 (mapconcat 'identity xs sep
))
51 (defface cocci-number-face
52 '((((background light
)) (:foreground
"black"))
53 (((background dark
)) (:foreground
"yellow3")))
54 "Used for Cocci numbers")
56 (defface cocci-punctuation-face
57 '((((background light
)) (:foreground
"black"))
58 (((background dark
)) (:foreground
"cyan")))
59 "Used for punctuation")
61 (defface cocci-problem-face
62 '((((background light
)) (:background
"deep pink"))
63 (((background dark
)) (:background
"deep pink")))
64 "Highlighting potential problems")
66 (defface cocci-special-face
67 '((((background light
)) (:foreground
"blue"))
68 (((background dark
)) (:foreground
"red")))
71 (defface cocci-rulename-face
72 '((((background light
)) (:foreground
"DarkSlateGray"))
73 (((background dark
)) (:foreground
"DarkSlateGray4")))
74 "Highlighting the rule names")
76 (defface cocci-minus-face
77 '((((background light
)) (:foreground
"red"))
78 (((background dark
)) (:foreground
"SeaGreen3")))
79 "Highlighting lines to be removed")
81 (defface cocci-plus-face
82 '((((background light
)) (:foreground
"dark green"))
83 (((background dark
)) (:foreground
"salmon")))
84 "Highlighting lines to be added")
86 (defface cocci-match-face
87 '((((background light
)) (:foreground
"violet red"))
88 (((background dark
)) (:foreground
"purple")))
89 "Highlighting lines to be matched (sgrep)")
92 ;; can look in lexer_cocci.mll for new identifiers
94 (defconst cocci-c-keywords-list
95 '("if" "else" "while" "do" "for" "return"
98 "static" "extern" "const" "volatile"
103 (defconst cocci-declaration-keywords-list
104 '("identifier" "type" "parameter" "constant" "expression" "statement"
105 "function" "local" "list"
113 "declarer" "iterator"
117 "char" "short" "int" "float" "double" "long"
122 (defconst cocci-iso-keywords-list
123 '("Expression" "Statement" "Type"
124 "Declaration" "TopLevel" "ArgExpression"
129 (defconst c-preprocessor-directives-list
131 "if" "ifdef" "elif" "else" "endif" "ifndef"
137 (setq cocci-font-lock-keywords
140 ; blink possible errors, when - or + is not in first column
141 ("^[ \t]+[-+]" .
'cocci-problem-face
)
144 ("^\\??\\+.*" .
'cocci-plus-face
)
145 ("^\\??-.*" .
'cocci-minus-face
)
147 ("^\\*.*" .
'cocci-match-face
)
148 ;("^\\??\\+.*?//" . 'cocci-plus-face)
154 ("#\\(include\\) *\\(.*\\)"
155 (1 'font-lock-builtin-face
)
156 (2 'font-lock-string-face
)
160 ("//.*" .
'font-lock-comment-face
)
163 ("\"[^\"]*\"" .
'font-lock-string-face
)
166 ("@[ \t]*@" .
'cocci-special-face
)
167 ; this rule may seems redundant with the following one, but
168 ; without it, @@ int x; @@ would color the int x with rulename-face.
169 ; by using this rule, we color the @@ and so prevent the
170 ; next rule to be applied (cf font-lock semantic when have not the
173 ("\\(@\\)\\(.*\\)\\(@\\)"
174 (1 'cocci-special-face
)
175 (2 'cocci-rulename-face
)
176 (3 'cocci-special-face
)
179 ("@.*\\b\\(extends\\|\\(depends[ \t]*on\\)\\)\\b.*@"
180 (1 'cocci-special-face t
))
182 ;old: does not work, not easy to handle the rule1, rule2, rule3 list.
183 ; ("@[ \t]*\\(\\(\\w+\\)[ \t,]*\\)*[ \t]*@"
184 ; ("\\(@\\)[ \t]*\\(\\w+\\)[ \t]*\\(@\\)"
185 ; ("\\(@\\)[ \t]*\\(\\w+\\)[ \t]+\\(extends\\)[ \t]+\\(\\w+\\)[ \t]*\\(@\\)"
186 ; ("\\(@\\)[ \t]*\\(\\w+\\)[ \t]+\\(depends\\)[ \t]+\\(on\\)[ \t]+\\(\\(\\w+\\)[ ,\t]*\\)+\\(@\\)"
189 ; inherited variable, fontifying rulename
191 "\\b\\(" (regexp-opt cocci-declaration-keywords-list
) "\\)\\b"
193 (2 'cocci-rulename-face
))
197 (1 'cocci-rulename-face
))
199 ; just for pad, metavariables in maj
200 ("\\b[A-Z][0-9]?\\b" . font-lock-variable-name-face
)
202 ; todo: do also for other variable, do as in font-lock.el
203 ; with font-lock-match-c-style-declaration-item-and-skip-to-next
205 ; special cocci operators
206 ("\\.\\.\\." .
'font-lock-keyword-face
)
207 ("^[()|]" .
'font-lock-keyword-face
)
209 ; escaped version of cocci operators
210 ("\\\\[()|]" .
'font-lock-keyword-face
)
212 ("\\bwhen[ \t]+!=" .
'font-lock-keyword-face
)
213 ("\\bWHEN[ \t]+!=" .
'font-lock-keyword-face
)
214 ("\\bwhen[ \t]+=" .
'font-lock-keyword-face
)
215 ("\\bWHEN[ \t]+=" .
'font-lock-keyword-face
)
218 ("<=>" .
'font-lock-keyword-face
)
219 ("=>" .
'font-lock-keyword-face
)
221 (,(concat "\\b\\(" (regexp-opt cocci-iso-keywords-list
) "\\)\\b") .
224 ("\\<[0-9]+\\>" .
'cocci-number-face
)
227 (list "(" ")" ";" "," "{" "}" "\\[" "\\]")) .
'cocci-punctuation-face
)
231 (,(concat "\\b\\(" (regexp-opt cocci-c-keywords-list
) "\\)\\b") .
232 'font-lock-keyword-face
)
234 ; cocci declaration keywords
235 (,(concat "\\b\\(" (regexp-opt cocci-declaration-keywords-list
) "\\)\\b") .
236 'font-lock-type-face
)
239 (,(concat "^#[ \t]*\\(" (regexp-opt c-preprocessor-directives-list
)
240 "\\)\\>[ \t!]*\\(\\sw+\\)?")
241 (1 'font-lock-builtin-face
))
244 ; "Expressions to highlight in cocci-mode.")
247 ;; define a mode-specific abbrev table for those who use such things
248 (defvar cocci-mode-abbrev-table nil
249 "Abbrev table used while in cocci mode.")
250 (define-abbrev-table 'cocci-mode-abbrev-table nil
)
253 (defvar cocci-mode-map nil
254 "Keymap used in `cocci-mode'.")
255 (unless cocci-mode-map
256 (setq cocci-mode-map
(make-sparse-keymap))
257 (define-key cocci-mode-map
[(meta control
*)] 'switch-between-cocci-c
)
258 (define-key cocci-mode-map
"%" 'cocci-replace-modifiers
)
260 ;(define-key cocci-mode-map "\C-c" 'compile)
264 (defvar cocci-mode-syntax-table nil
265 "Syntax table used while in cocci mode.")
266 (unless cocci-mode-syntax-table
267 (setq cocci-mode-syntax-table
(make-syntax-table))
269 ; _ is part of a word.
270 (modify-syntax-entry ?\_
"w" cocci-mode-syntax-table
)
272 ; change mode for ", bad interaction with font-lock
273 (modify-syntax-entry ?
\" "w" cocci-mode-syntax-table
)
279 ;; helper functions for the cocci programmer
281 (defun cocci-replace-modifiers (beg end str
)
284 (let ((str (read-string "New modifier string (+, -, space): "
286 (list (region-beginning) (region-end) str
)))
288 ;(interactive "rsNew modifier string (+, -, space): ")
289 (replace-regexp "^[-+]?" str nil beg end
)
292 ;Used internally while developping coccinelle.
293 ;Allow to switch between the corresponding SP and C file.
294 ;todo: handle the _verxxx naming convention.
295 (defun switch-between-cocci-c ()
298 (cond ((string-match ".c$" (buffer-name))
299 (replace-match ".cocci" t t
(buffer-name)))
300 ((string-match ".cocci$" (buffer-name))
301 (replace-match ".c" t t
(buffer-name)))
304 (if (get-buffer target
)
305 (switch-to-buffer target
)
307 (read-file-name "file: " nil nil t target
)))))
309 (eval-after-load "cc-mode"
311 (define-key c-mode-map
[(meta control
*)] 'switch-between-cocci-c
))
316 (defvar cocci-mode-hook nil
317 "Hook called by `cocci-mode'")
321 "Major mode for editing cocci code.
322 Special commands: \\{cocci-mode-map}
323 Turning on cocci-mode runs the hook `cocci-mode-hook'."
325 (kill-all-local-variables)
326 (make-local-variable 'font-lock-defaults
)
327 (make-local-variable 'comment-start
)
328 (make-local-variable 'comment-end
)
329 (make-local-variable 'compile-command
)
331 (use-local-map cocci-mode-map
)
332 (set-syntax-table cocci-mode-syntax-table
)
333 (setq mode-name
"cocci"
334 major-mode
'cocci-mode
335 local-abbrev-table cocci-mode-abbrev-table
336 font-lock-defaults
'(cocci-font-lock-keywords)
340 (easy-menu-add cocci-menu
)
342 (run-hooks 'cocci-mode-hook
)
348 (easy-menu-define cocci-menu cocci-mode-map
"Cocci menu"
350 ["Switch to corresponding C file" switch-between-cocci-c t
]
351 ["Replace modifiers" cocci-replace-modifiers t
]
356 ; put cursor before a parse error coccinelle message and it will
357 ; open the corresponding file and go to corresponding line.
358 (fset 'cocci-goto-next-error
359 [?\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])
363 (provide 'cocci-mode
)
365 ;;; cocci.el ends here