+(defvar c-fix-backslashes t)
+
+(defun c-indent-line (&optional syntax quiet ignore-point-pos)
+ "Indent the current line according to the syntactic context,
+if `c-syntactic-indentation' is non-nil. Optional SYNTAX is the
+syntactic information for the current line. Be silent about syntactic
+errors if the optional argument QUIET is non-nil, even if
+`c-report-syntactic-errors' is non-nil. Normally the position of
+point is used to decide where the old indentation is on a lines that
+is otherwise empty \(ignoring any line continuation backslash), but
+that's not done if IGNORE-POINT-POS is non-nil. Returns the amount of
+indentation change \(in columns)."
+ ;;
+ ;; This function does not do any hidden buffer changes.
+
+ (let ((line-cont-backslash (save-excursion
+ (end-of-line)
+ (eq (char-before) ?\\)))
+ (c-fix-backslashes c-fix-backslashes)
+ bs-col
+ shift-amt)
+ (when (and (not ignore-point-pos)
+ (save-excursion
+ (beginning-of-line)
+ (looking-at (if line-cont-backslash
+ "\\(\\s *\\)\\\\$"
+ "\\(\\s *\\)$")))
+ (<= (point) (match-end 1)))
+ ;; Delete all whitespace after point if there's only whitespace
+ ;; on the line, so that any code that does back-to-indentation
+ ;; or similar gets the current column in this case. If this
+ ;; removes a line continuation backslash it'll be restored
+ ;; at the end.
+ (unless c-auto-align-backslashes
+ ;; Should try to keep the backslash alignment
+ ;; in this case.
+ (save-excursion
+ (goto-char (match-end 0))
+ (setq bs-col (1- (current-column)))))
+ (delete-region (point) (match-end 0))
+ (setq c-fix-backslashes t))
+ (if c-syntactic-indentation
+ (setq c-parsing-error
+ (or (let ((c-parsing-error nil)
+ (c-syntactic-context
+ (or syntax
+ (and (boundp 'c-syntactic-context)
+ c-syntactic-context))))
+ (c-save-buffer-state (indent)
+ (unless c-syntactic-context
+ (setq c-syntactic-context (c-guess-basic-syntax)))
+ (setq indent (c-get-syntactic-indentation
+ c-syntactic-context))
+ (and (not (c-echo-parsing-error quiet))
+ c-echo-syntactic-information-p
+ (message "syntax: %s, indent: %d"
+ c-syntactic-context indent))
+ (setq shift-amt (- indent (current-indentation))))
+ (c-shift-line-indentation shift-amt)
+ (run-hooks 'c-special-indent-hook)
+ c-parsing-error)
+ c-parsing-error))
+ (let ((indent 0))
+ (save-excursion
+ (while (and (= (forward-line -1) 0)
+ (if (looking-at "\\s *\\\\?$")
+ t
+ (setq indent (current-indentation))
+ nil))))
+ (setq shift-amt (- indent (current-indentation)))
+ (c-shift-line-indentation shift-amt)))
+ (when (and c-fix-backslashes line-cont-backslash)
+ (if bs-col
+ (save-excursion
+ (indent-to bs-col)
+ (insert ?\\))
+ (when c-auto-align-backslashes
+ ;; Realign the line continuation backslash.
+ (c-backslash-region (point) (point) nil t))))
+ shift-amt))
+
+(defun c-newline-and-indent (&optional newline-arg)
+ "Inserts a newline and indents the new line.
+This function fixes line continuation backslashes if inside a macro,
+and takes care to set the indentation before calling
+`indent-according-to-mode', so that lineup functions like
+`c-lineup-dont-change' works better."
+ ;;
+ ;; This function does not do any hidden buffer changes.
+
+ ;; TODO: Backslashes before eol in comments and literals aren't
+ ;; kept intact.
+ (let ((c-macro-start (c-query-macro-start))
+ ;; Avoid calling c-backslash-region from c-indent-line if it's
+ ;; called during the newline call, which can happen due to
+ ;; c-electric-continued-statement, for example. We also don't
+ ;; want any backslash alignment from indent-according-to-mode.
+ (c-fix-backslashes nil)
+ has-backslash insert-backslash
+ start col)
+ (save-excursion
+ (beginning-of-line)
+ (setq start (point))
+ (while (and (looking-at "[ \t]*\\\\?$")
+ (= (forward-line -1) 0)))
+ (setq col (current-indentation)))
+ (when c-macro-start
+ (if (and (eolp) (eq (char-before) ?\\))
+ (setq insert-backslash t
+ has-backslash t)
+ (setq has-backslash (eq (char-before (c-point 'eol)) ?\\))))
+ (newline newline-arg)
+ (indent-to col)
+ (when c-macro-start
+ (if insert-backslash
+ (progn
+ ;; The backslash stayed on the previous line. Insert one
+ ;; before calling c-backslash-region, so that
+ ;; bs-col-after-end in it works better. Fixup the
+ ;; backslashes on the newly inserted line.
+ (insert ?\\)
+ (backward-char)
+ (c-backslash-region (point) (point) nil t))
+ ;; The backslash moved to the new line, if there was any. Let
+ ;; c-backslash-region fix a backslash on the previous line,
+ ;; and the one that might be on the new line.
+ ;; c-auto-align-backslashes is intentionally ignored here;
+ ;; maybe the moved backslash should be left alone if it's set,
+ ;; but we fix both lines on the grounds that the old backslash
+ ;; has been moved anyway and is now in a different context.
+ (c-backslash-region start (if has-backslash (point) start) nil t)))
+ (when c-syntactic-indentation
+ ;; Reindent syntactically. The indentation done above is not
+ ;; wasted, since c-indent-line might look at the current
+ ;; indentation.
+ (let ((c-syntactic-context (c-save-buffer-state nil
+ (c-guess-basic-syntax))))
+ ;; We temporarily insert another line break, so that the
+ ;; lineup functions will see the line as empty. That makes
+ ;; e.g. c-lineup-cpp-define more intuitive since it then
+ ;; proceeds to the preceding line in this case.
+ (insert ?\n)
+ (delete-horizontal-space)
+ (setq start (- (point-max) (point)))
+ (unwind-protect
+ (progn
+ (backward-char)
+ (indent-according-to-mode))
+ (goto-char (- (point-max) start))
+ (delete-char -1)))
+ (when has-backslash
+ ;; Must align the backslash again after reindentation. The
+ ;; c-backslash-region call above can't be optimized to ignore
+ ;; this line, since it then won't align correctly with the
+ ;; lines below if the first line in the macro is broken.
+ (c-backslash-region (point) (point) nil t)))))
+
+(defun c-show-syntactic-information (arg)
+ "Show syntactic information for current line.
+With universal argument, inserts the analysis as a comment on that line."
+ (interactive "P")
+ (let* ((c-parsing-error nil)
+ (syntax (if (boundp 'c-syntactic-context)
+ ;; Use `c-syntactic-context' in the same way as
+ ;; `c-indent-line', to be consistent.
+ c-syntactic-context
+ (c-save-buffer-state nil
+ (c-guess-basic-syntax)))))
+ (if (not (consp arg))
+ (message "syntactic analysis: %s" syntax)
+ (indent-for-comment)
+ (insert-and-inherit (format "%s" syntax))
+ ))
+ (c-keep-region-active))
+
+(defun c-syntactic-information-on-region (from to)
+ "Inserts a comment with the syntactic analysis on every line in the region."
+ (interactive "*r")
+ (save-excursion
+ (save-restriction
+ (narrow-to-region from to)
+ (goto-char (point-min))
+ (while (not (eobp))
+ (c-show-syntactic-information '(0))
+ (forward-line)))))
+
+\f
+(defun c-toggle-syntactic-indentation (&optional arg)
+ "Toggle syntactic indentation.
+Optional numeric ARG, if supplied, turns on syntactic indentation when
+positive, turns it off when negative, and just toggles it when zero or
+left out.
+
+When syntactic indentation is turned on (the default), the indentation
+functions and the electric keys indent according to the syntactic
+context keys, when applicable.
+
+When it's turned off, the electric keys does no reindentation, the
+indentation functions indents every new line to the same level as the
+previous nonempty line, and \\[c-indent-command] adjusts the
+indentation in seps specified `c-basic-offset'. The indentation style
+has no effect in this mode, nor any of the indentation associated
+variables, e.g. `c-special-indent-hook'.
+
+This command sets the variable `c-syntactic-indentation'."
+ (interactive "P")
+ (setq c-syntactic-indentation
+ (c-calculate-state arg c-syntactic-indentation))
+ (c-keep-region-active))
+