+(defun c-make-bare-char-alt (chars &optional inverted)
+ "Make a character alternative string from the list of characters CHARS.
+The returned string is of the type that can be used with
+`skip-chars-forward' and `skip-chars-backward'. If INVERTED is
+non-nil, a caret is prepended to invert the set."
+ ;; This function ought to be in the elisp core somewhere.
+ (let ((str (if inverted "^" "")) char char2)
+ (setq chars (sort (append chars nil) `<))
+ (while chars
+ (setq char (pop chars))
+ (if (memq char '(?\\ ?^ ?-))
+ ;; Quoting necessary (this method only works in the skip
+ ;; functions).
+ (setq str (format "%s\\%c" str char))
+ (setq str (format "%s%c" str char)))
+ ;; Check for range.
+ (setq char2 char)
+ (while (and chars (>= (1+ char2) (car chars)))
+ (setq char2 (pop chars)))
+ (unless (= char char2)
+ (if (< (1+ char) char2)
+ (setq str (format "%s-%c" str char2))
+ (push char2 chars))))
+ str))
+
+;; Leftovers from (X)Emacs 19 compatibility.
+(defalias 'c-regexp-opt 'regexp-opt)
+(defalias 'c-regexp-opt-depth 'regexp-opt-depth)
+
+\f
+;; Figure out what features this Emacs has
+
+(cc-bytecomp-defvar open-paren-in-column-0-is-defun-start)
+
+(defconst c-emacs-features
+ (let (list)
+
+ (if (boundp 'infodock-version)
+ ;; I've no idea what this actually is, but it's legacy. /mast
+ (setq list (cons 'infodock list)))
+
+ ;; XEmacs uses 8-bit modify-syntax-entry flags.
+ ;; Emacs uses a 1-bit flag. We will have to set up our
+ ;; syntax tables differently to handle this.
+ (let ((table (copy-syntax-table))
+ entry)
+ (modify-syntax-entry ?a ". 12345678" table)
+ (cond
+ ;; Emacs
+ ((arrayp table)
+ (setq entry (aref table ?a))
+ ;; In Emacs, table entries are cons cells
+ (if (consp entry) (setq entry (car entry))))
+ ;; XEmacs
+ ((fboundp 'get-char-table)
+ (setq entry (get-char-table ?a table)))
+ ;; incompatible
+ (t (error "CC Mode is incompatible with this version of Emacs")))
+ (setq list (cons (if (= (logand (lsh entry -16) 255) 255)
+ '8-bit
+ '1-bit)
+ list)))
+
+ (let ((buf (generate-new-buffer " test"))
+ parse-sexp-lookup-properties
+ parse-sexp-ignore-comments
+ lookup-syntax-properties)
+ (save-excursion
+ (set-buffer buf)
+ (set-syntax-table (make-syntax-table))
+
+ ;; For some reason we have to set some of these after the
+ ;; buffer has been made current. (Specifically,
+ ;; `parse-sexp-ignore-comments' in Emacs 21.)
+ (setq parse-sexp-lookup-properties t
+ parse-sexp-ignore-comments t
+ lookup-syntax-properties t)
+
+ ;; Find out if the `syntax-table' text property works.
+ (modify-syntax-entry ?< ".")
+ (modify-syntax-entry ?> ".")
+ (insert "<()>")
+ (c-mark-<-as-paren (point-min))
+ (c-mark->-as-paren (+ 3 (point-min)))
+ (goto-char (point-min))
+ (c-forward-sexp)
+ (if (= (point) (+ 4 (point-min)))
+ (setq list (cons 'syntax-properties list))
+ (error (concat
+ "CC Mode is incompatible with this version of Emacs - "
+ "support for the `syntax-table' text property "
+ "is required.")))
+
+ ;; Find out if generic comment delimiters work.
+ (c-safe
+ (modify-syntax-entry ?x "!")
+ (if (string-match "\\s!" "x")
+ (setq list (cons 'gen-comment-delim list))))
+
+ ;; Find out if generic string delimiters work.
+ (c-safe
+ (modify-syntax-entry ?x "|")
+ (if (string-match "\\s|" "x")
+ (setq list (cons 'gen-string-delim list))))
+
+ ;; See if POSIX char classes work.
+ (when (and (string-match "[[:alpha:]]" "a")
+ ;; All versions of Emacs 21 so far haven't fixed
+ ;; char classes in `skip-chars-forward' and
+ ;; `skip-chars-backward'.
+ (progn
+ (delete-region (point-min) (point-max))
+ (insert "foo123")
+ (skip-chars-backward "[:alnum:]")
+ (bobp))
+ (= (skip-chars-forward "[:alpha:]") 3))
+ (setq list (cons 'posix-char-classes list)))
+
+ ;; See if `open-paren-in-column-0-is-defun-start' exists and
+ ;; isn't buggy (Emacs >= 21.4).
+ (when (boundp 'open-paren-in-column-0-is-defun-start)
+ (let ((open-paren-in-column-0-is-defun-start nil)
+ (parse-sexp-ignore-comments t))
+ (delete-region (point-min) (point-max))
+ (set-syntax-table (make-syntax-table))
+ (modify-syntax-entry ?\' "\"")
+ (cond
+ ;; XEmacs. Afaik this is currently an Emacs-only
+ ;; feature, but it's good to be prepared.
+ ((memq '8-bit list)
+ (modify-syntax-entry ?/ ". 1456")
+ (modify-syntax-entry ?* ". 23"))
+ ;; Emacs
+ ((memq '1-bit list)
+ (modify-syntax-entry ?/ ". 124b")
+ (modify-syntax-entry ?* ". 23")))
+ (modify-syntax-entry ?\n "> b")
+ (insert "/* '\n () */")
+ (backward-sexp)
+ (if (bobp)
+ (setq list (cons 'col-0-paren list)))))
+
+ (set-buffer-modified-p nil))
+ (kill-buffer buf))
+
+ ;; See if `parse-partial-sexp' returns the eighth element.
+ (if (c-safe (>= (length (save-excursion (parse-partial-sexp (point) (point))))
+ 10))
+ (setq list (cons 'pps-extended-state list))
+ (error (concat
+ "CC Mode is incompatible with this version of Emacs - "
+ "`parse-partial-sexp' has to return at least 10 elements.")))
+
+ ;;(message "c-emacs-features: %S" list)
+ list)
+ "A list of certain features in the (X)Emacs you are using.
+There are many flavors of Emacs out there, each with different
+features supporting those needed by CC Mode. The following values
+might be present:
+
+'8-bit 8 bit syntax entry flags (XEmacs style).
+'1-bit 1 bit syntax entry flags (Emacs style).
+'syntax-properties It works to override the syntax for specific characters
+ in the buffer with the 'syntax-table property. It's
+ always set - CC Mode no longer works in emacsen without
+ this feature.
+'gen-comment-delim Generic comment delimiters work
+ (i.e. the syntax class `!').
+'gen-string-delim Generic string delimiters work
+ (i.e. the syntax class `|').
+'pps-extended-state `parse-partial-sexp' returns a list with at least 10
+ elements, i.e. it contains the position of the start of
+ the last comment or string. It's always set - CC Mode
+ no longer works in emacsen without this feature.
+'posix-char-classes The regexp engine understands POSIX character classes.
+'col-0-paren It's possible to turn off the ad-hoc rule that a paren
+ in column zero is the start of a defun.
+'infodock This is Infodock (based on XEmacs).
+
+'8-bit and '1-bit are mutually exclusive.")
+