Release coccinelle-0.2.2-rc1
[bpt/coccinelle.git] / editors / emacs / cocci.el
CommitLineData
34e49164
C
1;;; cocci.el --- a major mode for editing semantic patches
2
c3e37e97 3;; Copyright (C) 2010 Nicolas Palix <npalix@diku.dk>
34e49164
C
4;; Copyright (C) 2006-2007 Yoann Padioleau
5
7f004419 6;; Please imagine a long and boring gnu-style copyright notice
34e49164
C
7;; appearing just here.
8
9
10;; Emacs Lisp Archive Entry
7f004419 11;; Author: Padioleau Yoann <yoann.padioleau@gmail.com>,
34e49164
C
12;; Version: 0.2
13;; Keywords: coccinelle patch refactoring program transformation
7f004419 14;; URL: http://coccinelle.lip6.fr/
34e49164
C
15
16
17;;; Usage
18
1be43e12
C
19;; Copy this file in your ~/.emacs.d directory
20;;
34e49164 21;; Add the following lines to your ~/.emacs or equivalent:
1be43e12 22;; (load "~/.emacs.d/cocci.el")
7f004419 23;; (setq auto-mode-alist
34e49164 24;; (cons '("\\.cocci$" . cocci-mode) auto-mode-alist))
7f004419 25;; (autoload 'cocci-mode "cocci"
34e49164
C
26;; "Major mode for editing cocci code." t)
27;;
7f004419
C
28;; You can also use cocci-mode to edit the files containing the
29;; isomorphisms with:
30;; (setq auto-mode-alist
34e49164
C
31;; (cons '("\\.iso$" . cocci-mode) auto-mode-alist))
32;;
33
7f004419 34;;; History
34e49164 35
c3e37e97 36;; 2010-02-01 Nico: Add support for 'disable', 'using', scripting, 'virtual' rules
7f004419 37;; 2009-11-05 Nico: Cleanups, Change shortcut % to C-M-% (% is used in Python rule)
34e49164
C
38;; Some cleanups done by Rene Rydhof Hansen
39
7f004419 40;;; Utilities
34e49164 41
7f004419 42(defun join-sep (sep xs)
34e49164
C
43 (mapconcat 'identity xs sep))
44
45
7f004419 46;;; Variables
34e49164
C
47
48(defvar cocci-menu)
49
50
51;; new (color) faces
52
53(defface cocci-number-face
54 '((((background light)) (:foreground "black"))
55 (((background dark)) (:foreground "yellow3")))
56 "Used for Cocci numbers")
57
58(defface cocci-punctuation-face
59 '((((background light)) (:foreground "black"))
60 (((background dark)) (:foreground "cyan")))
61 "Used for punctuation")
62
63(defface cocci-problem-face
64 '((((background light)) (:background "deep pink"))
65 (((background dark)) (:background "deep pink")))
66 "Highlighting potential problems")
67
68(defface cocci-special-face
69 '((((background light)) (:foreground "blue"))
70 (((background dark)) (:foreground "red")))
71 "")
72
73(defface cocci-rulename-face
74 '((((background light)) (:foreground "DarkSlateGray"))
75 (((background dark)) (:foreground "DarkSlateGray4")))
76 "Highlighting the rule names")
77
78(defface cocci-minus-face
0708f913 79 '((((background light)) (:foreground "red"))
34e49164
C
80 (((background dark)) (:foreground "SeaGreen3")))
81 "Highlighting lines to be removed")
82
83(defface cocci-plus-face
0708f913 84 '((((background light)) (:foreground "dark green"))
34e49164
C
85 (((background dark)) (:foreground "salmon")))
86 "Highlighting lines to be added")
87
88(defface cocci-match-face
89 '((((background light)) (:foreground "violet red"))
90 (((background dark)) (:foreground "purple")))
91 "Highlighting lines to be matched (sgrep)")
92
93
94;; can look in lexer_cocci.mll for new identifiers
95
7f004419
C
96(defconst cocci-c-keywords-list
97 '("if" "else" "while" "do" "for" "return"
34e49164
C
98 "sizeof"
99 "struct" "union"
fc1ad971 100 "static" "extern" "const" "volatile"
34e49164
C
101 "break" "continue"
102 "switch" "case"
103 ))
104
7f004419 105(defconst cocci-declaration-keywords-list
34e49164 106 '("identifier" "type" "parameter" "constant" "expression" "statement"
7f004419
C
107 "function" "local" "list"
108 "fresh"
34e49164
C
109 "position"
110 "idexpression"
111
fc1ad971
C
112 "context"
113
7f004419 114 "typedef"
34e49164
C
115 "declarer" "iterator"
116 "pure"
117 ;"error" "words"
7f004419
C
118
119 "char" "short" "int" "float" "double" "long"
34e49164 120 "void"
7f004419 121 "signed" "unsigned"
34e49164
C
122 ))
123
124(defconst cocci-iso-keywords-list
7f004419 125 '("Expression" "Statement" "Type"
34e49164
C
126 "Declaration" "TopLevel" "ArgExpression"
127 ))
128
129
130
131(defconst c-preprocessor-directives-list
132 '("define" "undef"
133 "if" "ifdef" "elif" "else" "endif" "ifndef"
134 "include"
7f004419
C
135 "error" "pragma"
136 "file" "line"
34e49164
C
137 ))
138
7f004419 139(setq cocci-font-lock-keywords
34e49164 140 `(
c3e37e97
C
141 ; For virtual rule declarations
142 ("^[ \t]*\\(virtual\\)\\b\\(.*\\)"
143 (1 'cocci-special-face)
144 (2 'cocci-rulename-face)
145 )
34e49164
C
146
147 ; blink possible errors, when - or + is not in first column
148 ("^[ \t]+[-+]" . 'cocci-problem-face)
149
150 ; modifiers
151 ("^\\??\\+.*" . 'cocci-plus-face)
152 ("^\\??-.*" . 'cocci-minus-face)
153
154 ("^\\*.*" . 'cocci-match-face)
155 ;("^\\??\\+.*?//" . 'cocci-plus-face)
156 ; ! \\+
157
158 ; --- +++
159
160 ; #cpp
7f004419 161 ("#\\(include\\) *\\(.*\\)"
34e49164
C
162 (1 'font-lock-builtin-face)
163 (2 'font-lock-string-face)
164 )
165
166 ; comments
167 ("//.*" . 'font-lock-comment-face)
168
169 ; strings
170 ("\"[^\"]*\"" . 'font-lock-string-face)
171
172 ; rule header
7f004419
C
173 ("@[ \t]*@" . 'cocci-special-face)
174 ; this rule may seems redundant with the following one, but
34e49164 175 ; without it, @@ int x; @@ would color the int x with rulename-face.
7f004419 176 ; by using this rule, we color the @@ and so prevent the
34e49164
C
177 ; next rule to be applied (cf font-lock semantic when have not the
178 ; OVERRIDE flag).
179
7f004419 180 ("\\(@\\)\\(.*\\)\\(@\\)"
34e49164
C
181 (1 'cocci-special-face)
182 (2 'cocci-rulename-face)
183 (3 'cocci-special-face)
184 )
185
186 ("@.*\\b\\(extends\\|\\(depends[ \t]*on\\)\\)\\b.*@"
187 (1 'cocci-special-face t))
188
c3e37e97
C
189 ("@.*\\b\\(disable\\)\\b.*@"
190 (1 'cocci-special-face t))
191
192 ("@.*\\b\\(using\\)\\b.*@"
193 (1 'cocci-special-face t))
194
195 ("@.*\\b\\(initialize\\)[ \t]*:[ \t]*\\(.*\\)[ \t]*@"
196 (1 'cocci-special-face t)
197 (2 'cocci-script-face t)
198 )
199
200 ("@.*\\b\\(script\\)[ \t]*:[ \t]*\\(.*\\)[ \t]*@"
201 (1 'cocci-special-face t)
202 (2 'cocci-script-face t)
203 )
204
205 ("@.*\\b\\(finalize\\)[ \t]*:[ \t]*\\(.*\\)[ \t]*@"
206 (1 'cocci-special-face t)
207 (2 'cocci-script-face t)
208 )
209
34e49164
C
210 ;old: does not work, not easy to handle the rule1, rule2, rule3 list.
211 ; ("@[ \t]*\\(\\(\\w+\\)[ \t,]*\\)*[ \t]*@"
7f004419
C
212 ; ("\\(@\\)[ \t]*\\(\\w+\\)[ \t]*\\(@\\)"
213 ; ("\\(@\\)[ \t]*\\(\\w+\\)[ \t]+\\(extends\\)[ \t]+\\(\\w+\\)[ \t]*\\(@\\)"
214 ; ("\\(@\\)[ \t]*\\(\\w+\\)[ \t]+\\(depends\\)[ \t]+\\(on\\)[ \t]+\\(\\(\\w+\\)[ ,\t]*\\)+\\(@\\)"
34e49164
C
215
216
217 ; inherited variable, fontifying rulename
218 (,(concat "^"
219 "\\b\\(" (regexp-opt cocci-declaration-keywords-list) "\\)\\b"
220 ".*?\\(\\w+\\)\\.")
221 (2 'cocci-rulename-face))
222
7f004419 223 ;rule1.T *a;
34e49164
C
224 ("^\\(\\w+\\)\\."
225 (1 'cocci-rulename-face))
34e49164
C
226
227 ; just for pad, metavariables in maj
228 ("\\b[A-Z][0-9]?\\b" . font-lock-variable-name-face)
229
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
232
233 ; special cocci operators
234 ("\\.\\.\\." . 'font-lock-keyword-face)
235 ("^[()|]" . 'font-lock-keyword-face)
236
237 ; escaped version of cocci operators
238 ("\\\\[()|]" . 'font-lock-keyword-face)
239
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)
7f004419 244
34e49164
C
245 ; used in iso files
246 ("<=>" . 'font-lock-keyword-face)
247 ("=>" . 'font-lock-keyword-face)
248
7f004419 249 (,(concat "\\b\\(" (regexp-opt cocci-iso-keywords-list) "\\)\\b") .
34e49164
C
250 'cocci-special-face)
251
252 ("\\<[0-9]+\\>" . 'cocci-number-face)
253
7f004419 254 (,(join-sep "\\|"
34e49164
C
255 (list "(" ")" ";" "," "{" "}" "\\[" "\\]")) . 'cocci-punctuation-face)
256 ; . -> * + etc
257
258 ; c keywords
7f004419 259 (,(concat "\\b\\(" (regexp-opt cocci-c-keywords-list) "\\)\\b") .
34e49164
C
260 'font-lock-keyword-face)
261
262 ; cocci declaration keywords
7f004419 263 (,(concat "\\b\\(" (regexp-opt cocci-declaration-keywords-list) "\\)\\b") .
34e49164
C
264 'font-lock-type-face)
265
266 ; cpp directives
267 (,(concat "^#[ \t]*\\(" (regexp-opt c-preprocessor-directives-list)
268 "\\)\\>[ \t!]*\\(\\sw+\\)?")
269 (1 'font-lock-builtin-face))
270
271 ))
272; "Expressions to highlight in cocci-mode.")
273
274
34e49164
C
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)
279
280
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)
7f004419 287
34e49164
C
288 ;(define-key cocci-mode-map "\C-c" 'compile)
289 )
290
291
7f004419 292(defvar cocci-mode-syntax-table nil
34e49164
C
293 "Syntax table used while in cocci mode.")
294(unless cocci-mode-syntax-table
295 (setq cocci-mode-syntax-table (make-syntax-table))
296
297 ; _ is part of a word.
7f004419 298 (modify-syntax-entry ?\_ "w" cocci-mode-syntax-table)
34e49164
C
299
300 ; change mode for ", bad interaction with font-lock
7f004419 301 (modify-syntax-entry ?\" "w" cocci-mode-syntax-table)
34e49164
C
302 )
303
304
305;;; Code
306
7f004419 307;; helper functions for the cocci programmer
34e49164
C
308
309(defun cocci-replace-modifiers (beg end str)
310 "TODO"
311 (interactive
7f004419 312 (let ((str (read-string "New modifier string (+, -, space): "
34e49164
C
313 nil 'my-history)))
314 (list (region-beginning) (region-end) str)))
315
316 ;(interactive "rsNew modifier string (+, -, space): ")
317 (replace-regexp "^[-+]?" str nil beg end)
318 )
319
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 ()
324 (interactive)
325 (let ((target
7f004419 326 (cond ((string-match ".c$" (buffer-name))
34e49164 327 (replace-match ".cocci" t t (buffer-name)))
7f004419 328 ((string-match ".cocci$" (buffer-name))
34e49164
C
329 (replace-match ".c" t t (buffer-name)))
330 (t
331 "none"))))
332 (if (get-buffer target)
333 (switch-to-buffer target)
7f004419 334 (find-file
34e49164
C
335 (read-file-name "file: " nil nil t target)))))
336
337(eval-after-load "cc-mode"
338 '(progn
339 (define-key c-mode-map [(meta control *)] 'switch-between-cocci-c))
340 )
341
342
343
34e49164
C
344(defvar cocci-mode-hook nil
345 "Hook called by `cocci-mode'")
346
347;;;###autoload
348(defun cocci-mode ()
349 "Major mode for editing cocci code.
350Special commands: \\{cocci-mode-map}
351Turning on cocci-mode runs the hook `cocci-mode-hook'."
352 (interactive)
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)
358
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)
365 comment-start "//"
366 comment-end ""
367 )
368 (easy-menu-add cocci-menu)
369
370 (run-hooks 'cocci-mode-hook)
371)
372
373
7f004419 374;; Menu
34e49164
C
375
376(easy-menu-define cocci-menu cocci-mode-map "Cocci menu"
377 '("Cocci"
378 ["Switch to corresponding C file" switch-between-cocci-c t]
379 ["Replace modifiers" cocci-replace-modifiers t]
380 ))
381
382
383
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])
388;"
389
390;; Provide
391(provide 'cocci-mode)
392
393;;; cocci.el ends here