aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard M. Stallman1994-04-21 18:40:14 +0000
committerRichard M. Stallman1994-04-21 18:40:14 +0000
commit074521be7ec6efd83c943f4339bc14c5dc43de3a (patch)
tree09047238eacc83d84086b4950c30dc9d64bf2740
parent981947af1ad2f7d3e3cc16afd273e73a41fc1ed1 (diff)
downloademacs-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.el176
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.
240Expand the region between START and END in the current buffer using 211Expand the region between START and END in the current buffer using
241the shell command CPPCOMMAND (e.g. \"/lib/cpp -C -DDEBUG\"). 212the shell command CPPCOMMAND (e.g. \"/lib/cpp -C -DDEBUG\").
242Be sure to use a -C (don't strip comments) or equivalent option." 213Be sure to use a -C (don't strip comments) or equivalent option.
214Optional 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))))