diff options
| author | Richard M. Stallman | 1994-04-21 18:40:14 +0000 |
|---|---|---|
| committer | Richard M. Stallman | 1994-04-21 18:40:14 +0000 |
| commit | 074521be7ec6efd83c943f4339bc14c5dc43de3a (patch) | |
| tree | 09047238eacc83d84086b4950c30dc9d64bf2740 | |
| parent | 981947af1ad2f7d3e3cc16afd273e73a41fc1ed1 (diff) | |
| download | emacs-074521be7ec6efd83c943f4339bc14c5dc43de3a.tar.gz emacs-074521be7ec6efd83c943f4339bc14c5dc43de3a.zip | |
(c-macro-expansion): changed the algorithm to allow
__FILE__ and __LINE__ directives to be expanded correctly.
(c-macro-expansion): use a forth optional argument DISPLAY meaning
it should print messages at the start and end of preprocessing.
All callers changed.
(c-macro-expand): Don't display message here.
| -rw-r--r-- | lisp/progmodes/cmacexp.el | 176 |
1 files changed, 79 insertions, 97 deletions
diff --git a/lisp/progmodes/cmacexp.el b/lisp/progmodes/cmacexp.el index 5898cecb16e..76b86e24740 100644 --- a/lisp/progmodes/cmacexp.el +++ b/lisp/progmodes/cmacexp.el | |||
| @@ -3,7 +3,7 @@ | |||
| 3 | ;; Copyright (C) 1992 Free Software Foundation, Inc. | 3 | ;; Copyright (C) 1992 Free Software Foundation, Inc. |
| 4 | 4 | ||
| 5 | ;; Author: Francesco Potorti` <pot@cnuce.cnr.it> | 5 | ;; Author: Francesco Potorti` <pot@cnuce.cnr.it> |
| 6 | ;; Version: $Id: cmacexp.el,v 1.11 1994/04/20 06:12:03 rms Exp rms $ | 6 | ;; Version: $Id: cmacexp.el 1.14 1994/04/20 15:50:48 pot Exp $ |
| 7 | ;; Adapted-By: ESR | 7 | ;; Adapted-By: ESR |
| 8 | ;; Keywords: c | 8 | ;; Keywords: c |
| 9 | 9 | ||
| @@ -25,39 +25,28 @@ | |||
| 25 | 25 | ||
| 26 | ;; USAGE ============================================================= | 26 | ;; USAGE ============================================================= |
| 27 | 27 | ||
| 28 | ;; In C mode C-M-x is bound to c-macro-expand. The result of the | 28 | ;; In C mode C-C C-e is bound to c-macro-expand. The result of the |
| 29 | ;; expansion is put in a separate buffer. The buffer is put in | 29 | ;; expansion is put in a separate buffer. A user option allows the |
| 30 | ;; view-mode if the Inge Frick's view.el is installed. A user option | 30 | ;; window displaying the buffer to be optimally sized. |
| 31 | ;; allows the window displaying the buffer to be optimally sized. | ||
| 32 | ;; | 31 | ;; |
| 33 | ;; When called with a C-u prefix, c-macro-expand replaces the selected | 32 | ;; When called with a C-u prefix, c-macro-expand replaces the selected |
| 34 | ;; region with the expansion. Both the preprocessor name and the | 33 | ;; region with the expansion. Both the preprocessor name and the |
| 35 | ;; initial flag can be set by the user. If c-macro-prompt-p | 34 | ;; initial flag can be set by the user. If c-macro-prompt-flag is set |
| 36 | ;; is set to a non-nil value the user is offered to change the flags | 35 | ;; to a non-nil value the user is offered to change the options to the |
| 37 | ;; to the preprocessor each time c-macro-expand is invoked. | 36 | ;; preprocessor each time c-macro-expand is invoked. Preprocessor |
| 38 | ;; Preprocessor arguments default to the last ones entered. | 37 | ;; arguments default to the last ones entered. If c-macro-prompt-flag |
| 39 | ;; If c-macro-prompt is nil, one must use M-x set-variable to set a | 38 | ;; is nil, one must use M-x set-variable to set a different value for |
| 40 | ;; different value for c-macro-cppflags. | 39 | ;; c-macro-cppflags. |
| 41 | 40 | ||
| 42 | ;; A c-macro-expansion function is provided for non-interactive use. | 41 | ;; A c-macro-expansion function is provided for non-interactive use. |
| 43 | 42 | ||
| 44 | ;; INSTALLATION ====================================================== | 43 | ;; INSTALLATION ====================================================== |
| 45 | 44 | ||
| 46 | ;; Put this file on your load-path, byte compile it for increased | 45 | ;; Put the following in your ~/.emacs file. |
| 47 | ;; speed and put part or all of the following in your ~/.emacs file. | ||
| 48 | 46 | ||
| 49 | ;; To make a directory ~/emacs be in front of your load-path: | ||
| 50 | ;;(setq load-path (cons (expand-file-name "~/emacs") load-path)) | ||
| 51 | ;; | ||
| 52 | ;; Suggested keybinding (work only in c-mode): | ||
| 53 | ;;(if (boundp 'c-mode-map) | ||
| 54 | ;; (define-key c-mode-map "\C-x\C-e" 'c-macro-expand)) | ||
| 55 | ;;(if (boundp 'c++-mode-map) | ||
| 56 | ;; (define-key c++-mode-map "\C-x\C-e" 'c-macro-expand)) | ||
| 57 | ;; | ||
| 58 | ;; If you want the *Macroexpansion* window to be not higher than | 47 | ;; If you want the *Macroexpansion* window to be not higher than |
| 59 | ;; necessary: | 48 | ;; necessary: |
| 60 | ;;(setq c-macro-shrink-window-p t) | 49 | ;;(setq c-macro-shrink-window-flag t) |
| 61 | ;; | 50 | ;; |
| 62 | ;; If you use a preprocessor other than /lib/cpp (be careful to set a | 51 | ;; If you use a preprocessor other than /lib/cpp (be careful to set a |
| 63 | ;; -C option or equivalent in order to make the preprocessor not to | 52 | ;; -C option or equivalent in order to make the preprocessor not to |
| @@ -68,7 +57,7 @@ | |||
| 68 | ;;(setq c-macro-cppflags "-I /usr/include/local -DDEBUG" | 57 | ;;(setq c-macro-cppflags "-I /usr/include/local -DDEBUG" |
| 69 | ;; | 58 | ;; |
| 70 | ;; If you want the "Preprocessor arguments: " prompt: | 59 | ;; If you want the "Preprocessor arguments: " prompt: |
| 71 | ;;(setq c-macro-prompt-p t) | 60 | ;;(setq c-macro-prompt-flag t) |
| 72 | 61 | ||
| 73 | ;; BUG REPORTS ======================================================= | 62 | ;; BUG REPORTS ======================================================= |
| 74 | 63 | ||
| @@ -83,23 +72,12 @@ | |||
| 83 | ;; comment or a region #ifdef'd away by cpp. cpp is invoked with -C, | 72 | ;; comment or a region #ifdef'd away by cpp. cpp is invoked with -C, |
| 84 | ;; making comments visible in the expansion. | 73 | ;; making comments visible in the expansion. |
| 85 | ;; - All work is done in core memory, no need for temporary files. | 74 | ;; - All work is done in core memory, no need for temporary files. |
| 86 | ;; - The /lib/cpp process is run synchronously. This fixes an | ||
| 87 | ;; infinite loop bug on Motorola Delta (cpp waiting forever for | ||
| 88 | ;; end-of-file, don't know why). Fixes a similar intermittent | ||
| 89 | ;; problem on SunOS 4.1. | ||
| 90 | 75 | ||
| 91 | ;; ACKNOWLEDGEMENTS ================================================== | 76 | ;; ACKNOWLEDGEMENTS ================================================== |
| 92 | 77 | ||
| 93 | ;; A lot of thanks to Don Maszle who did a great work of testing, bug | 78 | ;; A lot of thanks to Don Maszle who did a great work of testing, bug |
| 94 | ;; reporting and suggestion of new features and to Inge Fricks for her | 79 | ;; reporting and suggestion of new features. This work has been |
| 95 | ;; help with view.el. This work has been partially inspired by Don | 80 | ;; partially inspired by Don Maszle and Jonathan Segal's. |
| 96 | ;; Maszle and Jonathan Segal's. | ||
| 97 | |||
| 98 | ;; By the way, I recommend you Inge Frick's view.el. It works like | ||
| 99 | ;; the standard view, but *it is not recursive* and has some more | ||
| 100 | ;; commands. Moreover it is a minor mode, so you preserve all your | ||
| 101 | ;; major mode keybindings (well, not always :). Mail me to obtain a | ||
| 102 | ;; copy, or get it by anonymous ftp in fly.cnuce.cnr.it:pub/view.el. | ||
| 103 | 81 | ||
| 104 | ;; BUGS ============================================================== | 82 | ;; BUGS ============================================================== |
| 105 | 83 | ||
| @@ -143,17 +121,12 @@ For use inside Lisp programs, see also `c-macro-expansion'." | |||
| 143 | (displaybuf (if subst | 121 | (displaybuf (if subst |
| 144 | (get-buffer c-macro-buffer-name) | 122 | (get-buffer c-macro-buffer-name) |
| 145 | (get-buffer-create c-macro-buffer-name))) | 123 | (get-buffer-create c-macro-buffer-name))) |
| 146 | (expansion "") | 124 | (expansion "")) |
| 147 | (mymsg "")) | ||
| 148 | ;; Build the command string. | 125 | ;; Build the command string. |
| 149 | (if c-macro-prompt-flag | 126 | (if c-macro-prompt-flag |
| 150 | (setq c-macro-cppflags | 127 | (setq c-macro-cppflags |
| 151 | (read-string "Preprocessor arguments: " | 128 | (read-string "Preprocessor arguments: " |
| 152 | c-macro-cppflags))) | 129 | c-macro-cppflags))) |
| 153 | (setq mymsg (format "Invoking %s%s%s on region..." | ||
| 154 | c-macro-preprocessor | ||
| 155 | (if (string= "" c-macro-cppflags) "" " ") | ||
| 156 | c-macro-cppflags)) | ||
| 157 | ;; Decide where to display output. | 130 | ;; Decide where to display output. |
| 158 | (if (and subst | 131 | (if (and subst |
| 159 | (and buffer-read-only (not inhibit-read-only)) | 132 | (and buffer-read-only (not inhibit-read-only)) |
| @@ -166,11 +139,9 @@ For use inside Lisp programs, see also `c-macro-expansion'." | |||
| 166 | (or displaybuf | 139 | (or displaybuf |
| 167 | (setq displaybuf (get-buffer-create c-macro-buffer-name))))) | 140 | (setq displaybuf (get-buffer-create c-macro-buffer-name))))) |
| 168 | ;; Expand the macro and output it. | 141 | ;; Expand the macro and output it. |
| 169 | (message mymsg) | ||
| 170 | (setq expansion (c-macro-expansion start end | 142 | (setq expansion (c-macro-expansion start end |
| 171 | (concat c-macro-preprocessor " " | 143 | (concat c-macro-preprocessor " " |
| 172 | c-macro-cppflags))) | 144 | c-macro-cppflags) t)) |
| 173 | (message (concat mymsg "done")) | ||
| 174 | (if subst | 145 | (if subst |
| 175 | (let ((exchange (= (point) start))) | 146 | (let ((exchange (= (point) start))) |
| 176 | (delete-region start end) | 147 | (delete-region start end) |
| @@ -235,11 +206,12 @@ For use inside Lisp programs, see also `c-macro-expansion'." | |||
| 235 | (select-window oldwin)))))) | 206 | (select-window oldwin)))))) |
| 236 | 207 | ||
| 237 | 208 | ||
| 238 | (defun c-macro-expansion (start end cppcommand) | 209 | (defun c-macro-expansion (start end cppcommand &optional display) |
| 239 | "Run a preprocessor on region and return the output as a string. | 210 | "Run a preprocessor on region and return the output as a string. |
| 240 | Expand the region between START and END in the current buffer using | 211 | Expand the region between START and END in the current buffer using |
| 241 | the shell command CPPCOMMAND (e.g. \"/lib/cpp -C -DDEBUG\"). | 212 | the shell command CPPCOMMAND (e.g. \"/lib/cpp -C -DDEBUG\"). |
| 242 | Be sure to use a -C (don't strip comments) or equivalent option." | 213 | Be sure to use a -C (don't strip comments) or equivalent option. |
| 214 | Optional arg DISPLAY non-nil means show messages in the echo area." | ||
| 243 | 215 | ||
| 244 | ;; Copy the current buffer's contents to a temporary hidden buffer. | 216 | ;; Copy the current buffer's contents to a temporary hidden buffer. |
| 245 | ;; Delete from END to end of buffer. Insert a preprocessor #line | 217 | ;; Delete from END to end of buffer. Insert a preprocessor #line |
| @@ -259,9 +231,15 @@ Be sure to use a -C (don't strip comments) or equivalent option." | |||
| 259 | buffer-file-name)) | 231 | buffer-file-name)) |
| 260 | (substring buffer-file-name (match-end 0)) | 232 | (substring buffer-file-name (match-end 0)) |
| 261 | (buffer-name))) | 233 | (buffer-name))) |
| 262 | (start-state) | 234 | (mymsg (format "Invoking %s%s%s on region..." |
| 235 | c-macro-preprocessor | ||
| 236 | (if (string= "" c-macro-cppflags) "" " ") | ||
| 237 | c-macro-cppflags)) | ||
| 238 | (uniquestring "???!!!???!!! start of c-macro expansion ???!!!???!!!") | ||
| 239 | (startlinenum 0) | ||
| 263 | (linenum 0) | 240 | (linenum 0) |
| 264 | (linelist ())) | 241 | (startstat ()) |
| 242 | (startmarker "")) | ||
| 265 | (unwind-protect | 243 | (unwind-protect |
| 266 | (save-excursion | 244 | (save-excursion |
| 267 | (save-restriction | 245 | (save-restriction |
| @@ -275,69 +253,73 @@ Be sure to use a -C (don't strip comments) or equivalent option." | |||
| 275 | ;; We have copied inbuf to outbuf. Point is at end of | 253 | ;; We have copied inbuf to outbuf. Point is at end of |
| 276 | ;; outbuf. Insert a space at the end, so cpp can correctly | 254 | ;; outbuf. Insert a space at the end, so cpp can correctly |
| 277 | ;; parse a token ending at END. | 255 | ;; parse a token ending at END. |
| 278 | |||
| 279 | (insert " ") | 256 | (insert " ") |
| 280 | 257 | ||
| 281 | (save-excursion | 258 | ;; Save sexp status and line number at START. |
| 282 | (goto-char start) | 259 | (setq startstat (parse-partial-sexp 1 start)) |
| 283 | (setq start-state (parse-partial-sexp 1 (point)))) | 260 | (setq startlinenum (+ (count-lines 1 (point)) |
| 261 | (if (bolp) 1 0))) | ||
| 262 | |||
| 284 | ;; Now we insert the #line directives after all #endif or | 263 | ;; Now we insert the #line directives after all #endif or |
| 285 | ;; #else following START. | 264 | ;; #else following START going backward, so the lines we |
| 265 | ;; insert don't change the line numbers. | ||
| 286 | ;(switch-to-buffer outbuf) (debug) ;debugging instructions | 266 | ;(switch-to-buffer outbuf) (debug) ;debugging instructions |
| 267 | (goto-char (point-max)) | ||
| 287 | (while (re-search-backward "\n#\\(endif\\|else\\)\\>" start 'move) | 268 | (while (re-search-backward "\n#\\(endif\\|else\\)\\>" start 'move) |
| 288 | (if (equal (nthcdr 3 (parse-partial-sexp start (point) start-state)) | 269 | (if (equal (nthcdr 3 (parse-partial-sexp start (point) |
| 270 | nil nil startstat)) | ||
| 289 | '(nil nil nil 0 nil)) ;neither in string nor in | 271 | '(nil nil nil 0 nil)) ;neither in string nor in |
| 290 | ;comment nor after quote | 272 | ;comment nor after quote |
| 291 | (progn | 273 | (progn |
| 292 | (goto-char (match-end 0)) | 274 | (goto-char (match-end 0)) |
| 293 | ;;; (setq linenum (count-lines 1 (point))) | 275 | (setq linenum (+ startlinenum |
| 294 | (setq linelist | 276 | (count-lines start (point)))) |
| 295 | ;; This used to be a #line command | 277 | (insert (format "\n#line %d \"%s\"\n" linenum filename)) |
| 296 | ;; but it's not guaranteed that the output | 278 | (goto-char (match-beginning 0))))) |
| 297 | ;; will have properly matching commands. | 279 | |
| 298 | ;; Only the *line numbers* have to agree! | 280 | ;; Now we are at START. Insert the first #line directive. |
| 299 | (cons (format "\n???!!!???!!!!\n") | 281 | ;; This must work even inside a string or comment, or after a |
| 300 | linelist)) | ||
| 301 | (insert (car linelist)) | ||
| 302 | (skip-chars-backward "^#") | ||
| 303 | (insert "line") | ||
| 304 | (goto-char (match-beginning 0))))) | ||
| 305 | |||
| 306 | ;; We are at START. Insert the first #line directive. This | ||
| 307 | ;; must work even inside a string or comment, or after a | ||
| 308 | ;; quote. | 282 | ;; quote. |
| 309 | ;;; (setq linenum (+ (count-lines 1 (point)) | 283 | (let* ((startinstring (nth 3 startstat)) |
| 310 | ;;; (if (bolp) 1 0))) | 284 | (startincomment (nth 4 startstat)) |
| 311 | (setq linelist | 285 | (startafterquote (nth 5 startstat)) |
| 312 | (cons | 286 | (startinbcomment (nth 7 startstat))) |
| 313 | (let* ((startstat (parse-partial-sexp 1 start)) | 287 | (insert (if startafterquote " " "") |
| 314 | (startinstring (nth 3 startstat)) | 288 | (cond (startinstring |
| 315 | (startincomment (nth 4 startstat)) | 289 | (char-to-string startinstring)) |
| 316 | (startafterquote (nth 5 startstat)) | 290 | (startincomment "*/") |
| 317 | (startinbcomment (nth 6 startstat))) | 291 | ("")) |
| 318 | (concat (if startafterquote " ") | 292 | (format "\n#line %d \"%s\"\n" startlinenum filename) |
| 319 | (cond (startinstring (char-to-string startinstring)) | 293 | (setq startmarker |
| 320 | (startincomment "*/")) | 294 | (concat uniquestring |
| 321 | (format "\n???!!!???!!!!") | 295 | (cond (startinstring |
| 322 | (cond (startinstring (char-to-string startinstring)) | 296 | (char-to-string startinstring)) |
| 323 | (startincomment "/*") | 297 | (startincomment "/*") |
| 324 | (startinbcomment "//")) | 298 | (startinbcomment "//")) |
| 325 | (if startafterquote "\\"))) | 299 | (if startafterquote "\\"))))) |
| 326 | linelist)) | ||
| 327 | (insert (car linelist)) | ||
| 328 | (skip-chars-backward "^#") | ||
| 329 | (insert "line") | ||
| 330 | 300 | ||
| 331 | ;; Call the preprocessor. | 301 | ;; Call the preprocessor. |
| 302 | (if display (message mymsg)) | ||
| 332 | (call-process-region 1 (point-max) "sh" t t nil "-c" | 303 | (call-process-region 1 (point-max) "sh" t t nil "-c" |
| 333 | (concat cppcommand " 2>/dev/null")) | 304 | (concat cppcommand " 2>/dev/null")) |
| 305 | (if display (message (concat mymsg "done"))) | ||
| 306 | |||
| 307 | ;; Find and delete the mark of the start of the expansion. | ||
| 308 | ;; Look for `# nn "file.c"' lines and delete them. | ||
| 309 | (goto-char (point-min)) | ||
| 310 | (search-forward startmarker) | ||
| 311 | (delete-region 1 (point)) | ||
| 312 | (while (re-search-forward (concat "^# [0-9]+ \"" | ||
| 313 | (regexp-quote filename) | ||
| 314 | "\"") nil t) | ||
| 315 | (beginning-of-line) | ||
| 316 | (let ((beg (point))) | ||
| 317 | (forward-line 1) | ||
| 318 | (delete-region beg (point)))) | ||
| 334 | 319 | ||
| 335 | (while (search-backward "\n???!!!???!!!!" nil t) | ||
| 336 | (replace-match "")) | ||
| 337 | |||
| 338 | ;; Compute the return value, keeping in account the space | 320 | ;; Compute the return value, keeping in account the space |
| 339 | ;; inserted at the end of the buffer. | 321 | ;; inserted at the end of the buffer. |
| 340 | (buffer-substring (point) (max (point) (- (point-max) 1)))) | 322 | (buffer-substring 1 (max 1 (- (point-max) 1)))) |
| 341 | 323 | ||
| 342 | ;; Cleanup. | 324 | ;; Cleanup. |
| 343 | (kill-buffer outbuf)))) | 325 | (kill-buffer outbuf)))) |