Release coccinelle-0.2.0rc1
[bpt/coccinelle.git] / editors / emacs / cocci.el
1 ;;; cocci.el --- a major mode for editing semantic patches
2
3 ;; Copyright (C) 2006-2007 Yoann Padioleau
4
5 ;; Please imagine a long and boring gnu-style copyright notice
6 ;; appearing just here.
7
8
9 ;; Emacs Lisp Archive Entry
10 ;; Author: Padioleau Yoann <yoann.padioleau@gmail.com>,
11 ;; Version: 0.2
12 ;; Keywords: coccinelle patch refactoring program transformation
13 ;; URL: http://coccinelle.lip6.fr/
14
15
16 ;;; Usage
17
18 ;; Copy this file in your ~/.emacs.d directory
19 ;;
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)
26 ;;
27 ;; You can also use cocci-mode to edit the files containing the
28 ;; isomorphisms with:
29 ;; (setq auto-mode-alist
30 ;; (cons '("\\.iso$" . cocci-mode) auto-mode-alist))
31 ;;
32
33 ;;; History
34
35 ;; 2009-11-05 Nico: Cleanups, Change shortcut % to C-M-% (% is used in Python rule)
36 ;; Some cleanups done by Rene Rydhof Hansen
37
38 ;;; Utilities
39
40 (defun join-sep (sep xs)
41 (mapconcat 'identity xs sep))
42
43
44 ;;; Variables
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
77 '((((background light)) (:foreground "red"))
78 (((background dark)) (:foreground "SeaGreen3")))
79 "Highlighting lines to be removed")
80
81 (defface cocci-plus-face
82 '((((background light)) (:foreground "dark green"))
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
94 (defconst cocci-c-keywords-list
95 '("if" "else" "while" "do" "for" "return"
96 "sizeof"
97 "struct" "union"
98 "static" "extern" "const" "volatile"
99 "break" "continue"
100 "switch" "case"
101 ))
102
103 (defconst cocci-declaration-keywords-list
104 '("identifier" "type" "parameter" "constant" "expression" "statement"
105 "function" "local" "list"
106 "fresh"
107 "position"
108 "idexpression"
109
110 "context"
111
112 "typedef"
113 "declarer" "iterator"
114 "pure"
115 ;"error" "words"
116
117 "char" "short" "int" "float" "double" "long"
118 "void"
119 "signed" "unsigned"
120 ))
121
122 (defconst cocci-iso-keywords-list
123 '("Expression" "Statement" "Type"
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"
133 "error" "pragma"
134 "file" "line"
135 ))
136
137 (setq cocci-font-lock-keywords
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
154 ("#\\(include\\) *\\(.*\\)"
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
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
171 ; OVERRIDE flag).
172
173 ("\\(@\\)\\(.*\\)\\(@\\)"
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]*@"
184 ; ("\\(@\\)[ \t]*\\(\\w+\\)[ \t]*\\(@\\)"
185 ; ("\\(@\\)[ \t]*\\(\\w+\\)[ \t]+\\(extends\\)[ \t]+\\(\\w+\\)[ \t]*\\(@\\)"
186 ; ("\\(@\\)[ \t]*\\(\\w+\\)[ \t]+\\(depends\\)[ \t]+\\(on\\)[ \t]+\\(\\(\\w+\\)[ ,\t]*\\)+\\(@\\)"
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
195 ;rule1.T *a;
196 ("^\\(\\w+\\)\\."
197 (1 'cocci-rulename-face))
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)
216
217 ; used in iso files
218 ("<=>" . 'font-lock-keyword-face)
219 ("=>" . 'font-lock-keyword-face)
220
221 (,(concat "\\b\\(" (regexp-opt cocci-iso-keywords-list) "\\)\\b") .
222 'cocci-special-face)
223
224 ("\\<[0-9]+\\>" . 'cocci-number-face)
225
226 (,(join-sep "\\|"
227 (list "(" ")" ";" "," "{" "}" "\\[" "\\]")) . 'cocci-punctuation-face)
228 ; . -> * + etc
229
230 ; c keywords
231 (,(concat "\\b\\(" (regexp-opt cocci-c-keywords-list) "\\)\\b") .
232 'font-lock-keyword-face)
233
234 ; cocci declaration keywords
235 (,(concat "\\b\\(" (regexp-opt cocci-declaration-keywords-list) "\\)\\b") .
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
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)
259
260 ;(define-key cocci-mode-map "\C-c" 'compile)
261 )
262
263
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))
268
269 ; _ is part of a word.
270 (modify-syntax-entry ?\_ "w" cocci-mode-syntax-table)
271
272 ; change mode for ", bad interaction with font-lock
273 (modify-syntax-entry ?\" "w" cocci-mode-syntax-table)
274 )
275
276
277 ;;; Code
278
279 ;; helper functions for the cocci programmer
280
281 (defun cocci-replace-modifiers (beg end str)
282 "TODO"
283 (interactive
284 (let ((str (read-string "New modifier string (+, -, space): "
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
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)))
302 (t
303 "none"))))
304 (if (get-buffer target)
305 (switch-to-buffer target)
306 (find-file
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
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.
322 Special commands: \\{cocci-mode-map}
323 Turning 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
346 ;; Menu
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