Commit | Line | Data |
---|---|---|
34e49164 C |
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://www.emn.fr/x-info/coccinelle/ | |
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") |
34e49164 C |
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 | ;; Some cleanups done by Rene Rydhof Hansen | |
36 | ||
37 | ;;; Utilities | |
38 | ||
39 | (defun join-sep (sep xs) | |
40 | (mapconcat 'identity xs sep)) | |
41 | ||
42 | ||
43 | ;;; Variables | |
44 | ||
45 | (defvar cocci-menu) | |
46 | ||
47 | ||
48 | ;; new (color) faces | |
49 | ||
50 | (defface cocci-number-face | |
51 | '((((background light)) (:foreground "black")) | |
52 | (((background dark)) (:foreground "yellow3"))) | |
53 | "Used for Cocci numbers") | |
54 | ||
55 | (defface cocci-punctuation-face | |
56 | '((((background light)) (:foreground "black")) | |
57 | (((background dark)) (:foreground "cyan"))) | |
58 | "Used for punctuation") | |
59 | ||
60 | (defface cocci-problem-face | |
61 | '((((background light)) (:background "deep pink")) | |
62 | (((background dark)) (:background "deep pink"))) | |
63 | "Highlighting potential problems") | |
64 | ||
65 | (defface cocci-special-face | |
66 | '((((background light)) (:foreground "blue")) | |
67 | (((background dark)) (:foreground "red"))) | |
68 | "") | |
69 | ||
70 | (defface cocci-rulename-face | |
71 | '((((background light)) (:foreground "DarkSlateGray")) | |
72 | (((background dark)) (:foreground "DarkSlateGray4"))) | |
73 | "Highlighting the rule names") | |
74 | ||
75 | (defface cocci-minus-face | |
76 | '((((background light)) (:foreground "dark green")) | |
77 | (((background dark)) (:foreground "SeaGreen3"))) | |
78 | "Highlighting lines to be removed") | |
79 | ||
80 | (defface cocci-plus-face | |
81 | '((((background light)) (:foreground "red")) | |
82 | (((background dark)) (:foreground "salmon"))) | |
83 | "Highlighting lines to be added") | |
84 | ||
85 | (defface cocci-match-face | |
86 | '((((background light)) (:foreground "violet red")) | |
87 | (((background dark)) (:foreground "purple"))) | |
88 | "Highlighting lines to be matched (sgrep)") | |
89 | ||
90 | ||
91 | ;; can look in lexer_cocci.mll for new identifiers | |
92 | ||
93 | (defconst cocci-c-keywords-list | |
94 | '("if" "else" "while" "do" "for" "return" | |
95 | "sizeof" | |
96 | "struct" "union" | |
97 | "static" "const" "volatile" | |
98 | "break" "continue" | |
99 | "switch" "case" | |
100 | )) | |
101 | ||
102 | (defconst cocci-declaration-keywords-list | |
103 | '("identifier" "type" "parameter" "constant" "expression" "statement" | |
104 | "function" "local" "list" | |
105 | "fresh" | |
106 | "position" | |
107 | "idexpression" | |
108 | ||
109 | "typedef" | |
110 | "declarer" "iterator" | |
111 | "pure" | |
112 | ;"error" "words" | |
113 | ||
114 | "char" "short" "int" "float" "double" "long" | |
115 | "void" | |
116 | "signed" "unsigned" | |
117 | )) | |
118 | ||
119 | (defconst cocci-iso-keywords-list | |
120 | '("Expression" "Statement" "Type" | |
121 | "Declaration" "TopLevel" "ArgExpression" | |
122 | )) | |
123 | ||
124 | ||
125 | ||
126 | (defconst c-preprocessor-directives-list | |
127 | '("define" "undef" | |
128 | "if" "ifdef" "elif" "else" "endif" "ifndef" | |
129 | "include" | |
130 | "error" "pragma" | |
131 | "file" "line" | |
132 | )) | |
133 | ||
134 | ||
135 | (setq cocci-font-lock-keywords | |
136 | `( | |
137 | ||
138 | ; blink possible errors, when - or + is not in first column | |
139 | ("^[ \t]+[-+]" . 'cocci-problem-face) | |
140 | ||
141 | ; modifiers | |
142 | ("^\\??\\+.*" . 'cocci-plus-face) | |
143 | ("^\\??-.*" . 'cocci-minus-face) | |
144 | ||
145 | ("^\\*.*" . 'cocci-match-face) | |
146 | ;("^\\??\\+.*?//" . 'cocci-plus-face) | |
147 | ; ! \\+ | |
148 | ||
149 | ; --- +++ | |
150 | ||
151 | ; #cpp | |
152 | ("#\\(include\\) *\\(.*\\)" | |
153 | (1 'font-lock-builtin-face) | |
154 | (2 'font-lock-string-face) | |
155 | ) | |
156 | ||
157 | ; comments | |
158 | ("//.*" . 'font-lock-comment-face) | |
159 | ||
160 | ; strings | |
161 | ("\"[^\"]*\"" . 'font-lock-string-face) | |
162 | ||
163 | ; rule header | |
164 | ("@[ \t]*@" . 'cocci-special-face) | |
165 | ; this rule may seems redundant with the following one, but | |
166 | ; without it, @@ int x; @@ would color the int x with rulename-face. | |
167 | ; by using this rule, we color the @@ and so prevent the | |
168 | ; next rule to be applied (cf font-lock semantic when have not the | |
169 | ; OVERRIDE flag). | |
170 | ||
171 | ("\\(@\\)\\(.*\\)\\(@\\)" | |
172 | (1 'cocci-special-face) | |
173 | (2 'cocci-rulename-face) | |
174 | (3 'cocci-special-face) | |
175 | ) | |
176 | ||
177 | ("@.*\\b\\(extends\\|\\(depends[ \t]*on\\)\\)\\b.*@" | |
178 | (1 'cocci-special-face t)) | |
179 | ||
180 | ;old: does not work, not easy to handle the rule1, rule2, rule3 list. | |
181 | ; ("@[ \t]*\\(\\(\\w+\\)[ \t,]*\\)*[ \t]*@" | |
182 | ; ("\\(@\\)[ \t]*\\(\\w+\\)[ \t]*\\(@\\)" | |
183 | ; ("\\(@\\)[ \t]*\\(\\w+\\)[ \t]+\\(extends\\)[ \t]+\\(\\w+\\)[ \t]*\\(@\\)" | |
184 | ; ("\\(@\\)[ \t]*\\(\\w+\\)[ \t]+\\(depends\\)[ \t]+\\(on\\)[ \t]+\\(\\(\\w+\\)[ ,\t]*\\)+\\(@\\)" | |
185 | ||
186 | ||
187 | ; inherited variable, fontifying rulename | |
188 | (,(concat "^" | |
189 | "\\b\\(" (regexp-opt cocci-declaration-keywords-list) "\\)\\b" | |
190 | ".*?\\(\\w+\\)\\.") | |
191 | (2 'cocci-rulename-face)) | |
192 | ||
193 | ;rule1.T *a; | |
194 | ("^\\(\\w+\\)\\." | |
195 | (1 'cocci-rulename-face)) | |
196 | ||
197 | ||
198 | ; just for pad, metavariables in maj | |
199 | ("\\b[A-Z][0-9]?\\b" . font-lock-variable-name-face) | |
200 | ||
201 | ; todo: do also for other variable, do as in font-lock.el | |
202 | ; with font-lock-match-c-style-declaration-item-and-skip-to-next | |
203 | ||
204 | ; special cocci operators | |
205 | ("\\.\\.\\." . 'font-lock-keyword-face) | |
206 | ("^[()|]" . 'font-lock-keyword-face) | |
207 | ||
208 | ; escaped version of cocci operators | |
209 | ("\\\\[()|]" . 'font-lock-keyword-face) | |
210 | ||
211 | ("\\bwhen[ \t]+!=" . '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 | ||
216 | ; used in iso files | |
217 | ("<=>" . 'font-lock-keyword-face) | |
218 | ("=>" . 'font-lock-keyword-face) | |
219 | ||
220 | (,(concat "\\b\\(" (regexp-opt cocci-iso-keywords-list) "\\)\\b") . | |
221 | 'cocci-special-face) | |
222 | ||
223 | ("\\<[0-9]+\\>" . 'cocci-number-face) | |
224 | ||
225 | (,(join-sep "\\|" | |
226 | (list "(" ")" ";" "," "{" "}" "\\[" "\\]")) . 'cocci-punctuation-face) | |
227 | ; . -> * + etc | |
228 | ||
229 | ; c keywords | |
230 | (,(concat "\\b\\(" (regexp-opt cocci-c-keywords-list) "\\)\\b") . | |
231 | 'font-lock-keyword-face) | |
232 | ||
233 | ; cocci declaration keywords | |
234 | (,(concat "\\b\\(" (regexp-opt cocci-declaration-keywords-list) "\\)\\b") . | |
235 | 'font-lock-type-face) | |
236 | ||
237 | ; cpp directives | |
238 | (,(concat "^#[ \t]*\\(" (regexp-opt c-preprocessor-directives-list) | |
239 | "\\)\\>[ \t!]*\\(\\sw+\\)?") | |
240 | (1 'font-lock-builtin-face)) | |
241 | ||
242 | )) | |
243 | ; "Expressions to highlight in cocci-mode.") | |
244 | ||
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 | ||
317 | (defvar cocci-mode-hook nil | |
318 | "Hook called by `cocci-mode'") | |
319 | ||
320 | ;;;###autoload | |
321 | (defun cocci-mode () | |
322 | "Major mode for editing cocci code. | |
323 | Special commands: \\{cocci-mode-map} | |
324 | Turning on cocci-mode runs the hook `cocci-mode-hook'." | |
325 | (interactive) | |
326 | (kill-all-local-variables) | |
327 | (make-local-variable 'font-lock-defaults) | |
328 | (make-local-variable 'comment-start) | |
329 | (make-local-variable 'comment-end) | |
330 | (make-local-variable 'compile-command) | |
331 | ||
332 | (use-local-map cocci-mode-map) | |
333 | (set-syntax-table cocci-mode-syntax-table) | |
334 | (setq mode-name "cocci" | |
335 | major-mode 'cocci-mode | |
336 | local-abbrev-table cocci-mode-abbrev-table | |
337 | font-lock-defaults '(cocci-font-lock-keywords) | |
338 | comment-start "//" | |
339 | comment-end "" | |
340 | ) | |
341 | (easy-menu-add cocci-menu) | |
342 | ||
343 | (run-hooks 'cocci-mode-hook) | |
344 | ) | |
345 | ||
346 | ||
347 | ;; Menu | |
348 | ||
349 | (easy-menu-define cocci-menu cocci-mode-map "Cocci menu" | |
350 | '("Cocci" | |
351 | ["Switch to corresponding C file" switch-between-cocci-c t] | |
352 | ["Replace modifiers" cocci-replace-modifiers t] | |
353 | )) | |
354 | ||
355 | ||
356 | ||
357 | ; put cursor before a parse error coccinelle message and it will | |
358 | ; open the corresponding file and go to corresponding line. | |
359 | (fset 'cocci-goto-next-error | |
360 | [?\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]) | |
361 | ;" | |
362 | ||
363 | ;; Provide | |
364 | (provide 'cocci-mode) | |
365 | ||
366 | ;;; cocci.el ends here |