* nsterm.m (ns_draw_window_cursor): Draw BAR_CURSOR correct for R2L.
[bpt/emacs.git] / lisp / progmodes / cc-bytecomp.el
CommitLineData
3afbc435 1;;; cc-bytecomp.el --- compile time setup for proper compilation
130c507e 2
114f9c96 3;; Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
d7a0267c 4;; Free Software Foundation, Inc.
130c507e
GM
5
6;; Author: Martin Stjernholm
7;; Maintainer: bug-cc-mode@gnu.org
8;; Created: 15-Jul-2000
9;; Version: See cc-mode.el
10;; Keywords: c languages oop
11
2be7dabc
GM
12;; This file is part of GNU Emacs.
13
b1fc2b50 14;; GNU Emacs is free software: you can redistribute it and/or modify
130c507e 15;; it under the terms of the GNU General Public License as published by
b1fc2b50
GM
16;; the Free Software Foundation, either version 3 of the License, or
17;; (at your option) any later version.
130c507e 18
2be7dabc 19;; GNU Emacs is distributed in the hope that it will be useful,
130c507e
GM
20;; but WITHOUT ANY WARRANTY; without even the implied warranty of
21;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22;; GNU General Public License for more details.
23
24;; You should have received a copy of the GNU General Public License
b1fc2b50 25;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
130c507e
GM
26
27;;; Commentary:
28
29;; This file is used to ensure that the CC Mode files are correctly
30;; compiled regardless the environment (e.g. if an older CC Mode with
31;; outdated macros are loaded during compilation). It also provides
32;; features to defeat the compiler warnings for selected symbols.
a66cd3ee
MS
33;;
34;; There's really nothing CC Mode specific here; this functionality
35;; ought to be provided by the byte compilers or some accompanying
d9e94c22
MS
36;; library. To use it from some package "foo.el", begin by putting
37;; the following blurb at the top of the file:
38;;
39;; (eval-when-compile
40;; (let ((load-path
41;; (if (and (boundp 'byte-compile-dest-file)
42;; (stringp byte-compile-dest-file))
43;; (cons (file-name-directory byte-compile-dest-file) load-path)
44;; load-path)))
45;; (load "cc-bytecomp" nil t))
46;;
47;; This (unfortunately rather clumsy) form will ensure that the
48;; cc-bytecomp.el in the same directory as foo.el is loaded during
49;; byte compilation of the latter.
50;;
51;; At the end of foo.el there should normally be a "(provide 'foo)".
52;; Replace it with "(cc-provide 'foo)"; that is necessary to restore
53;; the environment after the byte compilation. If you don't have a
54;; `provide' at the end, you have to add the following as the very
55;; last form in the file:
56;;
57;; (eval-when-compile (cc-bytecomp-restore-environment))
58;;
59;; Now everything is set to use the various functions and macros in
60;; this package.
61;;
62;; If your package is split into several files, you should use
63;; `cc-require', `cc-require-when-compile' or `cc-load' to load them.
64;; That ensures that the files in the same directory always are
65;; loaded, to avoid mixup with other versions of them that might exist
66;; elsewhere in the load path.
67;;
68;; To suppress byte compiler warnings, use the macros
69;; `cc-bytecomp-defun', `cc-bytecomp-defvar',
70;; `cc-bytecomp-obsolete-fun', and `cc-bytecomp-obsolete-var'.
71;;
72;; This file is not used at all after the package has been byte
73;; compiled. It is however necessary when running uncompiled.
130c507e
GM
74
75\f
3afbc435
PJ
76;;; Code:
77
130c507e
GM
78(defvar cc-bytecomp-unbound-variables nil)
79(defvar cc-bytecomp-original-functions nil)
80(defvar cc-bytecomp-original-properties nil)
130c507e
GM
81(defvar cc-bytecomp-loaded-files nil)
82(defvar cc-bytecomp-environment-set nil)
83
d9e94c22
MS
84(defmacro cc-bytecomp-debug-msg (&rest args)
85 ;;`(message ,@args)
86 )
130c507e
GM
87
88(defun cc-bytecomp-setup-environment ()
89 ;; Eval'ed during compilation to setup variables, functions etc
90 ;; declared with `cc-bytecomp-defvar' et al.
d9e94c22
MS
91 (if (not load-in-progress)
92 ;; Look at `load-in-progress' to tell whether we're called
93 ;; directly in the file being compiled or just from some file
94 ;; being loaded during compilation.
130c507e
GM
95 (let (p)
96 (if cc-bytecomp-environment-set
97 (error "Byte compilation environment already set - \
98perhaps a `cc-bytecomp-restore-environment' is forgotten somewhere"))
99 (setq p cc-bytecomp-unbound-variables)
100 (while p
101 (if (not (boundp (car p)))
102 (progn
103 (eval `(defvar ,(car p)))
d9e94c22
MS
104 (set (car p) (intern (concat "cc-bytecomp-ignore-var:"
105 (symbol-name (car p)))))
106 (cc-bytecomp-debug-msg
107 "cc-bytecomp-setup-environment: Covered variable %s"
108 (car p))))
130c507e
GM
109 (setq p (cdr p)))
110 (setq p cc-bytecomp-original-functions)
111 (while p
112 (let ((fun (car (car p)))
113 (temp-macro (car (cdr (car p)))))
d9e94c22
MS
114 (if (not (fboundp fun))
115 (if temp-macro
116 (progn
117 (eval `(defmacro ,fun ,@temp-macro))
118 (cc-bytecomp-debug-msg
119 "cc-bytecomp-setup-environment: Bound macro %s" fun))
120 (fset fun (intern (concat "cc-bytecomp-ignore-fun:"
121 (symbol-name fun))))
122 (cc-bytecomp-debug-msg
123 "cc-bytecomp-setup-environment: Covered function %s" fun))))
130c507e
GM
124 (setq p (cdr p)))
125 (setq p cc-bytecomp-original-properties)
126 (while p
127 (let ((sym (car (car (car p))))
128 (prop (cdr (car (car p))))
129 (tempdef (car (cdr (car p)))))
d9e94c22
MS
130 (put sym prop tempdef)
131 (cc-bytecomp-debug-msg
132 "cc-bytecomp-setup-environment: Bound property %s for %s to %s"
133 prop sym tempdef))
130c507e 134 (setq p (cdr p)))
d9e94c22
MS
135 (setq cc-bytecomp-environment-set t)
136 (cc-bytecomp-debug-msg
137 "cc-bytecomp-setup-environment: Done"))))
130c507e
GM
138
139(defun cc-bytecomp-restore-environment ()
140 ;; Eval'ed during compilation to restore variables, functions etc
141 ;; declared with `cc-bytecomp-defvar' et al.
d9e94c22 142 (if (not load-in-progress)
130c507e
GM
143 (let (p)
144 (setq p cc-bytecomp-unbound-variables)
145 (while p
146 (let ((var (car p)))
d9e94c22
MS
147 (if (boundp var)
148 (if (eq (intern (concat "cc-bytecomp-ignore-var:"
149 (symbol-name var)))
150 (symbol-value var))
151 (progn
152 (makunbound var)
153 (cc-bytecomp-debug-msg
154 "cc-bytecomp-restore-environment: Unbound variable %s"
155 var))
156 (cc-bytecomp-debug-msg
157 "cc-bytecomp-restore-environment: Not restoring variable %s"
158 var))))
130c507e
GM
159 (setq p (cdr p)))
160 (setq p cc-bytecomp-original-functions)
161 (while p
162 (let ((fun (car (car p)))
d9e94c22 163 (temp-macro (car (cdr (car p))))
130c507e 164 (def (car (cdr (cdr (car p))))))
d9e94c22
MS
165 (if (fboundp fun)
166 (if (eq (or temp-macro
167 (intern (concat "cc-bytecomp-ignore-fun:"
168 (symbol-name fun))))
169 (symbol-function fun))
170 (if (eq def 'unbound)
171 (progn
172 (fmakunbound fun)
173 (cc-bytecomp-debug-msg
174 "cc-bytecomp-restore-environment: Unbound function %s"
175 fun))
176 (fset fun def)
177 (cc-bytecomp-debug-msg
178 "cc-bytecomp-restore-environment: Restored function %s"
179 fun))
180 (cc-bytecomp-debug-msg
181 "cc-bytecomp-restore-environment: Not restoring function %s"
182 fun))))
130c507e
GM
183 (setq p (cdr p)))
184 (setq p cc-bytecomp-original-properties)
185 (while p
186 (let ((sym (car (car (car p))))
187 (prop (cdr (car (car p))))
188 (tempdef (car (cdr (car p))))
189 (origdef (cdr (cdr (car p)))))
190 (if (eq (get sym prop) tempdef)
d9e94c22
MS
191 (progn
192 (put sym prop origdef)
193 (cc-bytecomp-debug-msg
194 "cc-bytecomp-restore-environment: Restored property %s for %s to %s"
195 prop sym origdef))
196 (cc-bytecomp-debug-msg
197 "cc-bytecomp-restore-environment: Not restoring property %s for %s"
198 prop sym)))
130c507e 199 (setq p (cdr p)))
d9e94c22
MS
200 (setq cc-bytecomp-environment-set nil)
201 (cc-bytecomp-debug-msg
202 "cc-bytecomp-restore-environment: Done"))))
203
204(eval
205 ;; This eval is to avoid byte compilation of the function below.
206 ;; There's some bug in XEmacs 21.4.6 that can cause it to dump core
207 ;; here otherwise. My theory is that `cc-bytecomp-load' might be
208 ;; redefined recursively during the `load' inside it, and if it in
209 ;; that case is byte compiled then the byte interpreter gets
210 ;; confused. I haven't succeeded in isolating the bug, though. /mast
211
212 '(defun cc-bytecomp-load (cc-part)
213 ;; Eval'ed during compilation to load a CC Mode file from the source
214 ;; directory (assuming it's the same as the compiled file
215 ;; destination dir).
216 (if (and (boundp 'byte-compile-dest-file)
217 (stringp byte-compile-dest-file))
218 (progn
219 (cc-bytecomp-restore-environment)
220 (let ((load-path
221 (cons (file-name-directory byte-compile-dest-file)
222 load-path))
223 (cc-file (concat cc-part ".el")))
224 (if (member cc-file cc-bytecomp-loaded-files)
225 ()
226 (setq cc-bytecomp-loaded-files
227 (cons cc-file cc-bytecomp-loaded-files))
228 (cc-bytecomp-debug-msg
229 "cc-bytecomp-load: Loading %S" cc-file)
230 (load cc-file nil t t)
231 (cc-bytecomp-debug-msg
232 "cc-bytecomp-load: Loaded %S" cc-file)))
233 (cc-bytecomp-setup-environment)
234 t))))
130c507e
GM
235
236(defmacro cc-require (cc-part)
d9e94c22
MS
237 "Force loading of the corresponding .el file in the current directory
238during compilation, but compile in a `require'. Don't use within
239`eval-when-compile'.
130c507e
GM
240
241Having cyclic cc-require's will result in infinite recursion. That's
242somewhat intentional."
243 `(progn
d9e94c22 244 (eval-when-compile (cc-bytecomp-load (symbol-name ,cc-part)))
130c507e
GM
245 (require ,cc-part)))
246
247(defmacro cc-provide (feature)
248 "A replacement for the `provide' form that restores the environment
249after the compilation. Don't use within `eval-when-compile'."
250 `(progn
251 (eval-when-compile (cc-bytecomp-restore-environment))
252 (provide ,feature)))
253
254(defmacro cc-load (cc-part)
d9e94c22
MS
255 "Force loading of the corresponding .el file in the current directory
256during compilation. Don't use outside `eval-when-compile' or
257`eval-and-compile'.
130c507e
GM
258
259Having cyclic cc-load's will result in infinite recursion. That's
260somewhat intentional."
261 `(or (and (featurep 'cc-bytecomp)
262 (cc-bytecomp-load ,cc-part))
263 (load ,cc-part nil t nil)))
264
d9e94c22
MS
265(defmacro cc-require-when-compile (cc-part)
266 "Force loading of the corresponding .el file in the current directory
267during compilation, but do a compile time `require' otherwise. Don't
268use within `eval-when-compile'."
269 `(eval-when-compile
270 (if (and (featurep 'cc-bytecomp)
271 (cc-bytecomp-is-compiling))
272 (if (or (not load-in-progress)
273 (not (featurep ,cc-part)))
274 (cc-bytecomp-load (symbol-name ,cc-part)))
275 (require ,cc-part))))
276
277(defmacro cc-external-require (feature)
278 "Do a `require' of an external package.
279This restores and sets up the compilation environment before and
280afterwards. Don't use within `eval-when-compile'."
281 `(progn
282 (eval-when-compile (cc-bytecomp-restore-environment))
283 (require ,feature)
284 (eval-when-compile (cc-bytecomp-setup-environment))))
285
130c507e
GM
286(defun cc-bytecomp-is-compiling ()
287 "Return non-nil if eval'ed during compilation. Don't use outside
288`eval-when-compile'."
289 (and (boundp 'byte-compile-dest-file)
290 (stringp byte-compile-dest-file)))
291
292(defmacro cc-bytecomp-defvar (var)
293 "Binds the symbol as a variable during compilation of the file,
294to silence the byte compiler. Don't use within `eval-when-compile'."
295 `(eval-when-compile
296 (if (boundp ',var)
d9e94c22
MS
297 (cc-bytecomp-debug-msg
298 "cc-bytecomp-defvar: %s bound already as variable" ',var)
130c507e 299 (if (not (memq ',var cc-bytecomp-unbound-variables))
d9e94c22
MS
300 (progn
301 (cc-bytecomp-debug-msg
302 "cc-bytecomp-defvar: Saving %s (as unbound)" ',var)
303 (setq cc-bytecomp-unbound-variables
304 (cons ',var cc-bytecomp-unbound-variables))))
130c507e 305 (if (and (cc-bytecomp-is-compiling)
d9e94c22 306 (not load-in-progress))
130c507e
GM
307 (progn
308 (defvar ,var)
d9e94c22
MS
309 (set ',var (intern (concat "cc-bytecomp-ignore-var:"
310 (symbol-name ',var))))
311 (cc-bytecomp-debug-msg
312 "cc-bytecomp-defvar: Covered variable %s" ',var))))))
130c507e
GM
313
314(defmacro cc-bytecomp-defun (fun)
315 "Bind the symbol as a function during compilation of the file,
d9e94c22
MS
316to silence the byte compiler. Don't use within `eval-when-compile'.
317
318If the symbol already is bound as a function, it will keep that
319definition. That means that this macro will not shut up warnings
320about incorrect number of arguments. It's dangerous to try to replace
321existing functions since the byte compiler might need the definition
322at compile time, e.g. for macros and inline functions."
130c507e 323 `(eval-when-compile
6b5bbb98 324 (if (fboundp ',fun)
d9e94c22
MS
325 (cc-bytecomp-debug-msg
326 "cc-bytecomp-defun: %s bound already as function" ',fun)
6b5bbb98 327 (if (not (assq ',fun cc-bytecomp-original-functions))
d9e94c22
MS
328 (progn
329 (cc-bytecomp-debug-msg
330 "cc-bytecomp-defun: Saving %s (as unbound)" ',fun)
331 (setq cc-bytecomp-original-functions
332 (cons (list ',fun nil 'unbound)
333 cc-bytecomp-original-functions))))
6b5bbb98 334 (if (and (cc-bytecomp-is-compiling)
d9e94c22
MS
335 (not load-in-progress))
336 (progn
337 (fset ',fun (intern (concat "cc-bytecomp-ignore-fun:"
338 (symbol-name ',fun))))
339 (cc-bytecomp-debug-msg
340 "cc-bytecomp-defun: Covered function %s" ',fun))))))
130c507e
GM
341
342(put 'cc-bytecomp-defmacro 'lisp-indent-function 'defun)
343(defmacro cc-bytecomp-defmacro (fun &rest temp-macro)
344 "Bind the symbol as a macro during compilation (and evaluation) of the
345file. Don't use outside `eval-when-compile'."
d9e94c22
MS
346 `(let ((orig-fun (assq ',fun cc-bytecomp-original-functions)))
347 (if (not orig-fun)
348 (setq orig-fun
349 (list ',fun
350 nil
351 (if (fboundp ',fun)
352 (progn
353 (cc-bytecomp-debug-msg
354 "cc-bytecomp-defmacro: Saving %s" ',fun)
355 (symbol-function ',fun))
356 (cc-bytecomp-debug-msg
357 "cc-bytecomp-defmacro: Saving %s as unbound" ',fun)
358 'unbound))
359 cc-bytecomp-original-functions
360 (cons orig-fun cc-bytecomp-original-functions)))
361 (defmacro ,fun ,@temp-macro)
362 (cc-bytecomp-debug-msg
363 "cc-bytecomp-defmacro: Bound macro %s" ',fun)
364 (setcar (cdr orig-fun) (symbol-function ',fun))))
130c507e
GM
365
366(defmacro cc-bytecomp-put (symbol propname value)
367 "Set a property on a symbol during compilation (and evaluation) of
368the file. Don't use outside `eval-when-compile'."
d9e94c22 369 `(eval-when-compile
130c507e 370 (if (not (assoc (cons ,symbol ,propname) cc-bytecomp-original-properties))
d9e94c22
MS
371 (progn
372 (cc-bytecomp-debug-msg
373 "cc-bytecomp-put: Saving property %s for %s with value %s"
374 ,propname ,symbol (get ,symbol ,propname))
375 (setq cc-bytecomp-original-properties
376 (cons (cons (cons ,symbol ,propname)
377 (cons ,value (get ,symbol ,propname)))
378 cc-bytecomp-original-properties))))
379 (put ,symbol ,propname ,value)
380 (cc-bytecomp-debug-msg
381 "cc-bytecomp-put: Bound property %s for %s to %s"
382 ,propname ,symbol ,value)))
130c507e
GM
383
384(defmacro cc-bytecomp-obsolete-var (symbol)
d9e94c22 385 "Suppress warnings that the given symbol is an obsolete variable.
130c507e
GM
386Don't use within `eval-when-compile'."
387 `(eval-when-compile
388 (if (get ',symbol 'byte-obsolete-variable)
c0316672
RS
389 (cc-bytecomp-put ',symbol 'byte-obsolete-variable nil)
390 ;; This avoids a superfluous compiler warning
391 ;; about calling `get' for effect.
392 t)))
130c507e
GM
393
394(defun cc-bytecomp-ignore-obsolete (form)
395 ;; Wraps a call to `byte-compile-obsolete' that suppresses the warning.
5e0b2841
GM
396 (let ((byte-compile-warnings byte-compile-warnings))
397 (byte-compile-disable-warning 'obsolete)
130c507e
GM
398 (byte-compile-obsolete form)))
399
400(defmacro cc-bytecomp-obsolete-fun (symbol)
d9e94c22 401 "Suppress warnings that the given symbol is an obsolete function.
130c507e
GM
402Don't use within `eval-when-compile'."
403 `(eval-when-compile
404 (if (eq (get ',symbol 'byte-compile) 'byte-compile-obsolete)
405 (cc-bytecomp-put ',symbol 'byte-compile
d9e94c22
MS
406 'cc-bytecomp-ignore-obsolete)
407 ;; This avoids a superfluous compiler warning
408 ;; about calling `get' for effect.
409 t)))
410
411(defmacro cc-bytecomp-boundp (symbol)
412 "Return non-nil if the given symbol is bound as a variable outside
413the compilation. This is the same as using `boundp' but additionally
414exclude any variables that have been bound during compilation with
415`cc-bytecomp-defvar'."
416 (if (and (cc-bytecomp-is-compiling)
417 (memq (car (cdr symbol)) cc-bytecomp-unbound-variables))
418 nil
419 `(boundp ,symbol)))
420
421(defmacro cc-bytecomp-fboundp (symbol)
422 "Return non-nil if the given symbol is bound as a function outside
423the compilation. This is the same as using `fboundp' but additionally
424exclude any functions that have been bound during compilation with
425`cc-bytecomp-defun'."
426 (let (fun-elem)
427 (if (and (cc-bytecomp-is-compiling)
428 (setq fun-elem (assq (car (cdr symbol))
429 cc-bytecomp-original-functions))
430 (eq (elt fun-elem 2) 'unbound))
431 nil
432 `(fboundp ,symbol))))
130c507e
GM
433
434\f
435(provide 'cc-bytecomp)
3afbc435 436
cbee283d 437;; arch-tag: 2d71b3ad-57b0-4b13-abd3-ab836e08f975
3afbc435 438;;; cc-bytecomp.el ends here