Function: c-lang-defconst

c-lang-defconst is a macro defined in cc-defs.el.gz.

Signature

(c-lang-defconst NAME &rest ARGS)

Documentation

Set the language specific values of the language constant NAME.

The second argument can optionally be a docstring. The rest of the arguments are one or more repetitions of LANG VAL where LANG specifies the language(s) that VAL applies to. LANG is the name of the language, i.e. the mode name without the "-mode" suffix, or a list of such language names, or t for all languages. VAL is a form to evaluate to get the value.

If LANG isn't t or one of the core languages in CC Mode, it must have been declared with c-add-language.

Neither NAME, LANG nor VAL are evaluated directly - they should not be quoted. c-lang-defconst-eval-immediately can however be used inside VAL to evaluate parts of it directly.

When VAL is evaluated for some language, that language is temporarily made current so that c-lang-const without an explicit language can be used inside VAL to refer to the value of a language constant in the same language. That is particularly useful if LANG is t.

VAL is not evaluated right away but rather when the value is requested with c-lang-const. Thus it's possible to use c-lang-const inside VAL to refer to language constants that haven't been defined yet. However, if the definition of a language constant is in another file then that file must be loaded (at compile time) before it's safe to reference the constant.

The assignments in ARGS are processed in sequence like setq, so
(c-lang-const NAME) may be used inside a VAL to refer to the last
assigned value to this language constant, or a value that it has gotten in another earlier loaded file.

To work well with repeated loads and interactive reevaluation, only one c-lang-defconst for each NAME is permitted per file. If there already is one it will be completely replaced; the value in the earlier definition will not affect c-lang-const on the same constant. A file is identified by its base name.

Source Code

;; Defined in /usr/src/emacs/lisp/progmodes/cc-defs.el.gz
(defmacro c-lang-defconst (name &rest args)
  "Set the language specific values of the language constant NAME.
The second argument can optionally be a docstring.  The rest of the
arguments are one or more repetitions of LANG VAL where LANG specifies
the language(s) that VAL applies to.  LANG is the name of the
language, i.e. the mode name without the \"-mode\" suffix, or a list
of such language names, or t for all languages.  VAL is a form to
evaluate to get the value.

If LANG isn't t or one of the core languages in CC Mode, it must
have been declared with `c-add-language'.

Neither NAME, LANG nor VAL are evaluated directly - they should not be
quoted.  `c-lang-defconst-eval-immediately' can however be used inside
VAL to evaluate parts of it directly.

When VAL is evaluated for some language, that language is temporarily
made current so that `c-lang-const' without an explicit language can
be used inside VAL to refer to the value of a language constant in the
same language.  That is particularly useful if LANG is t.

VAL is not evaluated right away but rather when the value is requested
with `c-lang-const'.  Thus it's possible to use `c-lang-const' inside
VAL to refer to language constants that haven't been defined yet.
However, if the definition of a language constant is in another file
then that file must be loaded (at compile time) before it's safe to
reference the constant.

The assignments in ARGS are processed in sequence like `setq', so
\(c-lang-const NAME) may be used inside a VAL to refer to the last
assigned value to this language constant, or a value that it has
gotten in another earlier loaded file.

To work well with repeated loads and interactive reevaluation, only
one `c-lang-defconst' for each NAME is permitted per file.  If there
already is one it will be completely replaced; the value in the
earlier definition will not affect `c-lang-const' on the same
constant.  A file is identified by its base name."
  (declare (indent 1)
	   (debug (&define name [&optional stringp] [&rest sexp def-form])))
  (let* ((sym (intern (symbol-name name) c-lang-constants))
	 ;; Make `c-lang-const' expand to a straightforward call to
	 ;; `c-get-lang-constant' in `c--macroexpand-all' below.
	 ;;
	 ;; (The default behavior, i.e. to expand to a call inside
	 ;; `eval-when-compile' should be equivalent, since that macro
	 ;; should only expand to its content if it's used inside a
	 ;; form that's already evaluated at compile time.  It's
	 ;; however necessary to use our cover macro
	 ;; `cc-eval-when-compile' due to bugs in `eval-when-compile',
	 ;; and it expands to a bulkier form that in this case only is
	 ;; unnecessary garbage that we don't want to store in the
	 ;; language constant source definitions.)
	 (c-lang-const-expansion 'call)
	 (c-langs-are-parametric t)
	 (file (intern
		(or (c-get-current-file)
		    (error "`c-lang-defconst' can only be used in a file"))))
	 bindings
	 pre-files)

    (or (symbolp name)
	(error "Not a symbol: %S" name))

    (when (stringp (car-safe args))
      ;; The docstring is hardly used anywhere since there's no normal
      ;; symbol to attach it to.  It's primarily for getting the right
      ;; format in the source.
      (put sym 'variable-documentation (car args))
      (setq args (cdr args)))

    (or args
	(error "No assignments in `c-lang-defconst' for %S" name))

    ;; Rework ARGS to an association list to make it easier to handle.
    ;; It's reversed at the same time to make it easier to implement
    ;; the demand-driven (i.e. reversed) evaluation in `c-lang-const'.
    (while args
      (let ((assigned-mode
	     (cond ((eq (car args) t) t)
		   ((symbolp (car args))
		    (list (intern (concat (symbol-name (car args))
					  "-mode"))))
		   ((listp (car args))
		    (mapcar (lambda (lang)
			      (or (symbolp lang)
				  (error "Not a list of symbols: %S"
					 (car args)))
			      (intern (concat (symbol-name lang)
					      "-mode")))
			    (car args)))
		   (t (error "Not a symbol or a list of symbols: %S"
			     (car args)))))
	    val)

	(or (cdr args)
	    (error "No value for %S" (car args)))
	(setq args (cdr args)
	      val (car args))

	;; Emacs has a weird bug where it seems to fail to read
	;; backquote lists from byte compiled files correctly (,@
	;; forms, to be specific), so make sure the bindings in the
	;; expansion below don't contain any backquote stuff.
	;; (XEmacs handles it correctly and doesn't need this for that
	;; reason, but we also use this expansion handle
	;; `c-lang-defconst-eval-immediately' and to register
	;; dependencies on the `c-lang-const's in VAL.)
	(setq val (c--macroexpand-all val))

	(setq bindings `(cons (cons ',assigned-mode (lambda () ,val)) ,bindings)
	      args (cdr args))))

    ;; Compile in the other files that have provided source
    ;; definitions for this symbol, to make sure the order in the
    ;; `source' property is correct even when files are loaded out of
    ;; order.
    (setq pre-files (mapcar 'car (get sym 'source)))
    (if (memq file pre-files)
	;; This can happen when the source file (e.g. cc-langs.el) is first
	;; loaded as source, setting a 'source property entry, and then itself
	;; being compiled.
	(setq pre-files (cdr (memq file pre-files))))
    ;; Reverse to get the right load order.
    (setq pre-files (nreverse pre-files))

    `(eval-and-compile
       (c-define-lang-constant ',name ,bindings
			       ,@(and pre-files `(',pre-files))))))