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