+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; The following macros are to be used only in `c-parse-state' and its
+;; subroutines. Their main purpose is to simplify the handling of C++/Java
+;; template delimiters and CPP macros. In GNU Emacs, this is done slickly by
+;; the judicious use of 'category properties. These don't exist in XEmacs.
+;;
+;; Note: in the following macros, there is no special handling for parentheses
+;; inside CPP constructs. That is because CPPs are always syntactically
+;; balanced, thanks to `c-neutralize-CPP-line' in cc-mode.el.
+(defmacro c-sc-scan-lists-no-category+1+1 (from)
+ ;; Do a (scan-lists FROM 1 1). Any finishing position which either (i) is
+ ;; determined by and angle bracket; or (ii) is inside a macro whose start
+ ;; isn't POINT-MACRO-START doesn't count as a finishing position.
+ `(let ((here (point))
+ (pos (scan-lists ,from 1 1)))
+ (while (eq (char-before pos) ?>)
+ (setq pos (scan-lists pos 1 1)))
+ pos))
+
+(defmacro c-sc-scan-lists-no-category+1-1 (from)
+ ;; Do a (scan-lists FROM 1 -1). Any finishing position which either (i) is
+ ;; determined by an angle bracket; or (ii) is inside a macro whose start
+ ;; isn't POINT-MACRO-START doesn't count as a finishing position.
+ `(let ((here (point))
+ (pos (scan-lists ,from 1 -1)))
+ (while (eq (char-before pos) ?<)
+ (setq pos (scan-lists pos 1 1))
+ (setq pos (scan-lists pos 1 -1)))
+ pos))
+
+(defmacro c-sc-scan-lists-no-category-1+1 (from)
+ ;; Do a (scan-lists FROM -1 1). Any finishing position which either (i) is
+ ;; determined by and angle bracket; or (ii) is inside a macro whose start
+ ;; isn't POINT-MACRO-START doesn't count as a finishing position.
+ `(let ((here (point))
+ (pos (scan-lists ,from -1 1)))
+ (while (eq (char-after pos) ?<)
+ (setq pos (scan-lists pos -1 1)))
+ pos))
+
+(defmacro c-sc-scan-lists-no-category-1-1 (from)
+ ;; Do a (scan-lists FROM -1 -1). Any finishing position which either (i) is
+ ;; determined by and angle bracket; or (ii) is inside a macro whose start
+ ;; isn't POINT-MACRO-START doesn't count as a finishing position.
+ `(let ((here (point))
+ (pos (scan-lists ,from -1 -1)))
+ (while (eq (char-after pos) ?>)
+ (setq pos (scan-lists pos -1 1))
+ (setq pos (scan-lists pos -1 -1)))
+ pos))
+
+(defmacro c-sc-scan-lists (from count depth)
+ (if c-use-category
+ `(scan-lists ,from ,count ,depth)
+ (cond
+ ((and (eq count 1) (eq depth 1))
+ `(c-sc-scan-lists-no-category+1+1 ,from))
+ ((and (eq count 1) (eq depth -1))
+ `(c-sc-scan-lists-no-category+1-1 ,from))
+ ((and (eq count -1) (eq depth 1))
+ `(c-sc-scan-lists-no-category-1+1 ,from))
+ ((and (eq count -1) (eq depth -1))
+ `(c-sc-scan-lists-no-category-1-1 ,from))
+ (t (error "Invalid parameter(s) to c-sc-scan-lists")))))
+
+
+(defun c-sc-parse-partial-sexp-no-category (from to targetdepth stopbefore
+ oldstate)
+ ;; Do a parse-partial-sexp using the supplied arguments, disregarding
+ ;; template/generic delimiters < > and disregarding macros other than the
+ ;; one at POINT-MACRO-START.
+ ;;
+ ;; NOTE that STOPBEFORE must be nil. TARGETDEPTH should be one less than
+ ;; the depth in OLDSTATE. This function is thus a SPECIAL PURPOSE variation
+ ;; on parse-partial-sexp, designed for calling from
+ ;; `c-remove-stale-state-cache'.
+ ;;
+ ;; Any finishing position which is determined by an angle bracket delimiter
+ ;; doesn't count as a finishing position.
+ ;;
+ ;; Note there is no special handling of CPP constructs here, since these are
+ ;; always syntactically balanced (thanks to `c-neutralize-CPP-line').
+ (let ((state
+ (parse-partial-sexp from to targetdepth stopbefore oldstate)))
+ (while
+ (and (< (point) to)
+ ;; We must have hit targetdepth.
+ (or (eq (char-before) ?<)
+ (eq (char-before) ?>)))
+ (setcar state
+ (if (memq (char-before) '(?> ?\) ?\} ?\]))
+ (1+ (car state))
+ (1- (car state))))
+ (setq state
+ (parse-partial-sexp (point) to targetdepth stopbefore oldstate)))
+ state))
+
+(defmacro c-sc-parse-partial-sexp (from to &optional targetdepth stopbefore
+ oldstate)
+ (if c-use-category
+ `(parse-partial-sexp ,from ,to ,targetdepth ,stopbefore ,oldstate)
+ `(c-sc-parse-partial-sexp-no-category ,from ,to ,targetdepth ,stopbefore
+ ,oldstate)))
+
+\f
+(defvar c-emacs-features)
+
+(defmacro c-looking-at-non-alphnumspace ()
+ "Are we looking at a character which isn't alphanumeric or space?"
+ (if (memq 'gen-comment-delim c-emacs-features)
+ `(looking-at
+"\\([;#]\\|\\'\\|\\s(\\|\\s)\\|\\s\"\\|\\s\\\\|\\s$\\|\\s<\\|\\s>\\|\\s!\\)")
+ `(or (looking-at
+"\\([;#]\\|\\'\\|\\s(\\|\\s)\\|\\s\"\\|\\s\\\\|\\s$\\|\\s<\\|\\s>\\)"
+ (let ((prop (c-get-char-property (point) 'syntax-table)))
+ (eq prop '(14))))))) ; '(14) is generic comment delimiter.
+
+\f