Release coccinelle-0.2.2-rc1
[bpt/coccinelle.git] / editors / emacs / cocci.el
1 ;;; cocci.el --- a major mode for editing semantic patches
2
3 ;; Copyright (C) 2010 Nicolas Palix <npalix@diku.dk>
4 ;; Copyright (C) 2006-2007 Yoann Padioleau
5
6 ;; Please imagine a long and boring gnu-style copyright notice
7 ;; appearing just here.
8
9
10 ;; Emacs Lisp Archive Entry
11 ;; Author: Padioleau Yoann <yoann.padioleau@gmail.com>,
12 ;; Version: 0.2
13 ;; Keywords: coccinelle patch refactoring program transformation
14 ;; URL: http://coccinelle.lip6.fr/
15
16
17 ;;; Usage
18
19 ;; Copy this file in your ~/.emacs.d directory
20 ;;
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)
27 ;;
28 ;; You can also use cocci-mode to edit the files containing the
29 ;; isomorphisms with:
30 ;; (setq auto-mode-alist
31 ;; (cons '("\\.iso$" . cocci-mode) auto-mode-alist))
32 ;;
33
34 ;;; History
35
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
39
40 ;;; Utilities
41
42 (defun join-sep (sep xs)
43 (mapconcat 'identity xs sep))
44
45
46 ;;; Variables
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
79 '((((background light)) (:foreground "red"))
80 (((background dark)) (:foreground "SeaGreen3")))
81 "Highlighting lines to be removed")
82
83 (defface cocci-plus-face
84 '((((background light)) (:foreground "dark green"))
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
96 (defconst cocci-c-keywords-list
97 '("if" "else" "while" "do" "for" "return"
98 "sizeof"
99 "struct" "union"
100 "static" "extern" "const" "volatile"
101 "break" "continue"
102 "switch" "case"
103 ))
104
105 (defconst cocci-declaration-keywords-list
106 '("identifier" "type" "parameter" "constant" "expression" "statement"
107 "function" "local" "list"
108 "fresh"
109 "position"
110 "idexpression"
111
112 "context"
113
114 "typedef"
115 "declarer" "iterator"
116 "pure"
117 ;"error" "words"
118
119 "char" "short" "int" "float" "double" "long"
120 "void"
121 "signed" "unsigned"
122 ))
123
124 (defconst cocci-iso-keywords-list
125 '("Expression" "Statement" "Type"
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"
135 "error" "pragma"
136 "file" "line"
137 ))
138
139 (setq cocci-font-lock-keywords
140 `(
141 ; For virtual rule declarations
142 ("^[ \t]*\\(virtual\\)\\b\\(.*\\)"
143 (1 'cocci-special-face)
144 (2 'cocci-rulename-face)
145 )
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
161 ("#\\(include\\) *\\(.*\\)"
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
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
178 ; OVERRIDE flag).
179
180 ("\\(@\\)\\(.*\\)\\(@\\)"
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
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
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]*\\)+\\(@\\)"
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
223 ;rule1.T *a;
224 ("^\\(\\w+\\)\\."
225 (1 'cocci-rulename-face))
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)
244
245 ; used in iso files
246 ("<=>" . 'font-lock-keyword-face)
247 ("=>" . 'font-lock-keyword-face)
248
249 (,(concat "\\b\\(" (regexp-opt cocci-iso-keywords-list) "\\)\\b") .
250 'cocci-special-face)
251
252 ("\\<[0-9]+\\>" . 'cocci-number-face)
253
254 (,(join-sep "\\|"
255 (list "(" ")" ";" "," "{" "}" "\\[" "\\]")) . 'cocci-punctuation-face)
256 ; . -> * + etc
257
258 ; c keywords
259 (,(concat "\\b\\(" (regexp-opt cocci-c-keywords-list) "\\)\\b") .
260 'font-lock-keyword-face)
261
262 ; cocci declaration keywords
263 (,(concat "\\b\\(" (regexp-opt cocci-declaration-keywords-list) "\\)\\b") .
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
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)
287
288 ;(define-key cocci-mode-map "\C-c" 'compile)
289 )
290
291
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))
296
297 ; _ is part of a word.
298 (modify-syntax-entry ?\_ "w" cocci-mode-syntax-table)
299
300 ; change mode for ", bad interaction with font-lock
301 (modify-syntax-entry ?\" "w" cocci-mode-syntax-table)
302 )
303
304
305 ;;; Code
306
307 ;; helper functions for the cocci programmer
308
309 (defun cocci-replace-modifiers (beg end str)
310 "TODO"
311 (interactive
312 (let ((str (read-string "New modifier string (+, -, space): "
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
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)))
330 (t
331 "none"))))
332 (if (get-buffer target)
333 (switch-to-buffer target)
334 (find-file
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
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.
350 Special commands: \\{cocci-mode-map}
351 Turning 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
374 ;; Menu
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