]> git.donarmstrong.com Git - lib.git/blobdiff - emacs_el/cperl-mode.el
* UPdate debian-unsub template
[lib.git] / emacs_el / cperl-mode.el
index 1cc2f17de50d439b16a76f15bcf75269405b06db..e79528643fe3c93eb4f0a613c927d2eabf5a05bf 100644 (file)
@@ -1,11 +1,11 @@
 ;;; cperl-mode.el --- Perl code editing commands for Emacs
 
 ;; Copyright (C) 1985, 86, 87, 91, 92, 93, 94, 95, 96, 97, 98, 99,
-;;               2000, 2003, 2005
+;;               2000, 2003, 2005, 2006
 ;;     Free Software Foundation, Inc.
 
 ;; Author: Ilya Zakharevich and Bob Olson
-;; Maintainer: Ilya Zakharevich <cperl@ilyaz.org>
+;; Maintainer: Ilya Zakharevich <ilyaz@cpan.org>
 ;; Keywords: languages, Perl
 
 ;; This file is part of GNU Emacs.
 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 ;; Boston, MA 02111-1307, USA.
 
-;;; Corrections made by Ilya Zakharevich cperl@ilyaz.org
+;;; Corrections made by Ilya Zakharevich ilyaz@cpan.org
 ;;; XEmacs changes by Peter Arius arius@informatik.uni-erlangen.de
 
 ;;; Commentary:
 
-;; $Id: cperl-mode.el,v 5.16 2006/02/21 11:18:21 vera Exp vera $
+;; $Id: cperl-mode.el,v 5.23 2007/02/15 11:34:23 vera Exp vera $
 
 ;;; If your Emacs does not default to `cperl-mode' on Perl files:
 ;;; To use this mode put the following into
 ;;; `cperl-unwind-to-safe':    `cperl-beginning-of-property' won't return nil
 ;;; `cperl-syntaxify-for-menu':        New customization variable
 ;;; `cperl-select-this-pod-or-here-doc': New function
-;;; `cperl-get-here-doc-region': Extra argument.
-;;;                            Do not adjust pos by 1.
+;;; `cperl-get-here-doc-region': Extra argument
+;;;                            Do not adjust pos by 1
 
 ;;; New menu entries (Perl/Tools): selection of current POD or HERE-DOC section
 ;;;                            (Debugging CPerl:) backtrace on fontification
 ;;; `cperl-forward-re':                Remove spurious argument SET-ST
 ;;;                            Add documentation
 ;;; `cperl-forward-group-in-re': New function
-;;; `cperl-find-pods-heres':   Find and highlight (?{}) blocks in RExen.
+;;; `cperl-find-pods-heres':   Find and highlight (?{}) blocks in RExen
 ;;;    (XXXX Temporary (?) hack is to syntax-mark them as comment)
 
 ;;; After 5.13:
 ;;; `cperl-string-syntax-table': Make { and } not-grouping
 ;;;   (Sometimes they ARE grouping in RExen, but matching them would only
-;;;    confuse in many situations when they are not).
+;;;    confuse in many situations when they are not)
 ;;; `beginning-of-buffer':     Replaced two occurences with goto-char...
 ;;; `cperl-calculate-indent':  `char-after' could be nil...
 ;;; `cperl-find-pods-heres':   REx can start after "[" too
 ;;; `cperl-maybe-white-and-comment-rex': New constant
 ;;; `cperl-white-and-comment-rex': Likewise
 ;;;                            XXXX Not very efficient, but hard to make
-;;;                            better while keeping 1 group.
+;;;                            better while keeping 1 group
 
 ;;; After 5.13:
 ;;; `cperl-find-pods-heres':   $foo << identifier() is not a HERE-DOC
 ;;;                            Invert highlighting of charclasses: 
 ;;;                                    now the envelop is highlighted
 ;;;                            Highlight many others 0-length builtins
-;;; `cperl-praise':            Mention indenting and highlight in RExen.
+;;; `cperl-praise':            Mention indenting and highlight in RExen
+
+;;; After 5.15:
+;;; `cperl-find-pods-heres':   Highlight capturing parens in REx
+
+;;; After 5.16:
+;;; `cperl-find-pods-heres':   Highlight '|' for alternation
+;;;    Initialize `font-lock-warning-face' if not present
+;;; `cperl-find-pods-heres':   Use `font-lock-warning-face' instead of
+;;;                                     `font-lock-function-name-face'
+;;; `cperl-look-at-leading-count': Likewise
+;;; `cperl-find-pods-heres':   localize `font-lock-variable-name-face'
+;;;                                    `font-lock-keyword-face' (needed for
+;;;                                    batch processing) etc
+;;;                            Use `font-lock-builtin-face' for builtin in REx
+;;;                                    Now `font-lock-variable-name-face'
+;;;                                    is used for interpolated variables
+;;;                            Use "talking aliases" for faces inside REx
+;;;                            Highlight parts of REx (except in charclasses)
+;;;                                    according to the syntax and/or semantic
+;;;                            Syntax-mark a {}-part of (?{}) as "comment"
+;;;                                    (it was the ()-part)
+;;;                            Better logic to distinguish what is what in REx
+;;; `cperl-tips-faces':                Document REx highlighting
+;;; `cperl-praise':            Mention REx syntax highlight etc.
+
+;;; After 5.17:
+;;; `cperl-find-sub-attrs':    Would not always manage to print error message
+;;; `cperl-find-pods-heres':   localize `font-lock-constant-face'
+
+;;; After 5.18:
+;;; `cperl-find-pods-heres':   Misprint in REx for parsing REx
+;;;                            Very minor optimization
+;;;                            `my-cperl-REx-modifiers-face' got quoted
+;;;                            Recognize "print $foo <<END" as HERE-doc
+;;;                            Put `REx-interpolated' text attribute if needed
+;;; `cperl-invert-if-unless-modifiers':        New function
+;;; `cperl-backward-to-start-of-expr': Likewise
+;;; `cperl-forward-to-end-of-expr': Likewise
+;;; `cperl-invert-if-unless':  Works in "the opposite way" too
+;;;                            Cursor position on return is on the switch-word
+;;;                            Indents comments better
+;;; `REx-interpolated':                New text attribute
+;;; `cperl-next-interpolated-REx': New function
+;;; `cperl-next-interpolated-REx-0': Likewise
+;;; `cperl-next-interpolated-REx-1': Likewise
+;;; "\C-c\C-x", "\C-c\C-y", "\C-c\C-v":        New keybinding for these functions
+;;; Perl/Regexp menu:          3 new entries for `cperl-next-interpolated-REx'
+;;; `cperl-praise':            Mention finded interpolated RExen
+
+;;; After 5.19:
+;;; `cperl-init-faces':                Highlight %$foo, @$foo too
+;;; `cperl-short-docs':                Better docs for system, exec
+;;; `cperl-find-pods-heres':   Better detect << after print {FH} <<EOF etc.
+;;;                            Would not find HERE-doc ended by EOF without NL
+;;; `cperl-short-docs':                Correct not-doubled \-escapes
+;;; start block:               Put some `defvar' for stuff gone from XEmacs
+
+;;; After 5.20:
+;;; initial comment:           Extend copyright, fix email address
+;;; `cperl-indent-comment-at-column-0': New customization variable
+;;; `cperl-comment-indent':    Indentation after $#a would increasy by 1
+;;; `cperl-mode':              Make `defun-prompt-regexp' grok BEGIN/END etc
+;;; `cperl-find-pods-heres':   Mark CODE of s///e as `syntax-type' `multiline'
+;;; `cperl-at-end-of-expr':    Would fail if @BAR=12 follows after ";"
+;;; `cperl-init-faces':                If `cperl-highlight-variables-indiscriminately'
+;;;                                    highlight $ in $foo too (UNTESTED)
+;;; `cperl-set-style':         Docstring missed some available styles
+;;; toplevel:                  Menubar/Perl/Indent-Styles had FSF, now K&R
+;;;                            Change "Current" to "Memorize Current"
+;;; `cperl-indent-wrt-brace':  New customization variable; the default is
+;;;                            as for pre-5.2 version
+;;; `cperl-styles-entries':    Keep `cperl-extra-newline-before-brace-multiline'
+;;; `cperl-style-alist':       Likewise
+;;; `cperl-fix-line-spacing':  Support `cperl-merge-trailing-else' being nil,
+;;;                            and `cperl-extra-newline-before-brace' etc
+;;;                            being t
+;;; `cperl-indent-exp':                Plans B and C to find continuation blocks even
+;;;                            if `cperl-extra-newline-before-brace' is t
+
+;;; After 5.21:
+;;; Improve some docstrings concerning indentation.
+;;; `cperl-indent-rules-alist':        New variable
+;;; `cperl-sniff-for-indent':  New function name
+;;                             (separated from `cperl-calculate-indent')
+;;; `cperl-calculate-indent':  Separated the sniffer and the indenter;
+;;;                            uses `cperl-sniff-for-indent' now
+;;; `cperl-comment-indent':    Test for `cperl-indent-comment-at-column-0'
+;;;                            was inverted;
+;;;                            Support `comment-column' = 0
+
+;;; After 5.22:
+;;; `cperl-where-am-i':                Remove function
+;;; `cperl-backward-to-noncomment': Would go too far when skipping POD/HEREs
+;;; `cperl-sniff-for-indent':  [string] and [comment] were inverted
+;;;                            When looking for label, skip s:m:y:tr
+;;; `cperl-indent-line':       Likewise.
+;;; `cperl-mode':              `font-lock-multiline' was assumed auto-local
+;;; `cperl-windowed-init':     Wrong `ps-print' handling
+;;;                             (both thanks to Chong Yidong)
+;;; `cperl-look-at-leading-count': Could fail with unfinished RExen
+;;; `cperl-find-pods-heres':   If the second part of s()[] is missing,
+;;;                                    could try to highlight delimiters...
 
 ;;; Code:
 \f
       (defvar gud-perldb-history)
       (defvar font-lock-background-mode) ; not in Emacs
       (defvar font-lock-display-type)  ; ditto
+      (defvar paren-backwards-message) ; Not in newer XEmacs?
+      (defvar vc-rcs-header)           ; likewise?
+      (defvar vc-sccs-header)          ; likewise?
       (or (fboundp 'defgroup)
          (defmacro defgroup (name val doc &rest arr)
            nil))
@@ -1608,6 +1713,12 @@ This is in addition to cperl-continued-statement-offset."
   :type 'integer
   :group 'cperl-indentation-details)
 
+(defcustom cperl-indent-wrt-brace t
+  "*Non-nil means indent statements in if/etc block relative brace, not if/etc.
+Versions 5.2 ... 5.20 behaved as if this were `nil'."
+  :type 'boolean
+  :group 'cperl-indentation-details)
+
 (defcustom cperl-auto-newline nil
   "*Non-nil means automatically newline before and after braces,
 and after colons and semicolons, inserted in CPerl code.  The following
@@ -1704,6 +1815,11 @@ Affects: `cperl-font-lock', `cperl-electric-lbrace-space',
   :type 'integer
   :group 'cperl-indentation-details)
 
+(defcustom cperl-indent-comment-at-column-0 nil
+  "*Non-nil means that comment started at column 0 should be indentable."
+  :type 'boolean
+  :group 'cperl-indentation-details)
+
 (defcustom cperl-vc-sccs-header '("($sccs) = ('%W\%' =~ /(\\d+(\\.\\d+)+)/) ;")
   "*Special version of `vc-sccs-header' that is used in CPerl mode buffers."
   :type '(repeat string)
@@ -1956,6 +2072,7 @@ This way enabling/disabling of menu items is more correct."
     (font-lock-string-face             nil nil         italic underline)
     (cperl-nonoverridable-face         nil nil         italic underline)
     (font-lock-type-face               nil nil         underline)
+    (font-lock-warning-face            nil "LightGray" bold italic box)
     (underline                         nil "LightGray" strikeout))
   "List given as an argument to `ps-extend-face-list' in `cperl-ps-print'."
   :type '(repeat (cons symbol
@@ -2268,7 +2385,8 @@ voice);
           expressions; can find matching () and [] in a regular expression.
        s) Allows indentation of //x-style regular expressions;
        t) Highlights different symbols in regular expressions according
-          to their function; much less problems with backslashitis.
+          to their function; much less problems with backslashitis;
+       u) Allows to find regular expressions which contain interpolated parts.
 
 5) The indentation engine was very smart, but most of tricks may be
 not needed anymore with the support for `syntax-table' property.  Has
@@ -2286,7 +2404,10 @@ the settings present before the switch.
 line-breaks/spacing between elements of the construct.
 
 10) Uses a linear-time algorith for indentation of regions (on Emaxen with
-capable syntax engines).")
+capable syntax engines).
+
+11) Syntax-highlight, indentation, sexp-recognition inside regular expressions.
+")
 
 (defvar cperl-speed 'please-ignore-this-line
   "This is an incomplete compendium of what is available in other parts
@@ -2341,8 +2462,8 @@ B) Speed of editing operations.
                                syntaxically to be not code
   `font-lock-constant-face'    HERE-doc delimiters, labels, delimiters of
                                2-arg operators s/y/tr/ or of RExen,
-  `font-lock-function-name-face' Special-cased m// and s//foo/, _ as
-                               a target of a file tests, file tests,
+  `font-lock-warning-face'     Special-cased m// and s//foo/,
+  `font-lock-function-name-face' _ as a target of a file tests, file tests,
                                subroutine names at the moment of definition
                                (except those conflicting with Perl operators),
                                package names (when recognized), format names
@@ -2365,7 +2486,25 @@ m// and s/// which do not do what one would expect them to do.
 Help with best setup of these faces for printout requested (for each of
 the faces: please specify bold, italic, underline, shadow and box.)
 
-\(Not finished.)")
+In regular expressions (except character classes):
+  `font-lock-string-face'      \"Normal\" stuff and non-0-length constructs
+  `font-lock-constant-face':   Delimiters
+  `font-lock-warning-face'     Special-cased m// and s//foo/,
+                               Mismatched closing delimiters, parens
+                               we couldn't match, misplaced quantifiers,
+                               unrecognized escape sequences
+  `cperl-nonoverridable-face'  Modifiers, as gism in m/REx/gism
+  `font-lock-type-face'                POSIX classes inside charclasses,
+                               escape sequences with arguments (\x \23 \p \N)
+                               and others match-a-char escape sequences
+  `font-lock-keyword-face'     Capturing parens, and |
+  `font-lock-function-name-face' Special symbols: $ ^ . [ ] [^ ] (?{ }) (??{ })
+  `font-lock-builtin-face'     \"Remaining\" 0-length constructs, executable
+                               parts of a REx, not-capturing parens
+  `font-lock-variable-name-face' Interpolated constructs, embedded code
+  `font-lock-comment-face'     Embedded comments
+
+")
 
 \f
 
@@ -2448,7 +2587,7 @@ the faces: please specify bold, italic, underline, shadow and box.)
 
 (defun cperl-make-indent (column &optional minimum keep)
   "Makes indent of the current line the requested amount.
-If ANEW, removes the old indentation.  Works around a bug in ancient
+Unless KEEP, removes the old indentation.  Works around a bug in ancient
 versions of Emacs."
   (let ((prop (get-text-property (point) 'syntax-type)))
     (or keep
@@ -2521,6 +2660,9 @@ versions of Emacs."
   (cperl-define-key "\C-c\C-p" 'cperl-pod-spell)
   (cperl-define-key "\C-c\C-d" 'cperl-here-doc-spell)
   (cperl-define-key "\C-c\C-n" 'cperl-narrow-to-here-doc)
+  (cperl-define-key "\C-c\C-v" 'cperl-next-interpolated-REx)
+  (cperl-define-key "\C-c\C-x" 'cperl-next-interpolated-REx-0)
+  (cperl-define-key "\C-c\C-y" 'cperl-next-interpolated-REx-1)
   (cperl-define-key "\C-c\C-ha" 'cperl-toggle-autohelp)
   (cperl-define-key "\C-c\C-hp" 'cperl-perldoc)
   (cperl-define-key "\C-c\C-hP" 'cperl-perldoc-at-point)
@@ -2608,7 +2750,17 @@ versions of Emacs."
          ["Contract a group" cperl-contract-level
           cperl-use-syntax-table-text-property]
          ["Contract groups" cperl-contract-levels
-          cperl-use-syntax-table-text-property])
+          cperl-use-syntax-table-text-property]
+         "----"
+         ["Find next interpolated" cperl-next-interpolated-REx 
+          (next-single-property-change (point-min) 'REx-interpolated)]
+         ["Find next interpolated (no //o)"
+          cperl-next-interpolated-REx-0
+          (or (text-property-any (point-min) (point-max) 'REx-interpolated t)
+              (text-property-any (point-min) (point-max) 'REx-interpolated 1))]
+         ["Find next interpolated (neither //o nor whole-REx)"
+          cperl-next-interpolated-REx-1
+          (text-property-any (point-min) (point-max) 'REx-interpolated t)])
         ["Insert spaces if needed to fix style" cperl-find-bad-style t]
         ["Refresh \"hard\" constructions" cperl-find-pods-heres t]
         "----"
@@ -2717,10 +2869,10 @@ versions of Emacs."
          ["PerlStyle" (cperl-set-style "PerlStyle") t]
          ["GNU" (cperl-set-style "GNU") t]
          ["C++" (cperl-set-style "C++") t]
-         ["FSF" (cperl-set-style "FSF") t]
+         ["K&R" (cperl-set-style "K&R") t]
          ["BSD" (cperl-set-style "BSD") t]
          ["Whitesmith" (cperl-set-style "Whitesmith") t]
-         ["Current" (cperl-set-style "Current") t]
+         ["Memorize Current" (cperl-set-style "Current") t]
          ["Memorized" (cperl-set-style-back) cperl-old-style])
         ("Micro-docs"
          ["Tips" (describe-variable 'cperl-tips) t]
@@ -3022,16 +3174,24 @@ Variables controlling indentation style:
  `cperl-min-label-indent'
     Minimal indentation for line that is a label.
 
-Settings for K&R and BSD indentation styles are
-  `cperl-indent-level'                5    8
-  `cperl-continued-statement-offset'  5    8
-  `cperl-brace-offset'               -5   -8
-  `cperl-label-offset'               -5   -8
+Settings for classic indent-styles: K&R BSD=C++ GNU PerlStyle=Whitesmith
+  `cperl-indent-level'                5   4       2   4
+  `cperl-brace-offset'                0   0       0   0
+  `cperl-continued-brace-offset'     -5  -4       0   0
+  `cperl-label-offset'               -5  -4      -2  -4
+  `cperl-continued-statement-offset'  5   4       2   4
 
 CPerl knows several indentation styles, and may bulk set the
 corresponding variables.  Use \\[cperl-set-style] to do this.  Use
 \\[cperl-set-style-back] to restore the memorized preexisting values
-\(both available from menu).
+\(both available from menu).  See examples in `cperl-style-examples'.
+
+Part of the indentation style is how different parts of if/elsif/else
+statements are broken into lines; in CPerl, this is reflected on how
+templates for these constructs are created (controlled by
+`cperl-extra-newline-before-brace'), and how reflow-logic should treat \"continuation\" blocks of else/elsif/continue, controlled by the same variable,
+and by `cperl-extra-newline-before-brace-multiline',
+`cperl-merge-trailing-else', `cperl-indent-region-fix-constructs'.
 
 If `cperl-indent-level' is 0, the statement after opening brace in
 column 0 is indented on
@@ -3123,8 +3283,11 @@ or as help on variables `cperl-tips', `cperl-problems',
 ;;;      (cperl-after-sub-regexp 'named nil) ; 8=name 11=proto 14=attr-start
 ;;;      cperl-maybe-white-and-comment-rex     ; 15=pre-block
   (setq defun-prompt-regexp
-       (concat "[ \t]*sub"
+       (concat "[ \t]*\\(sub"
                (cperl-after-sub-regexp 'named 'attr-groups)
+               "\\|"                   ; per toke.c
+               "\\(BEGIN\\|CHECK\\|INIT\\|END\\|AUTOLOAD\\|DESTROY\\)"
+               "\\)"
                cperl-maybe-white-and-comment-rex))
   (make-local-variable 'comment-indent-function)
   (setq comment-indent-function 'cperl-comment-indent)
@@ -3151,6 +3314,18 @@ or as help on variables `cperl-tips', `cperl-problems',
   (set 'vc-header-alist (or cperl-vc-header-alist ; Avoid warning
                            (` ((SCCS (, (car cperl-vc-sccs-header)))
                                     (RCS (, (car cperl-vc-rcs-header)))))))
+  (cond ((boundp 'compilation-error-regexp-alist-alist);; xemacs 20.x
+        (make-local-variable 'compilation-error-regexp-alist-alist)
+        (set 'compilation-error-regexp-alist-alist
+             (cons (cons 'cperl cperl-compilation-error-regexp-alist)
+                   (symbol-value 'compilation-error-regexp-alist-alist)))
+        (let ((f 'compilation-build-compilation-error-regexp-alist))
+          (funcall f)))
+       ((boundp 'compilation-error-regexp-alist);; xmeacs 19.x
+        (make-local-variable 'compilation-error-regexp-alist)
+        (set 'compilation-error-regexp-alist
+              (cons cperl-compilation-error-regexp-alist
+                    (symbol-value 'compilation-error-regexp-alist)))))
   (make-local-variable 'font-lock-defaults)
   (setq        font-lock-defaults
        (cond
@@ -3193,7 +3368,7 @@ or as help on variables `cperl-tips', `cperl-problems',
   (if (boundp 'font-lock-multiline)    ; Newer font-lock; use its facilities
       (progn
        (setq cperl-font-lock-multiline t) ; Not localized...
-       (set 'font-lock-multiline t)) ; not present with old Emacs; auto-local
+       (set (make-local-variable 'font-lock-multiline) t))
     (make-local-variable 'font-lock-fontify-region-function)
     (set 'font-lock-fontify-region-function ; not present with old Emacs
         'cperl-font-lock-fontify-region-function))
@@ -3276,31 +3451,37 @@ or as help on variables `cperl-tips', `cperl-problems',
 (defvar cperl-st-ket '(5 . ?\<))
 
 
-(defun cperl-comment-indent ()
+(defun cperl-comment-indent ()         ; called at point at supposed comment
   (let ((p (point)) (c (current-column)) was phony)
-    (if (looking-at "^#") 0            ; Existing comment at bol stays there.
+    (if (and (not cperl-indent-comment-at-column-0)
+            (looking-at "^#"))
+       0       ; Existing comment at bol stays there.
       ;; Wrong comment found
       (save-excursion
        (setq was (cperl-to-comment-or-eol)
              phony (eq (get-text-property (point) 'syntax-table)
                        cperl-st-cfence))
        (if phony
-           (progn
+           (progn                      ; Too naive???
              (re-search-forward "#\\|$") ; Hmm, what about embedded #?
              (if (eq (preceding-char) ?\#)
                  (forward-char -1))
              (setq was nil)))
-       (if (= (point) p)
+       (if (= (point) p)               ; Our caller found a correct place
            (progn
              (skip-chars-backward " \t")
-             (max (1+ (current-column)) ; Else indent at comment column
-                  comment-column))
+             (setq was (current-column))
+             (if (eq was 0)
+                 comment-column
+               (max (1+ was) ; Else indent at comment column
+                    comment-column)))
+         ;; No, the caller found a random place; we need to edit ourselves
          (if was nil
            (insert comment-start)
            (backward-char (length comment-start)))
          (setq cperl-wrong-comment t)
-         (cperl-make-indent comment-column 1 'keep)    ; Indent minimum 1
-         c)))))                        ; except leave at least one space.
+         (cperl-make-indent comment-column 1) ; Indent min 1
+         c)))))
 
 ;;;(defun cperl-comment-indent-fallback ()
 ;;;  "Is called if the standard comment-search procedure fails.
@@ -3969,7 +4150,8 @@ Return the amount the indentation changed by."
          (t
           (skip-chars-forward " \t")
           (if (listp indent) (setq indent (car indent)))
-          (cond ((looking-at "[A-Za-z_][A-Za-z_0-9]*:[^:]")
+          (cond ((and (looking-at "[A-Za-z_][A-Za-z_0-9]*:[^:]")
+                      (not (looking-at "[smy]:\\|tr:")))
                  (and (> indent 0)
                       (setq indent (max cperl-min-label-indent
                                         (+ indent cperl-label-offset)))))
@@ -4052,41 +4234,37 @@ Will not look before LIM."
 ;;;           (point-min))))
   )
 
-(defun cperl-calculate-indent (&optional parse-data) ; was parse-start
-  "Return appropriate indentation for current line as Perl code.
-In usual case returns an integer: the column to indent to.
-Returns nil if line starts inside a string, t if in a comment.
-
-Will not correct the indentation for labels, but will correct it for braces
-and closing parentheses and brackets."
+(defun cperl-sniff-for-indent (&optional parse-data) ; was parse-start
+  ;; Old workhorse for calculation of indentation; the major problem
+  ;; is that it mixes the sniffer logic to understand what the current line
+  ;; MEANS with the logic to actually calculate where to indent it.
+  ;; The latter part should be eventually moved to `cperl-calculate-indent';
+  ;; actually, this is mostly done now...
   (cperl-update-syntaxification (point) (point))
-  (save-excursion
-    (if (or
-        (and (memq (get-text-property (point) 'syntax-type)
-                   '(pod here-doc here-doc-delim format))
-             (not (get-text-property (point) 'indentable)))
-        ;; before start of POD - whitespace found since do not have 'pod!
-        (and (looking-at "[ \t]*\n=")
-             (error "Spaces before POD section!"))
-        (and (not cperl-indent-left-aligned-comments)
-             (looking-at "^#")))
-       nil
-      (beginning-of-line)
-      (let* ((indent-point (point))
-            (char-after-pos (save-excursion
-                              (skip-chars-forward " \t")
-                              (point)))
-            (char-after (char-after char-after-pos))
-            (in-pod (get-text-property (point) 'in-pod))
-            (pre-indent-point (point))
-            p prop look-prop is-block delim)
-       (cond
-        (in-pod
-         ;; In the verbatim part, probably code example.  What to do???
-         )
-        (t
-         (save-excursion
-           ;; Not in POD
+  (let ((res (get-text-property (point) 'syntax-type)))
+    (save-excursion
+      (cond
+       ((and (memq res '(pod here-doc here-doc-delim format))
+            (not (get-text-property (point) 'indentable)))
+       (vector res))
+       ;; before start of POD - whitespace found since do not have 'pod!
+       ((looking-at "[ \t]*\n=")
+       (error "Spaces before POD section!"))
+       ((and (not cperl-indent-left-aligned-comments)
+            (looking-at "^#"))
+       [comment-special:at-beginning-of-line])
+       ((get-text-property (point) 'in-pod)
+       [in-pod])
+       (t
+       (beginning-of-line)
+       (let* ((indent-point (point))
+              (char-after-pos (save-excursion
+                                (skip-chars-forward " \t")
+                                (point)))
+              (char-after (char-after char-after-pos))
+              (pre-indent-point (point))
+              p prop look-prop is-block delim)
+         (save-excursion               ; Know we are not in POD, find appropriate pos before
            (cperl-backward-to-noncomment nil)
            (setq p (max (point-min) (1- (point)))
                  prop (get-text-property p 'syntax-type)
@@ -4096,493 +4274,430 @@ and closing parentheses and brackets."
                (progn
                  (goto-char (cperl-beginning-of-property p look-prop))
                  (beginning-of-line)
-                 (setq pre-indent-point (point)))))))
-       (goto-char pre-indent-point)
-       (let* ((case-fold-search nil)
-              (s-s (cperl-get-state (car parse-data) (nth 1 parse-data)))
-              (start (or (nth 2 parse-data)
-                         (nth 0 s-s)))
-              (state (nth 1 s-s))
-              (containing-sexp (car (cdr state)))
-              old-indent)
-         (if (and
-              ;;containing-sexp                ;; We are buggy at toplevel :-(
-              parse-data)
-             (progn
-               (setcar parse-data pre-indent-point)
-               (setcar (cdr parse-data) state)
-               (or (nth 2 parse-data)
-                   (setcar (cddr parse-data) start))
-               ;; Before this point: end of statement
-               (setq old-indent (nth 3 parse-data))))
-         (cond ((get-text-property (point) 'indentable)
-                ;; indent to "after" the surrounding open
-                ;; (same offset as `cperl-beautify-regexp-piece'),
-                ;; skip blanks if we do not close the expression.
-                (setq delim            ; We do not close the expression
-                      (get-text-property
-                       (cperl-1+ char-after-pos) 'indentable)
-                      p (1+ (cperl-beginning-of-property
-                             (point) 'indentable))
-                      is-block         ; misused for: preceeding line in REx
-                      (save-excursion  ; Find preceeding line
-                        (cperl-backward-to-noncomment p)
-                        (beginning-of-line)
-                        (if (<= (point) p)
-                            (progn     ; get indent from the first line
-                              (goto-char p)
-                              (skip-chars-forward " \t")
-                              (if (memq (char-after (point))
-                                        (append "#\n" nil))
-                                  nil  ; Can't use intentation of this line...
-                                (point)))
-                          (skip-chars-forward " \t")
-                          (point)))
-                      prop (parse-partial-sexp p char-after-pos))
-                (cond ((not delim)
-                       (goto-char p)   ; beginning of REx etc
-                       (1- (current-column))) ; End the REx, ignore is-block
-                      (is-block
-                       ;; Indent as the level after closing parens
-                       (goto-char char-after-pos)
-                       (skip-chars-forward " \t)")
-                       (setq char-after-pos (point))
-                       (goto-char is-block)
-                       (skip-chars-forward " \t)")
-                       (setq p (parse-partial-sexp (point) char-after-pos))
-                       (goto-char is-block)
-                       (+ (* (nth 0 p)
-                             (or cperl-regexp-indent-step cperl-indent-level))
-                          (cond ((eq char-after ?\) )
-                                 (- cperl-close-paren-offset)) ; compensate
-                                ((eq char-after ?\| )
-                                 (- (or cperl-regexp-indent-step cperl-indent-level)))
-                                (t 0))
-                          (if (eq (following-char) ?\| )
-                              (or cperl-regexp-indent-step cperl-indent-level)
-                            0)
-                          (current-column)))
-                      ;; Now we have no preceeding line...
-                      (t
-                       (goto-char p)
-                       (+ (or cperl-regexp-indent-step cperl-indent-level)
-                          -1
-                          (current-column)))))
-               ((get-text-property char-after-pos 'REx-part2)
-                (condition-case nil    ; Use indentation of the 1st part
-                    (forward-sexp -1))
-                (current-column))
-               ((or (nth 3 state) (nth 4 state))
-                ;; return nil or t if should not change this line
-                (nth 4 state))
-               ;; XXXX Do we need to special-case this?
-               ((null containing-sexp)
-                ;; Line is at top level.  May be data or function definition,
-                ;; or may be function argument declaration.
-                ;; Indent like the previous top level line
-                ;; unless that ends in a closeparen without semicolon,
-                ;; in which case this line is the first argument decl.
-                (skip-chars-forward " \t")
-                (+ (save-excursion
-                     (goto-char start)
-                     (- (current-indentation)
-                        (if (nth 2 s-s) cperl-indent-level 0)))
-                   (if (eq char-after ?{) cperl-continued-brace-offset 0)
-                   (progn
-                     (cperl-backward-to-noncomment (or old-indent (point-min)))
-                     ;; Look at previous line that's at column 0
-                     ;; to determine whether we are in top-level decls
-                     ;; or function's arg decls.  Set basic-indent accordingly.
-                     ;; Now add a little if this is a continuation line.
-                     (if (or (bobp)
-                             (eq (point) old-indent) ; old-indent was at comment
-                             (eq (preceding-char) ?\;)
-                             ;;  Had ?\) too
-                             (and (eq (preceding-char) ?\})
-                                  (cperl-after-block-and-statement-beg
-                                   (point-min))) ; Was start - too close
-                             (memq char-after (append ")]}" nil))
-                             (and (eq (preceding-char) ?\:) ; label
-                                  (progn
-                                    (forward-sexp -1)
-                                    (skip-chars-backward " \t")
-                                    (looking-at "[ \t]*[a-zA-Z_][a-zA-Z_0-9]*[ \t]*:")))
-                             (get-text-property (point) 'first-format-line))
-                         (progn
-                           (if (and parse-data
-                                    (not (eq char-after ?\C-j)))
-                               (setcdr (cddr parse-data)
-                                       (list pre-indent-point)))
-                           0)
-                       cperl-continued-statement-offset))))
-               ((not
-                 (or (setq is-block
-                           (and (setq delim (= (char-after containing-sexp) ?{))
-                                (save-excursion ; Is it a hash?
-                                  (goto-char containing-sexp)
-                                  (cperl-block-p))))
-                     cperl-indent-parens-as-block))
-                ;; group is an expression, not a block:
-                ;; indent to just after the surrounding open parens,
-                ;; skip blanks if we do not close the expression.
-                (goto-char (1+ containing-sexp))
-                (or (memq char-after
-                          (append (if delim "}" ")]}") nil))
-                    (looking-at "[ \t]*\\(#\\|$\\)")
-                    (skip-chars-forward " \t"))
-                (+ (current-column)
-                   (if (and delim
-                            (eq char-after ?\}))
-                       ;; Correct indentation of trailing ?\}
-                       (+ cperl-indent-level cperl-close-paren-offset)
-                     0)))
-;;;          ((and (/= (char-after containing-sexp) ?{)
-;;;                (not cperl-indent-parens-as-block))
-;;;           ;; line is expression, not statement:
-;;;           ;; indent to just after the surrounding open,
-;;;           ;; skip blanks if we do not close the expression.
-;;;           (goto-char (1+ containing-sexp))
-;;;           (or (memq char-after (append ")]}" nil))
-;;;               (looking-at "[ \t]*\\(#\\|$\\)")
-;;;               (skip-chars-forward " \t"))
-;;;           (current-column))
-;;;          ((progn
-;;;             ;; Containing-expr starts with \{.  Check whether it is a hash.
-;;;             (goto-char containing-sexp)
-;;;             (and (not (cperl-block-p))
-;;;                  (not cperl-indent-parens-as-block)))
-;;;           (goto-char (1+ containing-sexp))
-;;;           (or (eq char-after ?\})
-;;;               (looking-at "[ \t]*\\(#\\|$\\)")
-;;;               (skip-chars-forward " \t"))
-;;;           (+ (current-column)      ; Correct indentation of trailing ?\}
-;;;              (if (eq char-after ?\}) (+ cperl-indent-level
-;;;                                         cperl-close-paren-offset)
-;;;                0)))
-               (t
-                ;; Statement level.  Is it a continuation or a new statement?
-                ;; Find previous non-comment character.
-                (goto-char pre-indent-point)
-                (cperl-backward-to-noncomment containing-sexp)
-                ;; Back up over label lines, since they don't
-                ;; affect whether our line is a continuation.
-                ;; (Had \, too)
-                (while;;(or (eq (preceding-char) ?\,)
-                    (and (eq (preceding-char) ?:)
-                         (or;;(eq (char-after (- (point) 2)) ?\') ; ????
-                          (memq (char-syntax (char-after (- (point) 2)))
-                                '(?w ?_))))
-                  ;;)
-                  (if (eq (preceding-char) ?\,)
-                      ;; Will go to beginning of line, essentially.
-                      ;; Will ignore embedded sexpr XXXX.
-                      (cperl-backward-to-start-of-continued-exp containing-sexp))
-                  (beginning-of-line)
-                  (cperl-backward-to-noncomment containing-sexp))
-                ;; Now we get the answer.
-                (if (not (or (eq (1- (point)) containing-sexp)
-                             (memq (preceding-char)
-                                   (append (if is-block " ;{" " ,;{") '(nil)))
-                             (and (eq (preceding-char) ?\})
-                                  (cperl-after-block-and-statement-beg
-                                   containing-sexp))
-                             (get-text-property (point) 'first-format-line)))
-                    ;; This line is continuation of preceding line's statement;
-                    ;; indent  `cperl-continued-statement-offset'  more than the
-                    ;; previous line of the statement.
-                    ;;
-                    ;; There might be a label on this line, just
-                    ;; consider it bad style and ignore it.
-                    (progn
-                      (cperl-backward-to-start-of-continued-exp containing-sexp)
-                      (+ (if (memq char-after (append "}])" nil))
-                             0         ; Closing parenth
-                           cperl-continued-statement-offset)
-                         (if (or is-block
-                                 (not delim)
-                                 (not (eq char-after ?\})))
-                             0
-                           ;; Now it is a hash reference
-                           (+ cperl-indent-level cperl-close-paren-offset))
-                         ;; Labels do not take :: ...
-                         (if (looking-at "\\(\\w\\|_\\)+[ \t]*:")
-                             (if (> (current-indentation) cperl-min-label-indent)
-                                 (- (current-indentation) cperl-label-offset)
-                               ;; Do not move `parse-data', this should
-                               ;; be quick anyway (this comment comes
-                               ;; from different location):
-                               (cperl-calculate-indent))
-                           (current-column))
-                         (if (eq char-after ?\{)
-                             cperl-continued-brace-offset 0)))
-                  ;; This line starts a new statement.
-                  ;; Position following last unclosed open.
-                  (goto-char containing-sexp)
-                  ;; Is line first statement after an open-brace?
-                  (or
-                   ;; If no, find that first statement and indent like
-                   ;; it.  If the first statement begins with label, do
-                   ;; not believe when the indentation of the label is too
-                   ;; small.
-                   (save-excursion
-                     (forward-char 1)
-                     (setq old-indent (current-indentation))
-                     (let ((colon-line-end 0))
-                       (while
-                           (progn (skip-chars-forward " \t\n")
-                                  (looking-at "#\\|[a-zA-Z0-9_$]*:[^:]\\|=[a-zA-Z]"))
-                         ;; Skip over comments and labels following openbrace.
-                         (cond ((= (following-char) ?\#)
-                                (forward-line 1))
-                               ((= (following-char) ?\=)
-                                (goto-char
-                                 (or (next-single-property-change (point) 'in-pod)
-                                     (point-max)))) ; do not loop if no syntaxification
-                               ;; label:
-                               (t
-                                (save-excursion (end-of-line)
-                                                (setq colon-line-end (point)))
-                                (search-forward ":"))))
-                       ;; The first following code counts
-                       ;; if it is before the line we want to indent.
-                       (and (< (point) indent-point)
-                            (if (> colon-line-end (point)) ; After label
-                                (if (> (current-indentation)
-                                       cperl-min-label-indent)
-                                    (- (current-indentation) cperl-label-offset)
-                                  ;; Do not believe: `max' is involved
-                                  (+ old-indent cperl-indent-level))
-                              (current-column)))))
-                   ;; If no previous statement,
-                   ;; indent it relative to line brace is on.
-                   ;; For open brace in column zero, don't let statement
-                   ;; start there too.  If cperl-indent-level is zero,
-                   ;; use cperl-brace-offset + cperl-continued-statement-offset instead.
-                   ;; For open-braces not the first thing in a line,
-                   ;; add in cperl-brace-imaginary-offset.
-
-                   ;; If first thing on a line:  ?????
-                   (+ (if (and (bolp) (zerop cperl-indent-level))
-                          (+ cperl-brace-offset cperl-continued-statement-offset)
-                        cperl-indent-level)
-                      (if (or is-block
-                              (not delim)
-                              (not (eq char-after ?\})))
-                          0
-                        ;; Now it is a hash reference
-                        (+ cperl-indent-level cperl-close-paren-offset))
-                      ;; Move back over whitespace before the openbrace.
-                      ;; If openbrace is not first nonwhite thing on the line,
-                      ;; add the cperl-brace-imaginary-offset.
-                      (progn (skip-chars-backward " \t")
-                             (if (bolp) 0 cperl-brace-imaginary-offset))
-                      ;; If the openbrace is preceded by a parenthesized exp,
-                      ;; move to the beginning of that;
-                      ;; possibly a different line
+                 (setq pre-indent-point (point)))))
+         (goto-char pre-indent-point)  ; Orig line skipping preceeding pod/etc
+         (let* ((case-fold-search nil)
+                (s-s (cperl-get-state (car parse-data) (nth 1 parse-data)))
+                (start (or (nth 2 parse-data) ; last complete sexp terminated
+                           (nth 0 s-s))) ; Good place to start parsing
+                (state (nth 1 s-s))
+                (containing-sexp (car (cdr state)))
+                old-indent)
+           (if (and
+                ;;containing-sexp              ;; We are buggy at toplevel :-(
+                parse-data)
+               (progn
+                 (setcar parse-data pre-indent-point)
+                 (setcar (cdr parse-data) state)
+                 (or (nth 2 parse-data)
+                     (setcar (cddr parse-data) start))
+                 ;; Before this point: end of statement
+                 (setq old-indent (nth 3 parse-data))))
+           (cond ((get-text-property (point) 'indentable)
+                  ;; indent to "after" the surrounding open
+                  ;; (same offset as `cperl-beautify-regexp-piece'),
+                  ;; skip blanks if we do not close the expression.
+                  (setq delim          ; We do not close the expression
+                        (get-text-property
+                         (cperl-1+ char-after-pos) 'indentable)
+                        p (1+ (cperl-beginning-of-property
+                               (point) 'indentable))
+                        is-block       ; misused for: preceeding line in REx
+                        (save-excursion ; Find preceeding line
+                          (cperl-backward-to-noncomment p)
+                          (beginning-of-line)
+                          (if (<= (point) p)
+                              (progn   ; get indent from the first line
+                                (goto-char p)
+                                (skip-chars-forward " \t")
+                                (if (memq (char-after (point))
+                                          (append "#\n" nil))
+                                    nil ; Can't use intentation of this line...
+                                  (point)))
+                            (skip-chars-forward " \t")
+                            (point)))
+                        prop (parse-partial-sexp p char-after-pos))
+                  (cond ((not delim)   ; End the REx, ignore is-block
+                         (vector 'indentable 'terminator p is-block))
+                        (is-block      ; Indent w.r.t. preceeding line
+                         (vector 'indentable 'cont-line char-after-pos
+                                 is-block char-after p))
+                        (t             ; No preceeding line...
+                         (vector 'indentable 'first-line p))))
+                 ((get-text-property char-after-pos 'REx-part2)
+                  (vector 'REx-part2 (point)))
+                 ((nth 4 state)
+                  [comment])
+                 ((nth 3 state)
+                  [string])
+                 ;; XXXX Do we need to special-case this?
+                 ((null containing-sexp)
+                  ;; Line is at top level.  May be data or function definition,
+                  ;; or may be function argument declaration.
+                  ;; Indent like the previous top level line
+                  ;; unless that ends in a closeparen without semicolon,
+                  ;; in which case this line is the first argument decl.
+                  (skip-chars-forward " \t")
+                  (cperl-backward-to-noncomment (or old-indent (point-min)))
+                  (setq state
+                        (or (bobp)
+                            (eq (point) old-indent) ; old-indent was at comment
+                            (eq (preceding-char) ?\;)
+                            ;;  Had ?\) too
+                            (and (eq (preceding-char) ?\})
+                                 (cperl-after-block-and-statement-beg
+                                  (point-min))) ; Was start - too close
+                            (memq char-after (append ")]}" nil))
+                            (and (eq (preceding-char) ?\:) ; label
+                                 (progn
+                                   (forward-sexp -1)
+                                   (skip-chars-backward " \t")
+                                   (looking-at "[ \t]*[a-zA-Z_][a-zA-Z_0-9]*[ \t]*:")))
+                            (get-text-property (point) 'first-format-line)))
+                  
+                  ;; Look at previous line that's at column 0
+                  ;; to determine whether we are in top-level decls
+                  ;; or function's arg decls.  Set basic-indent accordingly.
+                  ;; Now add a little if this is a continuation line.
+                  (and state
+                       parse-data
+                       (not (eq char-after ?\C-j))
+                       (setcdr (cddr parse-data)
+                               (list pre-indent-point)))
+                  (vector 'toplevel start char-after state (nth 2 s-s)))
+                 ((not
+                   (or (setq is-block
+                             (and (setq delim (= (char-after containing-sexp) ?{))
+                                  (save-excursion ; Is it a hash?
+                                    (goto-char containing-sexp)
+                                    (cperl-block-p))))
+                       cperl-indent-parens-as-block))
+                  ;; group is an expression, not a block:
+                  ;; indent to just after the surrounding open parens,
+                  ;; skip blanks if we do not close the expression.
+                  (goto-char (1+ containing-sexp))
+                  (or (memq char-after
+                            (append (if delim "}" ")]}") nil))
+                      (looking-at "[ \t]*\\(#\\|$\\)")
+                      (skip-chars-forward " \t"))
+                  (setq old-indent (point)) ; delim=is-brace
+                  (vector 'in-parens char-after (point) delim containing-sexp))
+                 (t
+                  ;; Statement level.  Is it a continuation or a new statement?
+                  ;; Find previous non-comment character.
+                  (goto-char pre-indent-point) ; Skip one level of POD/etc
+                  (cperl-backward-to-noncomment containing-sexp)
+                  ;; Back up over label lines, since they don't
+                  ;; affect whether our line is a continuation.
+                  ;; (Had \, too)
+                  (while;;(or (eq (preceding-char) ?\,)
+                      (and (eq (preceding-char) ?:)
+                           (or;;(eq (char-after (- (point) 2)) ?\') ; ????
+                            (memq (char-syntax (char-after (- (point) 2)))
+                                  '(?w ?_))))
+                    ;;)
+                    ;; This is always FALSE?
+                    (if (eq (preceding-char) ?\,)
+                        ;; Will go to beginning of line, essentially.
+                        ;; Will ignore embedded sexpr XXXX.
+                        (cperl-backward-to-start-of-continued-exp containing-sexp))
+                    (beginning-of-line)
+                    (cperl-backward-to-noncomment containing-sexp))
+                  ;; Now we get non-label preceeding the indent point
+                  (if (not (or (eq (1- (point)) containing-sexp)
+                               (memq (preceding-char)
+                                     (append (if is-block " ;{" " ,;{") '(nil)))
+                               (and (eq (preceding-char) ?\})
+                                    (cperl-after-block-and-statement-beg
+                                     containing-sexp))
+                               (get-text-property (point) 'first-format-line)))
+                      ;; This line is continuation of preceding line's statement;
+                      ;; indent  `cperl-continued-statement-offset'  more than the
+                      ;; previous line of the statement.
+                      ;;
+                      ;; There might be a label on this line, just
+                      ;; consider it bad style and ignore it.
                       (progn
-                        (cperl-backward-to-noncomment (point-min))
-                        (if (eq (preceding-char) ?\))
-                            (forward-sexp -1))
-                        ;; In the case it starts a subroutine, indent with
-                        ;; respect to `sub', not with respect to the
-                        ;; first thing on the line, say in the case of
-                        ;; anonymous sub in a hash.
-                        ;;
-                        ;;(skip-chars-backward " \t")
-                        (cperl-backward-to-noncomment (point-min))
-                        (if (and
-                             (or
-                              (and (get-text-property (point) 'attrib-group)
-                                   (goto-char
-                                    (cperl-beginning-of-property
-                                     (point) 'attrib-group)))
-                              (and (eq (preceding-char) ?b)
-                                   (progn
-                                     (forward-sexp -1)
-                                     (looking-at "sub\\>"))))
-                             (setq old-indent
-                                   (nth 1
-                                        (parse-partial-sexp
-                                         (save-excursion (beginning-of-line) (point))
-                                         (point)))))
-                            (progn (goto-char (1+ old-indent))
-                                   (skip-chars-forward " \t")
-                                   (current-column))
-                          ;; Get initial indentation of the line we are on.
-                          ;; If line starts with label, calculate label indentation
-                          (if (save-excursion
-                                (beginning-of-line)
-                                (looking-at "[ \t]*[a-zA-Z_][a-zA-Z_0-9]*:[^:]"))
-                              (if (> (current-indentation) cperl-min-label-indent)
-                                  (- (current-indentation) cperl-label-offset)
-                                ;; Do not move `parse-data', this should
-                                ;; be quick anyway:
-                                (cperl-calculate-indent))
-                            (current-indentation))))))))))))))
-
-(defvar cperl-indent-alist
-  '((string nil)
-    (comment nil)
-    (toplevel 0)
-    (toplevel-after-parenth 2)
-    (toplevel-continued 2)
-    (expression 1))
+                        (cperl-backward-to-start-of-continued-exp containing-sexp)
+                        (vector 'continuation (point) char-after is-block delim))
+                    ;; This line starts a new statement.
+                    ;; Position following last unclosed open brace
+                    (goto-char containing-sexp)
+                    ;; Is line first statement after an open-brace?
+                    (or
+                     ;; If no, find that first statement and indent like
+                     ;; it.  If the first statement begins with label, do
+                     ;; not believe when the indentation of the label is too
+                     ;; small.
+                     (save-excursion
+                       (forward-char 1)
+                       (let ((colon-line-end 0))
+                         (while
+                             (progn (skip-chars-forward " \t\n")
+                                    ;; s: foo : bar :x is NOT label
+                                    (and (looking-at "#\\|\\([a-zA-Z0-9_$]+\\):[^:]\\|=[a-zA-Z]")
+                                         (not (looking-at "[sym]:\\|tr:"))))
+                           ;; Skip over comments and labels following openbrace.
+                           (cond ((= (following-char) ?\#)
+                                  (forward-line 1))
+                                 ((= (following-char) ?\=)
+                                  (goto-char
+                                   (or (next-single-property-change (point) 'in-pod)
+                                       (point-max)))) ; do not loop if no syntaxification
+                                 ;; label:
+                                 (t
+                                  (save-excursion (end-of-line)
+                                                  (setq colon-line-end (point)))
+                                  (search-forward ":"))))
+                         ;; We are at beginning of code (NOT label or comment)
+                         ;; First, the following code counts
+                         ;; if it is before the line we want to indent.
+                         (and (< (point) indent-point)
+                              (vector 'have-prev-sibling (point) colon-line-end
+                                      containing-sexp))))
+                     (progn
+                       ;; If no previous statement,
+                       ;; indent it relative to line brace is on.
+
+                       ;; For open-braces not the first thing in a line,
+                       ;; add in cperl-brace-imaginary-offset.
+
+                       ;; If first thing on a line:  ?????
+                       ;; Move back over whitespace before the openbrace.
+                       (setq           ; brace first thing on a line
+                        old-indent (progn (skip-chars-backward " \t") (bolp)))
+                       ;; Should we indent w.r.t. earlier than start?
+                       ;; Move to start of control group, possibly on a different line
+                       (or cperl-indent-wrt-brace
+                           (cperl-backward-to-noncomment (point-min)))
+                       ;; If the openbrace is preceded by a parenthesized exp,
+                       ;; move to the beginning of that;
+                       (if (eq (preceding-char) ?\))
+                           (progn
+                             (forward-sexp -1)
+                             (cperl-backward-to-noncomment (point-min))))
+                       ;; In the case it starts a subroutine, indent with
+                       ;; respect to `sub', not with respect to the
+                       ;; first thing on the line, say in the case of
+                       ;; anonymous sub in a hash.
+                       (if (and;; Is it a sub in group starting on this line?
+                            (cond ((get-text-property (point) 'attrib-group)
+                                   (goto-char (cperl-beginning-of-property
+                                               (point) 'attrib-group)))
+                                  ((eq (preceding-char) ?b)
+                                   (forward-sexp -1)
+                                   (looking-at "sub\\>")))
+                            (setq p (nth 1 ; start of innermost containing list
+                                         (parse-partial-sexp
+                                          (save-excursion (beginning-of-line)
+                                                          (point))
+                                          (point)))))
+                           (progn
+                             (goto-char (1+ p)) ; enclosing block on the same line
+                             (skip-chars-forward " \t")
+                             (vector 'code-start-in-block containing-sexp char-after
+                                     (and delim (not is-block)) ; is a HASH
+                                     old-indent ; brace first thing on a line
+                                     t (point) ; have something before...
+                                     )
+                             ;;(current-column)
+                             )
+                         ;; Get initial indentation of the line we are on.
+                         ;; If line starts with label, calculate label indentation
+                         (vector 'code-start-in-block containing-sexp char-after
+                                 (and delim (not is-block)) ; is a HASH
+                                 old-indent ; brace first thing on a line
+                                 nil (point))))))))))))))) ; nothing interesting before
+
+(defvar cperl-indent-rules-alist
+  '((pod nil)                          ; via `syntax-type' property
+    (here-doc nil)                     ; via `syntax-type' property
+    (here-doc-delim nil)               ; via `syntax-type' property
+    (format nil)                       ; via `syntax-type' property
+    (in-pod nil)                       ; via `in-pod' property
+    (comment-special:at-beginning-of-line nil)
+    (string t)
+    (comment nil))
   "Alist of indentation rules for CPerl mode.
 The values mean:
   nil: do not indent;
-  number: add this amount of indentation.
-
-Not finished, not used.")
+  number: add this amount of indentation.")
 
-(defun cperl-where-am-i (&optional parse-start start-state)
-  ;; Unfinished
-  "Return a list of lists ((TYPE POS)...) of good points before the point.
-POS may be nil if it is hard to find, say, when TYPE is `string' or `comment'.
+(defun cperl-calculate-indent (&optional parse-data) ; was parse-start
+  "Return appropriate indentation for current line as Perl code.
+In usual case returns an integer: the column to indent to.
+Returns nil if line starts inside a string, t if in a comment.
 
-Not finished, not used."
+Will not correct the indentation for labels, but will correct it for braces
+and closing parentheses and brackets."
+  ;; This code is still a broken architecture: in some cases we need to
+  ;; compensate for some modifications which `cperl-indent-line' will add later
   (save-excursion
-    (let* ((start-point (point)) unused
-          (s-s (cperl-get-state))
-          (start (nth 0 s-s))
-          (state (nth 1 s-s))
-          (prestart (nth 3 s-s))
-          (containing-sexp (car (cdr state)))
-          (case-fold-search nil)
-          (res (list (list 'parse-start start) (list 'parse-prestart prestart))))
-      (cond ((nth 3 state)             ; In string
-            (setq res (cons (list 'string nil (nth 3 state)) res))) ; What started string
-           ((nth 4 state)              ; In comment
-            (setq res (cons '(comment) res)))
-           ((null containing-sexp)
-            ;; Line is at top level.
-            ;; Indent like the previous top level line
-            ;; unless that ends in a closeparen without semicolon,
-            ;; in which case this line is the first argument decl.
-            (cperl-backward-to-noncomment (or parse-start (point-min)))
-            ;;(skip-chars-backward " \t\f\n")
-            (cond
-             ((or (bobp)
-                  (memq (preceding-char) (append ";}" nil)))
-              (setq res (cons (list 'toplevel start) res)))
-             ((eq (preceding-char) ?\) )
-              (setq res (cons (list 'toplevel-after-parenth start) res)))
-             (t
-              (setq res (cons (list 'toplevel-continued start) res)))))
-           ((/= (char-after containing-sexp) ?{)
-            ;; line is expression, not statement:
-            ;; indent to just after the surrounding open.
-            ;; skip blanks if we do not close the expression.
-            (setq res (cons (list 'expression-blanks
-                                  (progn
-                                    (goto-char (1+ containing-sexp))
-                                    (or (looking-at "[ \t]*\\(#\\|$\\)")
-                                        (skip-chars-forward " \t"))
-                                    (point)))
-                            (cons (list 'expression containing-sexp) res))))
-           ((progn
-              ;; Containing-expr starts with \{.  Check whether it is a hash.
-              (goto-char containing-sexp)
-              (not (cperl-block-p)))
-            (setq res (cons (list 'expression-blanks
-                                  (progn
-                                    (goto-char (1+ containing-sexp))
-                                    (or (looking-at "[ \t]*\\(#\\|$\\)")
-                                        (skip-chars-forward " \t"))
-                                    (point)))
-                            (cons (list 'expression containing-sexp) res))))
-           (t
-            ;; Statement level.
-            (setq res (cons (list 'in-block containing-sexp) res))
-            ;; Is it a continuation or a new statement?
-            ;; Find previous non-comment character.
-            (cperl-backward-to-noncomment containing-sexp)
-            ;; Back up over label lines, since they don't
-            ;; affect whether our line is a continuation.
-            ;; Back up comma-delimited lines too ?????
-            (while (or (eq (preceding-char) ?\,)
-                       (save-excursion (cperl-after-label)))
-              (if (eq (preceding-char) ?\,)
-                  ;; Will go to beginning of line, essentially
-                  ;; Will ignore embedded sexpr XXXX.
-                  (cperl-backward-to-start-of-continued-exp containing-sexp))
-              (beginning-of-line)
-              (cperl-backward-to-noncomment containing-sexp))
-            ;; Now we get the answer.
-            (if (not (memq (preceding-char) (append ";}{" '(nil)))) ; Was ?\,
-                ;; This line is continuation of preceding line's statement.
-                (list (list 'statement-continued containing-sexp))
-              ;; This line starts a new statement.
-              ;; Position following last unclosed open.
-              (goto-char containing-sexp)
-              ;; Is line first statement after an open-brace?
-              (or
-               ;; If no, find that first statement and indent like
-               ;; it.  If the first statement begins with label, do
-               ;; not believe when the indentation of the label is too
-               ;; small.
-               (save-excursion
-                 (forward-char 1)
-                 (let ((colon-line-end 0))
-                   (while (progn (skip-chars-forward " \t\n" start-point)
-                                 (and (< (point) start-point)
-                                      (looking-at
-                                       "#\\|[a-zA-Z_][a-zA-Z0-9_]*:[^:]")))
-                     ;; Skip over comments and labels following openbrace.
-                     (cond ((= (following-char) ?\#)
-                            ;;(forward-line 1)
-                            (end-of-line))
-                           ;; label:
-                           (t
-                            (save-excursion (end-of-line)
-                                            (setq colon-line-end (point)))
-                            (search-forward ":"))))
-                   ;; Now at the point, after label, or at start
-                   ;; of first statement in the block.
-                   (and (< (point) start-point)
-                        (if (> colon-line-end (point))
-                            ;; Before statement after label
-                            (if (> (current-indentation)
-                                   cperl-min-label-indent)
-                                (list (list 'label-in-block (point)))
-                              ;; Do not believe: `max' is involved
-                              (list
-                               (list 'label-in-block-min-indent (point))))
-                          ;; Before statement
-                          (list 'statement-in-block (point))))))
-               ;; If no previous statement,
-               ;; indent it relative to line brace is on.
-               ;; For open brace in column zero, don't let statement
-               ;; start there too.  If cperl-indent-level is zero,
-               ;; use cperl-brace-offset + cperl-continued-statement-offset instead.
-               ;; For open-braces not the first thing in a line,
-               ;; add in cperl-brace-imaginary-offset.
-
-               ;; If first thing on a line:  ?????
-               (setq unused            ; This is not finished...
-               (+ (if (and (bolp) (zerop cperl-indent-level))
-                      (+ cperl-brace-offset cperl-continued-statement-offset)
-                    cperl-indent-level)
-                  ;; Move back over whitespace before the openbrace.
-                  ;; If openbrace is not first nonwhite thing on the line,
-                  ;; add the cperl-brace-imaginary-offset.
-                  (progn (skip-chars-backward " \t")
-                         (if (bolp) 0 cperl-brace-imaginary-offset))
-                  ;; If the openbrace is preceded by a parenthesized exp,
-                  ;; move to the beginning of that;
-                  ;; possibly a different line
-                  (progn
-                    (if (eq (preceding-char) ?\))
-                        (forward-sexp -1))
-                    ;; Get initial indentation of the line we are on.
-                    ;; If line starts with label, calculate label indentation
-                    (if (save-excursion
-                          (beginning-of-line)
-                          (looking-at "[ \t]*[a-zA-Z_][a-zA-Z_0-9]*:[^:]"))
-                        (if (> (current-indentation) cperl-min-label-indent)
-                            (- (current-indentation) cperl-label-offset)
-                          (cperl-calculate-indent))
-                      (current-indentation)))))))))
-      res)))
+    (let ((i (cperl-sniff-for-indent parse-data)) what p)
+      (cond
+       ;;((or (null i) (eq i t) (numberp i))
+       ;;  i)
+       ((vectorp i)
+       (setq what (assoc (elt i 0) cperl-indent-rules-alist))
+       (cond
+        (what (cadr what))             ; Load from table
+        ;;
+        ;; Indenters for regular expressions with //x and qw()
+        ;;
+        ((eq 'REx-part2 (elt i 0)) ;; [self start] start of /REP in s//REP/x
+         (goto-char (elt i 1))
+         (condition-case nil   ; Use indentation of the 1st part
+             (forward-sexp -1))
+         (current-column))
+        ((eq 'indentable (elt i 0))    ; Indenter for REGEXP qw() etc
+         (cond                ;;; [indentable terminator start-pos is-block]
+          ((eq 'terminator (elt i 1)) ; Lone terminator of "indentable string"
+           (goto-char (elt i 2))       ; After opening parens
+           (1- (current-column)))
+          ((eq 'first-line (elt i 1)); [indentable first-line start-pos]
+           (goto-char (elt i 2))
+           (+ (or cperl-regexp-indent-step cperl-indent-level)
+              -1
+              (current-column)))
+          ((eq 'cont-line (elt i 1)); [indentable cont-line pos prev-pos first-char start-pos]
+           ;; Indent as the level after closing parens
+           (goto-char (elt i 2))       ; indent line
+           (skip-chars-forward " \t)") ; Skip closing parens
+           (setq p (point))
+           (goto-char (elt i 3))       ; previous line
+           (skip-chars-forward " \t)") ; Skip closing parens
+           ;; Number of parens in between:
+           (setq p (nth 0 (parse-partial-sexp (point) p))
+                 what (elt i 4))       ; First char on current line
+           (goto-char (elt i 3))       ; previous line
+           (+ (* p (or cperl-regexp-indent-step cperl-indent-level))
+              (cond ((eq what ?\) )
+                     (- cperl-close-paren-offset)) ; compensate
+                    ((eq what ?\| )
+                     (- (or cperl-regexp-indent-step cperl-indent-level)))
+                    (t 0))
+              (if (eq (following-char) ?\| )
+                  (or cperl-regexp-indent-step cperl-indent-level)
+                0)
+              (current-column)))
+          (t
+           (error "Unrecognized value of indent: " i))))
+        ;;
+        ;; Indenter for stuff at toplevel
+        ;;
+        ((eq 'toplevel (elt i 0)) ;; [toplevel start char-after state immed-after-block]
+         (+ (save-excursion            ; To beg-of-defun, or end of last sexp
+              (goto-char (elt i 1))    ; start = Good place to start parsing
+              (- (current-indentation) ; 
+                 (if (elt i 4) cperl-indent-level 0))) ; immed-after-block
+            (if (eq (elt i 2) ?{) cperl-continued-brace-offset 0) ; char-after
+            ;; Look at previous line that's at column 0
+            ;; to determine whether we are in top-level decls
+            ;; or function's arg decls.  Set basic-indent accordingly.
+            ;; Now add a little if this is a continuation line.
+            (if (elt i 3)              ; state (XXX What is the semantic???)
+                0
+              cperl-continued-statement-offset)))
+        ;;
+        ;; Indenter for stuff in "parentheses" (or brackets, braces-as-hash)
+        ;;
+        ((eq 'in-parens (elt i 0))
+         ;; in-parens char-after old-indent-point is-brace containing-sexp
+
+         ;; group is an expression, not a block:
+         ;; indent to just after the surrounding open parens,
+         ;; skip blanks if we do not close the expression.
+         (+ (progn
+              (goto-char (elt i 2))            ; old-indent-point
+              (current-column))
+            (if (and (elt i 3)         ; is-brace
+                     (eq (elt i 1) ?\})) ; char-after
+                ;; Correct indentation of trailing ?\}
+                (+ cperl-indent-level cperl-close-paren-offset)
+              0)))
+        ;;
+        ;; Indenter for continuation lines
+        ;;
+        ((eq 'continuation (elt i 0))
+         ;; [continuation statement-start char-after is-block is-brace]
+         (goto-char (elt i 1))         ; statement-start
+         (+ (if (memq (elt i 2) (append "}])" nil)) ; char-after
+                0                      ; Closing parenth
+              cperl-continued-statement-offset)
+            (if (or (elt i 3)          ; is-block
+                    (not (elt i 4))            ; is-brace
+                    (not (eq (elt i 2) ?\}))) ; char-after
+                0
+              ;; Now it is a hash reference
+              (+ cperl-indent-level cperl-close-paren-offset))
+            ;; Labels do not take :: ...
+            (if (looking-at "\\(\\w\\|_\\)+[ \t]*:")
+                (if (> (current-indentation) cperl-min-label-indent)
+                    (- (current-indentation) cperl-label-offset)
+                  ;; Do not move `parse-data', this should
+                  ;; be quick anyway (this comment comes
+                  ;; from different location):
+                  (cperl-calculate-indent))
+              (current-column))
+            (if (eq (elt i 2) ?\{)     ; char-after
+                cperl-continued-brace-offset 0)))
+        ;;
+        ;; Indenter for lines in a block which are not leading lines
+        ;;
+        ((eq 'have-prev-sibling (elt i 0))
+         ;; [have-prev-sibling sibling-beg colon-line-end block-start]
+         (goto-char (elt i 1))         ; sibling-beg
+         (if (> (elt i 2) (point)) ; colon-line-end; have label before point
+             (if (> (current-indentation)
+                    cperl-min-label-indent)
+                 (- (current-indentation) cperl-label-offset)
+               ;; Do not believe: `max' was involved in calculation of indent
+               (+ cperl-indent-level
+                  (save-excursion
+                    (goto-char (elt i 3)) ; block-start
+                    (current-indentation))))
+           (current-column)))
+        ;;
+        ;; Indenter for the first line in a block
+        ;;
+        ((eq 'code-start-in-block (elt i 0))
+         ;;[code-start-in-block before-brace char-after
+         ;; is-a-HASH-ref brace-is-first-thing-on-a-line
+         ;; group-starts-before-start-of-sub start-of-control-group]
+         (goto-char (elt i 1))
+         ;; For open brace in column zero, don't let statement
+         ;; start there too.  If cperl-indent-level=0,
+         ;; use cperl-brace-offset + cperl-continued-statement-offset instead.
+         (+ (if (and (bolp) (zerop cperl-indent-level))
+                (+ cperl-brace-offset cperl-continued-statement-offset)
+              cperl-indent-level)
+            (if (and (elt i 3) ; is-a-HASH-ref
+                     (eq (elt i 2) ?\})) ; char-after: End of a hash reference
+                (+ cperl-indent-level cperl-close-paren-offset)
+              0)
+            ;; Unless openbrace is the first nonwhite thing on the line,
+            ;; add the cperl-brace-imaginary-offset.
+            (if (elt i 4) 0            ; brace-is-first-thing-on-a-line
+              cperl-brace-imaginary-offset)
+            (progn
+              (goto-char (elt i 6))    ; start-of-control-group
+              (if (elt i 5)            ; group-starts-before-start-of-sub
+                  (current-column)
+                ;; Get initial indentation of the line we are on.
+                ;; If line starts with label, calculate label indentation
+                (if (save-excursion
+                      (beginning-of-line)
+                      (looking-at "[ \t]*[a-zA-Z_][a-zA-Z_0-9]*:[^:]"))
+                    (if (> (current-indentation) cperl-min-label-indent)
+                        (- (current-indentation) cperl-label-offset)
+                      ;; Do not move `parse-data', this should
+                      ;; be quick anyway:
+                      (cperl-calculate-indent))
+                  (current-indentation))))))
+        (t
+         (error "Unrecognized value of indent: " i))))
+       (t
+       (error (format "Got strange value of indent: " i)))))))
 
 (defun cperl-calculate-indent-within-comment ()
   "Return the indentation amount for line, assuming that
@@ -4858,10 +4973,14 @@ Works before syntax recognition is done."
 ;;     d) 'Q'uoted string:
 ;;             part between markers inclusive is marked `syntax-type' ==> `string'
 ;;             part between `q' and the first marker is marked `syntax-type' ==> `prestring'
+;;             second part of s///e is marked `syntax-type' ==> `multiline'
 ;;     e) Attributes of subroutines: `attrib-group' ==> t
 ;;             (or 0 if declaration); up to `{' or ';': `syntax-type' => `sub-decl'.
 ;;      f) Multiline my/our declaration lists etc: `syntax-type' => `multiline'
 
+;;; In addition, some parts of RExes may be marked as `REx-interpolated'
+;;; (value: 0 in //o, 1 if "interpolated variable" is whole-REx, t otherwise).
+
 (defun cperl-unwind-to-safe (before &optional end)
   ;; if BEFORE, go to the previous start-of-line on each step of unwinding
   (let ((pos (point)) opos)
@@ -4897,9 +5016,15 @@ Works before syntax recognition is done."
                           (setq end (point)))))
          (or end pos)))))
 
+;;; These are needed for byte-compile (at least with v19)
 (defvar cperl-nonoverridable-face)
+(defvar font-lock-variable-name-face)
 (defvar font-lock-function-name-face)
+(defvar font-lock-keyword-face)
+(defvar font-lock-builtin-face)
+(defvar font-lock-type-face)
 (defvar font-lock-comment-face)
+(defvar font-lock-warning-face)
 
 (defun cperl-find-sub-attrs (&optional st-l b-fname e-fname pos)
   "Syntaxically mark (and fontify) attributes of a subroutine.
@@ -4941,7 +5066,8 @@ Should be called with the point before leading colon of an attribute."
          (setq after-first t))
       (error (message
              "L%d: attribute `%s': %s"
-             (count-lines (point-min) (point)) (buffer-substring start1 end1) b)
+             (count-lines (point-min) (point))
+             (and start1 end1 (buffer-substring start1 end1)) b)
             (setq start nil)))
     (and start
         (progn
@@ -4967,12 +5093,14 @@ Should be called with the point before leading colon of an attribute."
        (set-syntax-table reset-st))))
 
 (defsubst cperl-look-at-leading-count (is-x-REx e)
-  (if (re-search-forward (concat "\\=" (if is-x-REx "[ \t\n]*" "") "[{?+*]")
-                        (1- e) t)      ; return nil on failure, no moving
+  (if (and
+       (< (point) e)
+       (re-search-forward (concat "\\=" (if is-x-REx "[ \t\n]*" "") "[{?+*]")
+                         (1- e) t))    ; return nil on failure, no moving
       (if (eq ?\{ (preceding-char)) nil
        (cperl-postpone-fontification
         (1- (point)) (point)
-        'face font-lock-function-name-face))))
+        'face font-lock-warning-face))))
 
 ;;; Debugging this may require (setq max-specpdl-size 2000)...
 (defun cperl-find-pods-heres (&optional min max non-inter end ignore-max end-of-here-doc)
@@ -4989,7 +5117,7 @@ the sections using `cperl-pod-head-face', `cperl-pod-face',
         face head-face here-face b e bb tag qtag b1 e1 argument i c tail tb
         is-REx is-x-REx REx-subgr-start REx-subgr-end was-subgr i2 hairy-RE
         (case-fold-search nil) (inhibit-read-only t) (buffer-undo-list t)
-        (modified (buffer-modified-p)) overshoot
+        (modified (buffer-modified-p)) overshoot is-o-REx
         (after-change-functions nil)
         (cperl-font-locking t)
         (use-syntax-state (and cperl-syntax-state
@@ -5002,24 +5130,53 @@ the sections using `cperl-pod-head-face', `cperl-pod-face',
         ;; (st-l '(nil)) (err-l '(nil)) ; Would overwrite - propagates from a function call to a function call!
         (st-l (list nil)) (err-l (list nil))
         ;; Somehow font-lock may be not loaded yet...
+        ;; (e.g., when building TAGS via command-line call)
         (font-lock-string-face (if (boundp 'font-lock-string-face)
                                    font-lock-string-face
                                  'font-lock-string-face))
-        (font-lock-constant-face (if (boundp 'font-lock-constant-face)
+        (my-cperl-delimiters-face (if (boundp 'font-lock-constant-face)
                                      font-lock-constant-face
                                    'font-lock-constant-face))
-        (font-lock-function-name-face
+        (my-cperl-REx-spec-char-face   ; [] ^.$ and wrapper-of ({})
+         (if (boundp 'font-lock-function-name-face)
+             font-lock-function-name-face
+           'font-lock-function-name-face))
+        (font-lock-variable-name-face  ; interpolated vars and ({})-code
+         (if (boundp 'font-lock-variable-name-face)
+             font-lock-variable-name-face
+           'font-lock-variable-name-face))
+        (font-lock-function-name-face  ; used in `cperl-find-sub-attrs'
          (if (boundp 'font-lock-function-name-face)
              font-lock-function-name-face
            'font-lock-function-name-face))
+        (font-lock-constant-face       ; used in `cperl-find-sub-attrs'
+         (if (boundp 'font-lock-constant-face)
+             font-lock-constant-face
+           'font-lock-constant-face))
+        (my-cperl-REx-0length-face ; 0-length, (?:)etc, non-literal \
+         (if (boundp 'font-lock-builtin-face)
+             font-lock-builtin-face
+           'font-lock-builtin-face))
         (font-lock-comment-face
          (if (boundp 'font-lock-comment-face)
              font-lock-comment-face
            'font-lock-comment-face))
-        (cperl-nonoverridable-face
+        (font-lock-warning-face
+         (if (boundp 'font-lock-warning-face)
+             font-lock-warning-face
+           'font-lock-warning-face))
+        (my-cperl-REx-ctl-face         ; (|)
+         (if (boundp 'font-lock-keyword-face)
+             font-lock-keyword-face
+           'font-lock-keyword-face))
+        (my-cperl-REx-modifiers-face   ; //gims
          (if (boundp 'cperl-nonoverridable-face)
              cperl-nonoverridable-face
            'cperl-nonoverridable-face))
+        (my-cperl-REx-length1-face     ; length=1 escaped chars, POSIX classes
+         (if (boundp 'font-lock-type-face)
+             font-lock-type-face
+           'font-lock-type-face))
         (stop-point (if ignore-max
                         (point-max)
                       max))
@@ -5090,6 +5247,7 @@ the sections using `cperl-pod-head-face', `cperl-pod-face',
            (remove-text-properties min max
                                    '(syntax-type t in-pod t syntax-table t
                                                  attrib-group t
+                                                 REx-interpolated t
                                                  cperl-postpone t
                                                  syntax-subtype t
                                                  rear-nonsticky t
@@ -5169,6 +5327,7 @@ the sections using `cperl-pod-head-face', `cperl-pod-face',
                         (remove-text-properties
                          max e '(syntax-type t in-pod t syntax-table t
                                              attrib-group t
+                                             REx-interpolated t
                                              cperl-postpone t
                                              syntax-subtype t
                                              here-doc-group t
@@ -5256,7 +5415,15 @@ the sections using `cperl-pod-head-face', `cperl-pod-face',
                                         (cond
                                          ((looking-at "[0-9$({]")
                                           (forward-sexp 1)
-                                          (looking-at "[ \t]*<<")))))
+                                          (and
+                                           (looking-at "[ \t]*<<")
+                                           (condition-case nil
+                                               ;; print $foo <<EOF
+                                               (progn
+                                                 (forward-sexp -2)
+                                                 (not
+                                                  (looking-at "\\(printf?\\|system\\|exec\\|sort\\)\\>")))
+                                               (error t)))))))
                                   (error nil))) ; func(<<EOF)
                               (and (not (match-beginning 6)) ; Empty
                                    (looking-at
@@ -5273,7 +5440,8 @@ the sections using `cperl-pod-head-face', `cperl-pod-face',
                        qtag (regexp-quote tag))
                  (cond (cperl-pod-here-fontify
                         ;; Highlight the starting delimiter
-                        (cperl-postpone-fontification b1 e1 'face font-lock-constant-face)
+                        (cperl-postpone-fontification 
+                         b1 e1 'face my-cperl-delimiters-face)
                         (cperl-put-do-not-fontify b1 e1 t)))
                  (forward-line)
                  (setq i (point))
@@ -5284,7 +5452,8 @@ the sections using `cperl-pod-head-face', `cperl-pod-face',
                  ;; some hook of fontification, and max is random
                  (or (and (re-search-forward (concat "^" qtag "$")
                                              stop-point 'toend)
-                          (eq (following-char) ?\n))
+                          ;;;(eq (following-char) ?\n) ; XXXX WHY???
+                          )
                    (progn              ; Pretend we matched at the end
                      (goto-char (point-max))
                      (re-search-forward "\\'")
@@ -5293,8 +5462,9 @@ the sections using `cperl-pod-head-face', `cperl-pod-face',
                  (if cperl-pod-here-fontify
                      (progn
                        ;; Highlight the ending delimiter
-                       (cperl-postpone-fontification (match-beginning 0) (match-end 0)
-                                                     'face font-lock-constant-face)
+                       (cperl-postpone-fontification
+                        (match-beginning 0) (match-end 0)
+                        'face my-cperl-delimiters-face)
                        (cperl-put-do-not-fontify b (match-end 0) t)
                        ;; Highlight the HERE-DOC
                        (cperl-postpone-fontification b (match-beginning 0)
@@ -5534,7 +5704,7 @@ the sections using `cperl-pod-head-face', `cperl-pod-face',
                                 (1- e1))
                        e (if i i e1)   ; end of the first part
                        qtag nil        ; need to preserve backslashitis
-                       is-x-REx nil)   ; REx has //x modifier
+                       is-x-REx nil is-o-REx nil); REx has //x //o modifiers
                  ;; If s{} (), then b/b1 are at "{", "(", e1/i after ")", "}"
                  ;; Commenting \\ is dangerous, what about ( ?
                  (and i tail
@@ -5543,6 +5713,9 @@ the sections using `cperl-pod-head-face', `cperl-pod-face',
                  (and (if go (looking-at ".\\sw*x")
                         (looking-at "\\sw*x")) ; qr//x
                       (setq is-x-REx t))
+                 (and (if go (looking-at ".\\sw*o")
+                        (looking-at "\\sw*o")) ; //o
+                      (setq is-o-REx t))
                  (if (null i)
                      ;; Considered as 1arg form
                      (progn
@@ -5571,6 +5744,7 @@ the sections using `cperl-pod-head-face', `cperl-pod-face',
                                (cperl-modify-syntax-type (1- (point)) cperl-st-ket)
                                (cperl-modify-syntax-type i cperl-st-bra)))
                          (put-text-property b i 'syntax-type 'string)
+                         (put-text-property i (point) 'syntax-type 'multiline)
                          (if is-x-REx
                              (put-text-property b i 'indentable t)))
                      (cperl-commentify b1 (point) t)
@@ -5586,7 +5760,7 @@ the sections using `cperl-pod-head-face', `cperl-pod-face',
                        (forward-word 1) ; skip modifiers s///s
                        (if tail (cperl-commentify tail (point) t))
                        (cperl-postpone-fontification
-                        e1 (point) 'face 'cperl-nonoverridable-face)))
+                        e1 (point) 'face my-cperl-REx-modifiers-face)))
                  ;; Check whether it is m// which means "previous match"
                  ;; and highlight differently
                  (setq is-REx
@@ -5604,7 +5778,7 @@ the sections using `cperl-pod-head-face', `cperl-pod-face',
                                   (not (looking-at "split\\>")))
                               (error t))))
                      (cperl-postpone-fontification
-                      b e 'face font-lock-function-name-face)
+                      b e 'face font-lock-warning-face)
                    (if (or i2          ; Has 2 args
                            (and cperl-fontify-m-as-s
                                 (or
@@ -5613,11 +5787,17 @@ the sections using `cperl-pod-head-face', `cperl-pod-face',
                                       (not (eq ?\< (char-after b)))))))
                        (progn
                          (cperl-postpone-fontification
-                          b (cperl-1+ b) 'face font-lock-constant-face)
+                          b (cperl-1+ b) 'face my-cperl-delimiters-face)
                          (cperl-postpone-fontification
-                          (1- e) e 'face font-lock-constant-face)))
+                          (1- e) e 'face my-cperl-delimiters-face)))
                    (if (and is-REx cperl-regexp-scan)
                        ;; Process RExen: embedded comments, charclasses and ]
+;;;/\3333\xFg\x{FFF}a\ppp\PPP\qqq\C\99f(?{  foo  })(??{  foo  })/;
+;;;/a\.b[^a[:ff:]b]x$ab->$[|$,$ab->[cd]->[ef]|$ab[xy].|^${a,b}{c,d}/;
+;;;/(?<=foo)(?<!bar)(x)(?:$ab|\$\/)$|\\\b\x888\776\[\:$/xxx;
+;;;m?(\?\?{b,a})? + m/(??{aa})(?(?=xx)aa|bb)(?#aac)/;
+;;;m$(^ab[c]\$)$ + m+(^ab[c]\$\+)+ + m](^ab[c\]$|.+)] + m)(^ab[c]$|.+\));
+;;;m^a[\^b]c^ + m.a[^b]\.c.;
                        (save-excursion
                          (goto-char (1+ b))
                          ;; First 
@@ -5636,12 +5816,33 @@ the sections using `cperl-pod-head-face', `cperl-pod-face',
                                    "\\(\\[\\)" ; 3=[
                                 "\\|"
                                    "\\(]\\)" ; 4=]
-                                "\\|"  ; 5=builtin 0-length, 6
+                                "\\|"
+                                ;; XXXX Will not be able to use it in s)))
+                                (if (eq (char-after b) ?\) )
+                                    "\\())))\\)" ; Will never match
+                                  (if (eq (char-after b) ?? )
+                                      ;;"\\((\\\\\\?\\(\\\\\\?\\)?{\\)"
+                                      "\\((\\\\\\?\\\\\\?{\\|()\\\\\\?{\\)"
+                                    "\\((\\?\\??{\\)")) ; 5= (??{ (?{
+                                "\\|"  ; 6= 0-length, 7: name, 8,9:code, 10:group
+                                   "\\(" ;; XXXX 1-char variables, exc. |()\s
+                                      "[$@]"
+                                      "\\("
+                                         "[_a-zA-Z:][_a-zA-Z0-9:]*"
+                                      "\\|"
+                                         "{[^{}]*}" ; only one-level allowed
+                                      "\\|"
+                                         "[^{(|) \t\r\n\f]"
+                                      "\\)"
+                                      "\\(" ;;8,9:code part of array/hash elt
+                                         "\\(" "->" "\\)?"
+                                         "\\[[^][]*\\]"
+                                         "\\|"
+                                         "{[^{}]*}"
+                                      "\\)*"
                                    ;; XXXX: what if u is delim?
-                                   "\\("
-                                      "[)^$|]"
                                    "\\|"
-                                      "[*?+]" ; Do not need \?? !
+                                      "[)^|$.*?+]"
                                    "\\|"
                                       "{[0-9]+}"
                                    "\\|"
@@ -5649,232 +5850,287 @@ the sections using `cperl-pod-head-face', `cperl-pod-face',
                                    "\\|"
                                       "\\\\[luLUEQbBAzZG]"
                                    "\\|"
-                                      "("
-                                      "\\("
-                                         "\\?[:=!>]"
+                                      "(" ; Group opener
+                                      "\\(" ; 10 group opener follower
+                                         "\\?\\((\\?\\)" ; 11: in (?(?=C)A|B)
+                                      "\\|"
+                                         "\\?[:=!>?{]" ; "?" something
                                       "\\|"
                                          "\\?[-imsx]+[:)]" ; (?i) (?-s:.)
                                       "\\|"
                                          "\\?([0-9]+)" ; (?(1)foo|bar)
                                       "\\|"
                                          "\\?<[=!]"
-                                      "\\|"
-                                         "\\?" ; (?(?=foo)bar|baz)
+                                      ;;;"\\|"
+                                      ;;;   "\\?"
                                       "\\)?"
                                    "\\)"
-                                ;; XXXX Need {5,6}?
                                 "\\|"
-                                   "\\\\\\(.\\)" ; 7=\SYMBOL
-                                ;; XXXX Will not be able to use it in s)))
-                                (if (eq (char-after b) ?\) ) ""
-                                  (concat
-                                   "\\|"
-                                   (if (eq (char-after b) ?? ) ; 8 = (?{
-                                       "\\((\\\\\\?\\(\\\\\\?\\)?{\\)"
-                                     "\\((\\?\\(\\?\\)?{\\)"))))) ; 8 = opt ?
+                                   "\\\\\\(.\\)" ; 12=\SYMBOL
+                                ))
                          (while
                              (and (< (point) (1- e))
                                   (re-search-forward hairy-RE (1- e) 'to-end))
                            (goto-char (match-beginning 0))
                            (setq REx-subgr-start (point)
-                                 was-subgr t)
-                           (if (save-excursion
-                                 (and
-                                  nil  ; Not needed now, when we skip \SYMBOL
-                                  (/= (1+ b) (point)) ; \ may be delim
-                                  (eq (preceding-char) ?\\)
-                                  (= (% (skip-chars-backward "\\\\") 2)
-                                     (if (and (eq (char-after b) ?\#)
-                                              (eq (following-char) ?\#))
-                                         0
-                                       -1))))
-                               ;; Not a subgr, avoid loop:
-                               (progn (setq was-subgr nil)
-                                      (forward-char 1))
-                             (cond
-                              ((match-beginning 5) ; 0-length builtins
-                               (setq was-subgr nil) ; We do stuff here
-                               (goto-char (match-end 5))
-                               (if (>= (point) e)
-                                   (goto-char (1- e)))
+                                 was-subgr (following-char))
+                           (cond
+                            ((match-beginning 6) ; 0-length builtins, groups
+                             (goto-char (match-end 0))
+                             (if (match-beginning 11)
+                                 (goto-char (match-beginning 11)))
+                             (if (>= (point) e)
+                                 (goto-char (1- e)))
+                             (cperl-postpone-fontification
+                              (match-beginning 0) (point)
+                              'face
+                              (cond
+                               ((eq was-subgr ?\) )
+                                (condition-case nil
+                                    (save-excursion
+                                      (forward-sexp -1)
+                                      (if (> (point) b)
+                                          (if (if (eq (char-after b) ?? )
+                                                  (looking-at "(\\\\\\?")
+                                                (eq (char-after (1+ (point))) ?\?))
+                                              my-cperl-REx-0length-face
+                                            my-cperl-REx-ctl-face)
+                                        font-lock-warning-face))
+                                  (error font-lock-warning-face)))
+                               ((eq was-subgr ?\| )
+                                my-cperl-REx-ctl-face)
+                               ((eq was-subgr ?\$ )
+                                (if (> (point) (1+ REx-subgr-start))
+                                    (progn
+                                      (put-text-property
+                                       (match-beginning 0) (point)
+                                       'REx-interpolated
+                                       (if is-o-REx 0
+                                           (if (and (eq (match-beginning 0)
+                                                        (1+ b))
+                                                    (eq (point)
+                                                        (1- e))) 1 t)))
+                                      font-lock-variable-name-face)
+                                  my-cperl-REx-spec-char-face))
+                               ((memq was-subgr (append "^." nil) )
+                                my-cperl-REx-spec-char-face)
+                               ((eq was-subgr ?\( )
+                                (if (not (match-beginning 10))
+                                    my-cperl-REx-ctl-face
+                                  my-cperl-REx-0length-face))
+                               (t my-cperl-REx-0length-face)))
+                             (if (and (memq was-subgr (append "(|" nil))
+                                      (not (string-match "(\\?[-imsx]+)"
+                                                         (match-string 0))))
+                                 (cperl-look-at-leading-count is-x-REx e))
+                             (setq was-subgr nil)) ; We do stuff here
+                            ((match-beginning 12) ; \SYMBOL
+                             (forward-char 2)
+                             (if (>= (point) e)
+                                 (goto-char (1- e))
+                               ;; How many chars to not highlight:
+                               ;; 0-len special-alnums in other branch =>
+                               ;; Generic:  \non-alnum (1), \alnum (1+face)
+                               ;; Is-delim: \non-alnum (1/spec-2) alnum-1 (=what hai)
+                               (setq REx-subgr-start (point)
+                                     qtag (preceding-char))
                                (cperl-postpone-fontification
-                                (match-beginning 5) (point)
-                                'face font-lock-variable-name-face)
-                               (if (and (memq (string-to-char (match-string 5))
-                                              (append "(|" nil))
-                                        (not (string-match "(\?[-imsx]+)"
-                                                           (match-string 5))))
-                                   (cperl-look-at-leading-count is-x-REx e)))
-                              ((match-beginning 7) ; \SYMBOL
-                               (forward-char 2)
-                               (if (>= (point) e)
-                                   (goto-char (1- e))
-                                 ;; 0-len special-alnums in other branch =>
-                                 ;; Generic:  \non-alnum (1), \alnum NO
-                                 ;; Is-delim: \non-alnum (1/spec-2) alnum-1 (=what hai)
-                                 ;; How many chars to not highlight
-                                 (setq was-subgr (if (eq (char-after b)
-                                                         (string-to-char
-                                                          (match-string 7)))
-                                                     (if (string-match
-                                                          "[][)^$|*?+]"
-                                                          (match-string 7))
-                                                         0
-                                                       1)
-                                                   (if (string-match
-                                                        "[a-zA-Z0-9]"
-                                                        (match-string 7))
-                                                       nil
-                                                     1)))
-                                 (if was-subgr
+                                (- (point) 2) (- (point) 1) 'face
+                                (if (memq qtag
+                                          (append "ghijkmoqvFHIJKMORTVY" nil))
+                                    font-lock-warning-face
+                                  my-cperl-REx-0length-face))
+                               (if (and (eq (char-after b) qtag)
+                                        (memq qtag (append ".])^$|*?+" nil)))
+                                   (progn
+                                     (if (and cperl-use-syntax-table-text-property
+                                              (eq qtag ?\) ))
+                                         (put-text-property
+                                          REx-subgr-start (1- (point))
+                                          'syntax-table cperl-st-punct))
                                      (cperl-postpone-fontification
-                                      (- (point) 2) (- (point) was-subgr)
-                                      'face font-lock-variable-name-face)))
-                               (setq was-subgr nil)) ; We do stuff here
-                              ((match-beginning 3) ; [charclass]
-                               ;; Mismatch for /$patterns->[1]/
-                               (forward-char 1)
-                               (setq qtag 0) ; leaders
-                               (if (eq (char-after b) ?^ )
-                                   (and (eq (following-char) ?\\ )
-                                        (eq (char-after (cperl-1+ (point)))
-                                            ?^ )
-                                        (forward-char 2))
-                                 (and (eq (following-char) ?^ )
-                                      (forward-char 1)))
-                               (setq argument b ; continue?
-                                     tag nil ; list of POSIX classes
-                                     qtag (point))
-                               (if (eq (char-after b) ?\] )
-                                   (and (eq (following-char) ?\\ )
-                                        (eq (char-after (cperl-1+ (point)))
-                                            ?\] )
-                                        (setq qtag (1+ qtag))
-                                        (forward-char 2))
-                                 (and (eq (following-char) ?\] )
-                                      (forward-char 1)))
-                               ;; Apparently, I can't put \] into a charclass
-                               ;; in m]]: m][\\\]\]] produces [\\]]
+                                      (1- (point)) (point) 'face
+                                       ; \] can't appear below
+                                      (if (memq qtag (append ".]^$" nil))
+                                          'my-cperl-REx-spec-char-face
+                                        (if (memq qtag (append "*?+" nil))
+                                            'my-cperl-REx-0length-face
+                                          'my-cperl-REx-ctl-face))))) ; )|
+                               ;; Test for arguments:
+                               (cond
+                                ;; This is not pretty: the 5.8.7 logic:
+                                ;; \0numx  -> octal (up to total 3 dig)
+                                ;; \DIGIT  -> backref unless \0
+                                ;; \DIGITs -> backref if legal
+                                ;;          otherwise up to 3 -> octal
+                                ;; Do not try to distinguish, we guess
+                                ((or (and (memq qtag (append "01234567" nil))
+                                          (re-search-forward
+                                           "\\=[01234567]?[01234567]?"
+                                           (1- e) 'to-end))
+                                     (and (memq qtag (append "89" nil))
+                                          (re-search-forward 
+                                           "\\=[0123456789]*" (1- e) 'to-end))
+                                     (and (eq qtag ?x)
+                                          (re-search-forward
+                                           "\\=[0-9a-fA-F][0-9a-fA-F]?\\|\\={[0-9a-fA-F]+}"
+                                           (1- e) 'to-end))
+                                     (and (memq qtag (append "pPN" nil))
+                                          (re-search-forward "\\={[^{}]+}\\|."
+                                           (1- e) 'to-end))
+                                     (eq (char-syntax qtag) ?w))
+                                 (cperl-postpone-fontification
+                                  (1- REx-subgr-start) (point)
+                                  'face my-cperl-REx-length1-face))))
+                             (setq was-subgr nil)) ; We do stuff here
+                            ((match-beginning 3) ; [charclass]
+                             (forward-char 1)
+                             (if (eq (char-after b) ?^ )
+                                 (and (eq (following-char) ?\\ )
+                                      (eq (char-after (cperl-1+ (point)))
+                                          ?^ )
+                                      (forward-char 2))
+                               (and (eq (following-char) ?^ )
+                                    (forward-char 1)))
+                             (setq argument b ; continue?
+                                   tag nil ; list of POSIX classes
+                                   qtag (point))
+                             (if (eq (char-after b) ?\] )
+                                 (and (eq (following-char) ?\\ )
+                                      (eq (char-after (cperl-1+ (point)))
+                                          ?\] )
+                                      (setq qtag (1+ qtag))
+                                      (forward-char 2))
+                               (and (eq (following-char) ?\] )
+                                    (forward-char 1)))
+                             ;; Apparently, I can't put \] into a charclass
+                             ;; in m]]: m][\\\]\]] produces [\\]]
 ;;; POSIX?  [:word:] [:^word:] only inside []
 ;;;                                   "\\=\\(\\\\.\\|[^][\\\\]\\|\\[:\\^?\sw+:]\\|\\[[^:]\\)*]")
-                               (while 
-                                   (and argument
-                                        (re-search-forward
-                                         (if (eq (char-after b) ?\] )
-                                             "\\=\\(\\\\[^]]\\|[^]\\\\]\\)*\\\\]"
-                                           "\\=\\(\\\\.\\|[^]\\\\]\\)*]")
-                                         (1- e) 'toend))
-                                        ;; Is this ] the end of POSIX class?
-                                 (if (save-excursion
-                                       (and
-                                        (search-backward "[" argument t)
-                                        (< REx-subgr-start (point))
-                                        (not
-                                         (and ; Should work with delim = \
-                                          (eq (preceding-char) ?\\ )
-                                          (= (% (skip-chars-backward
-                                                 "\\\\") 2) 0)))
-                                        (looking-at
-                                         (cond
-                                          ((eq (char-after b) ?\] )
-                                           "\\\\*\\[:\\^?\\sw+:\\\\\\]")
-                                          ((eq (char-after b) ?\: )
-                                           "\\\\*\\[\\\\:\\^?\\sw+\\\\:]")
-                                          ((eq (char-after b) ?^ )
-                                           "\\\\*\\[:\\(\\\\\\^\\)?\\sw+:\]")
-                                          ((eq (char-syntax (char-after b))
-                                               ?w)
-                                           (concat
-                                            "\\\\*\\[:\\(\\\\\\^\\)?\\(\\\\"
-                                            (char-to-string (char-after b))
-                                            "\\|\\sw\\)+:\]"))
-                                          (t "\\\\*\\[:\\^?\\sw*:]")))
-                                        (setq argument (point))))
-                                     (setq tag (cons (cons argument (point))
-                                                     tag)
-                                           argument (point)) ; continue
-                                   (setq argument nil)))
-                               (and argument
-                                    (message "Couldn't find end of charclass in a REx, pos=%s"
-                                            REx-subgr-start))
-                               (if (and cperl-use-syntax-table-text-property
-                                        (> (- (point) 2) REx-subgr-start))
-                                   (put-text-property
-                                    (1+ REx-subgr-start) (1- (point))
-                                    'syntax-table cperl-st-punct))
+                             (while 
+                                 (and argument
+                                      (re-search-forward
+                                       (if (eq (char-after b) ?\] )
+                                           "\\=\\(\\\\[^]]\\|[^]\\\\]\\)*\\\\]"
+                                         "\\=\\(\\\\.\\|[^]\\\\]\\)*]")
+                                       (1- e) 'toend))
+                               ;; Is this ] an end of POSIX class?
+                               (if (save-excursion
+                                     (and
+                                      (search-backward "[" argument t)
+                                      (< REx-subgr-start (point))
+                                      (not
+                                       (and ; Should work with delim = \
+                                        (eq (preceding-char) ?\\ )
+                                        (= (% (skip-chars-backward
+                                               "\\\\") 2) 0)))
+                                      (looking-at
+                                       (cond
+                                        ((eq (char-after b) ?\] )
+                                         "\\\\*\\[:\\^?\\sw+:\\\\\\]")
+                                        ((eq (char-after b) ?\: )
+                                         "\\\\*\\[\\\\:\\^?\\sw+\\\\:]")
+                                        ((eq (char-after b) ?^ )
+                                         "\\\\*\\[:\\(\\\\\\^\\)?\\sw+:\]")
+                                        ((eq (char-syntax (char-after b))
+                                             ?w)
+                                         (concat
+                                          "\\\\*\\[:\\(\\\\\\^\\)?\\(\\\\"
+                                          (char-to-string (char-after b))
+                                          "\\|\\sw\\)+:\]"))
+                                        (t "\\\\*\\[:\\^?\\sw*:]")))
+                                      (setq argument (point))))
+                                   (setq tag (cons (cons argument (point))
+                                                   tag)
+                                         argument (point)) ; continue
+                                 (setq argument nil)))
+                             (and argument
+                                  (message "Couldn't find end of charclass in a REx, pos=%s"
+                                           REx-subgr-start))
+                             (if (and cperl-use-syntax-table-text-property
+                                      (> (- (point) 2) REx-subgr-start))
+                                 (put-text-property
+                                  (1+ REx-subgr-start) (1- (point))
+                                  'syntax-table cperl-st-punct))
+                             (cperl-postpone-fontification
+                              REx-subgr-start qtag
+                              'face my-cperl-REx-spec-char-face)
+                             (cperl-postpone-fontification
+                              (1- (point)) (point) 'face
+                              my-cperl-REx-spec-char-face)
+                             (if (eq (char-after b) ?\] )
+                                 (cperl-postpone-fontification
+                                  (- (point) 2) (1- (point))
+                                  'face my-cperl-REx-0length-face))
+                             (while tag
+                               (cperl-postpone-fontification
+                                (car (car tag)) (cdr (car tag))
+                                'face my-cperl-REx-length1-face)
+                               (setq tag (cdr tag)))
+                             (setq was-subgr nil)) ; did facing already
+                            ;; Now rare stuff:
+                            ((and (match-beginning 2) ; #-comment
+                                  (/= (match-beginning 2) (match-end 2)))
+                             (beginning-of-line 2)
+                             (if (> (point) e)
+                                 (goto-char (1- e))))
+                            ((match-beginning 4) ; character "]"
+                             (setq was-subgr nil) ; We do stuff here
+                             (goto-char (match-end 0))
+                             (if cperl-use-syntax-table-text-property
+                                 (put-text-property
+                                  (1- (point)) (point)
+                                  'syntax-table cperl-st-punct))
+                             (cperl-postpone-fontification
+                              (1- (point)) (point)
+                              'face font-lock-warning-face))
+                            ((match-beginning 5) ; before (?{}) (??{})
+                             (setq tag (match-end 0))
+                             (if (or (setq qtag
+                                           (cperl-forward-group-in-re st-l))
+                                     (and (>= (point) e)
+                                          (setq qtag "no matching `)' found"))
+                                     (and (not (eq (char-after (- (point) 2))
+                                                   ?\} ))
+                                          (setq qtag "Can't find })")))
+                                 (progn
+                                   (goto-char (1- e))
+                                   (message qtag))
                                (cperl-postpone-fontification
-                                REx-subgr-start qtag
+                                (1- tag) (1- (point))
                                 'face font-lock-variable-name-face)
                                (cperl-postpone-fontification
-                                (if (eq (char-after b) ?\] )
-                                    (- (point) 2)
-                                  (1- (point)))
-                                (point) 'face font-lock-variable-name-face)
-                               (while tag
-                                 (cperl-postpone-fontification
-                                  (car (car tag)) (cdr (car tag))
-                                  'face font-lock-type-face)
-                                 (setq tag (cdr tag)))
-                               (setq was-subgr nil)) ; did facing already
-                              ;; Now rare stuff:
-                              ((and (match-beginning 2) ; #-comment
-                                    (/= (match-beginning 2) (match-end 2)))
-                               (beginning-of-line 2)
-                               (if (> (point) e)
-                                   (goto-char (1- e))))
-                              ((match-beginning 4) ; character "]"
-                               (setq was-subgr nil) ; We do stuff here
-                               (goto-char (match-end 0))
-                               (if cperl-use-syntax-table-text-property
-                                   (put-text-property
-                                    (1- (point)) (point)
-                                    'syntax-table cperl-st-punct))
+                                REx-subgr-start (1- tag)
+                                'face my-cperl-REx-spec-char-face)
                                (cperl-postpone-fontification
                                 (1- (point)) (point)
-                                'face font-lock-function-name-face))
-                              ((match-beginning 8) ; (?{})
-                               (setq was-subgr (point)
-                                     tag (match-end 0))
-                               (if (or
-                                    (setq qtag
-                                          (cperl-forward-group-in-re st-l))
-                                    (and (>= (point) e)
-                                         (setq qtag "no matching `)' found"))
-                                    (and
-                                     (not (eq (char-after (- (point) 2))
-                                              ?\} ))
-                                     (setq qtag "Can't find })")))
+                                'face my-cperl-REx-spec-char-face)
+                               (if cperl-use-syntax-table-text-property
                                    (progn
-                                     (goto-char (1- e))
-                                     (message qtag))
-                                 (cperl-postpone-fontification
-                                  (1- tag) (1- (point))
-                                  'face font-lock-variable-name-face)
-                                 (if cperl-use-syntax-table-text-property
-                                     (progn
-                                       (put-text-property
-                                        (1- (point)) (point)
-                                        'syntax-table cperl-st-cfence)
-                                       (put-text-property
-                                        was-subgr (1+ was-subgr)
-                                        'syntax-table cperl-st-cfence))))
-                               (setq was-subgr nil))
-                              (t       ; (?#)-comment
-                               ;; Inside "(" and "\" arn't special in any way
-                               ;; Works also if the outside delimiters are ().
-                               (or ;;(if (eq (char-after b) ?\) )
-                                       ;;(re-search-forward
-                                       ;; "[^\\\\]\\(\\\\\\\\\\)*\\\\)"
-                                       ;; (1- e) 'toend)
-                                     (search-forward ")" (1- e) 'toend)
-                                     ;;)
-                                   (message
-                                    "Couldn't find end of (?#...)-comment in a REx, pos=%s"
-                                    REx-subgr-start)))))
+                                     (put-text-property
+                                      (- (point) 2) (1- (point))
+                                      'syntax-table cperl-st-cfence)
+                                     (put-text-property
+                                      (+ REx-subgr-start 2)
+                                      (+ REx-subgr-start 3)
+                                      'syntax-table cperl-st-cfence))))
+                             (setq was-subgr nil))
+                            (t         ; (?#)-comment
+                             ;; Inside "(" and "\" arn't special in any way
+                             ;; Works also if the outside delimiters are ().
+                             (or;;(if (eq (char-after b) ?\) )
+                              ;;(re-search-forward
+                              ;; "[^\\\\]\\(\\\\\\\\\\)*\\\\)"
+                              ;; (1- e) 'toend)
+                              (search-forward ")" (1- e) 'toend)
+                              ;;)
+                              (message
+                               "Couldn't find end of (?#...)-comment in a REx, pos=%s"
+                               REx-subgr-start))))
                            (if (>= (point) e)
                                (goto-char (1- e)))
                            (cond
-                            ((eq was-subgr t)
+                            (was-subgr
                              (setq REx-subgr-end (point))
                              (cperl-commentify
                               REx-subgr-start REx-subgr-end nil)
@@ -5884,14 +6140,14 @@ the sections using `cperl-pod-head-face', `cperl-pod-face',
                    (if (and is-REx is-x-REx)
                        (put-text-property (1+ b) (1- e)
                                           'syntax-subtype 'x-REx)))
-                 (if i2
-                     (progn
+                 (if (and i2 e1 b1 (> e1 b1))
+                     (progn            ; No errors finding the second part...
                        (cperl-postpone-fontification
-                        (1- e1) e1 'face font-lock-constant-face)
+                        (1- e1) e1 'face my-cperl-delimiters-face)
                        (if (assoc (char-after b) cperl-starters)
                            (progn
                              (cperl-postpone-fontification
-                              b1 (1+ b1) 'face font-lock-constant-face)
+                              b1 (1+ b1) 'face my-cperl-delimiters-face)
                              (put-text-property b1 (1+ b1)
                                           'REx-part2 t)))))
                  (if (> (point) max)
@@ -5979,14 +6235,16 @@ the sections using `cperl-pod-head-face', `cperl-pod-face',
       (beginning-of-line)
       (if (memq (setq pr (get-text-property (point) 'syntax-type))
                '(pod here-doc here-doc-delim))
-         (cperl-unwind-to-safe nil)
-       (or (and (looking-at "^[ \t]*\\(#\\|$\\)")
-                (not (memq pr '(string prestring))))
-           (progn (cperl-to-comment-or-eol) (bolp))
-           (progn
-             (skip-chars-backward " \t")
-             (if (< p (point)) (goto-char p))
-             (setq stop t)))))))
+         (progn
+           (cperl-unwind-to-safe nil)
+           (setq pr (get-text-property (point) 'syntax-type))))
+      (or (and (looking-at "^[ \t]*\\(#\\|$\\)")
+              (not (memq pr '(string prestring))))
+         (progn (cperl-to-comment-or-eol) (bolp))
+         (progn
+           (skip-chars-backward " \t")
+           (if (< p (point)) (goto-char p))
+           (setq stop t))))))
 
 ;; Used only in `cperl-calculate-indent'...
 (defun cperl-block-p ()                   ; Do not C-M-q !  One string contains ";" !
@@ -6102,6 +6360,44 @@ CHARS is a string that contains good characters to have before us (however,
                       (eq (get-text-property (point) 'syntax-type)
                           'format)))))))))
 
+(defun cperl-backward-to-start-of-expr (&optional lim)
+  (condition-case nil
+      (progn
+       (while (and (or (not lim)
+                       (> (point) lim))
+                   (not (cperl-after-expr-p lim)))
+         (forward-sexp -1)
+         ;; May be after $, @, $# etc of a variable
+         (skip-chars-backward "$@%#")))
+    (error nil)))
+
+(defun cperl-at-end-of-expr (&optional lim)
+  ;; Since the SEXP approach below is very fragile, do some overengineering
+  (or (looking-at (concat cperl-maybe-white-and-comment-rex "[;}]"))
+      (condition-case nil
+         (save-excursion
+           ;; If nothing interesting after, does as (forward-sexp -1);
+           ;; otherwise fails, or ends at a start of following sexp.
+           ;; XXXX PROBLEMS: if what follows (after ";") @FOO, or ${bar}
+           ;; may be stuck after @ or $; just put some stupid workaround now:
+           (let ((p (point)))
+             (forward-sexp 1)
+             (forward-sexp -1)
+             (while (memq (preceding-char) (append "%&@$*" nil))
+               (forward-char -1))
+             (or (< (point) p)
+                 (cperl-after-expr-p lim))))
+       (error t))))
+
+(defun cperl-forward-to-end-of-expr (&optional lim)
+  (let ((p (point))))
+  (condition-case nil
+      (progn
+       (while (and (< (point) (or lim (point-max)))
+                   (not (cperl-at-end-of-expr)))
+         (forward-sexp 1)))
+    (error nil)))
+
 (defun cperl-backward-to-start-of-continued-exp (lim)
   (if (memq (preceding-char) (append ")]}\"'`" nil))
       (forward-sexp -1))
@@ -6145,18 +6441,51 @@ conditional/loop constructs."
        (beginning-of-line)
        (while (null done)
          (setq top (point))
-         (while (= (nth 0 (parse-partial-sexp (point) tmp-end
-                                              -1)) -1)
+         ;; Plan A: if line has an unfinished paren-group, go to end-of-group
+         (while (= -1 (nth 0 (parse-partial-sexp (point) tmp-end -1)))
            (setq top (point)))         ; Get the outermost parenths in line
          (goto-char top)
          (while (< (point) tmp-end)
            (parse-partial-sexp (point) tmp-end nil t) ; To start-sexp or eol
            (or (eolp) (forward-sexp 1)))
-         (if (> (point) tmp-end)
-             (save-excursion
-               (end-of-line)
-               (setq tmp-end (point)))
-           (setq done t)))
+         (if (> (point) tmp-end)       ; Yes, there an unfinished block
+             nil
+           (if (eq ?\) (preceding-char))
+               (progn ;; Plan B: find by REGEXP block followup this line
+                 (setq top (point))
+                 (condition-case nil
+                     (progn
+                       (forward-sexp -2)
+                       (if (eq (following-char) ?$ ) ; for my $var (list)
+                           (progn
+                             (forward-sexp -1)
+                             (if (looking-at "\\(my\\|local\\|our\\)\\>")
+                                 (forward-sexp -1))))
+                       (if (looking-at
+                            (concat "\\(\\elsif\\|if\\|unless\\|while\\|until"
+                                    "\\|for\\(each\\)?\\>\\(\\("
+                                    cperl-maybe-white-and-comment-rex
+                                    "\\(my\\|local\\|our\\)\\)?"
+                                    cperl-maybe-white-and-comment-rex
+                                    "\\$[_a-zA-Z0-9]+\\)?\\)\\>"))
+                           (progn
+                             (goto-char top)
+                             (forward-sexp 1)
+                             (setq top (point)))))
+                   (error (setq done t)))
+                 (goto-char top))
+             (if (looking-at           ; Try Plan C: continuation block
+                  (concat cperl-maybe-white-and-comment-rex
+                          "\\<\\(else\\|elsif\|continue\\)\\>"))
+                 (progn
+                   (goto-char (match-end 0))
+                   (save-excursion
+                     (end-of-line)
+                     (setq tmp-end (point))))
+               (setq done t))))
+         (save-excursion
+           (end-of-line)
+           (setq tmp-end (point))))
        (goto-char tmp-end)
        (setq tmp-end (point-marker)))
       (if cperl-indent-region-fix-constructs
@@ -6185,16 +6514,26 @@ Returns some position at the last line."
        ;; Looking at:
        ;; }
        ;; else
-       (if (and cperl-merge-trailing-else
-                (looking-at
-                 "[ \t]*}[ \t]*\n[ \t\n]*\\(els\\(e\\|if\\)\\|continue\\)\\>"))
-           (progn
-             (search-forward "}")
-             (setq p (point))
-             (skip-chars-forward " \t\n")
-             (delete-region p (point))
-             (insert (make-string cperl-indent-region-fix-constructs ?\ ))
-             (beginning-of-line)))
+       (if cperl-merge-trailing-else
+           (if (looking-at
+                "[ \t]*}[ \t]*\n[ \t\n]*\\(els\\(e\\|if\\)\\|continue\\)\\>")
+               (progn
+                 (search-forward "}")
+                 (setq p (point))
+                 (skip-chars-forward " \t\n")
+                 (delete-region p (point))
+                 (insert (make-string cperl-indent-region-fix-constructs ?\ ))
+                 (beginning-of-line)))
+         (if (looking-at "[ \t]*}[ \t]*\\(els\\(e\\|if\\)\\|continue\\)\\>")
+             (save-excursion
+                 (search-forward "}")
+                 (delete-horizontal-space)
+                 (insert "\n")
+                 (setq ret (point))
+                 (if (cperl-indent-line parse-data)
+                     (progn
+                       (cperl-fix-line-spacing end parse-data)
+                       (setq ret (point)))))))
        ;; Looking at:
        ;; }     else
        (if (looking-at "[ \t]*}\\(\t*\\|[ \t][ \t]+\\)\\<\\(els\\(e\\|if\\)\\|continue\\)\\>")
@@ -6231,19 +6570,19 @@ Returns some position at the last line."
              (insert
               (make-string cperl-indent-region-fix-constructs ?\ ))
              (beginning-of-line)))
-       ;; Looking at:
-       ;; } foreach my $var ()    {
+       ;; Looking at (with or without "}" at start, ending after "({"):
+       ;; } foreach my $var ()         OR   {
        (if (looking-at
             "[ \t]*\\(}[ \t]*\\)?\\<\\(\\els\\(e\\|if\\)\\|continue\\|if\\|unless\\|while\\|for\\(each\\)?\\(\\([ \t]+\\(my\\|local\\|our\\)\\)?[ \t]*\\$[_a-zA-Z0-9]+\\)?\\|until\\)\\>\\([ \t]*(\\|[ \t\n]*{\\)\\|[ \t]*{")
            (progn
-             (setq ml (match-beginning 8))
+             (setq ml (match-beginning 8)) ; "(" or "{" after control word
              (re-search-forward "[({]")
              (forward-char -1)
              (setq p (point))
              (if (eq (following-char) ?\( )
                  (progn
                    (forward-sexp 1)
-                   (setq pp (point)))
+                   (setq pp (point)))  ; past parenth-group
                ;; after `else' or nothing
                (if ml                  ; after `else'
                    (skip-chars-backward " \t\n")
@@ -6253,13 +6592,13 @@ Returns some position at the last line."
              ;; Multiline expr should be special
              (setq ml (and pp (save-excursion (goto-char p)
                                               (search-forward "\n" pp t))))
-             (if (and (or (not pp) (< pp end))
+             (if (and (or (not pp) (< pp end)) ; Do not go too far...
                       (looking-at "[ \t\n]*{"))
                  (progn
                    (cond
                     ((bolp)            ; Were before `{', no if/else/etc
                      nil)
-                    ((looking-at "\\(\t*\\| [ \t]+\\){")
+                    ((looking-at "\\(\t*\\| [ \t]+\\){") ; Not exactly 1 SPACE
                      (delete-horizontal-space)
                      (if (if ml
                              cperl-extra-newline-before-brace-multiline
@@ -6282,7 +6621,17 @@ Returns some position at the last line."
                      (skip-chars-forward " \t\n")
                      (delete-region pp (point))
                      (insert
-                      (make-string cperl-indent-region-fix-constructs ?\ ))))
+                      (make-string cperl-indent-region-fix-constructs ?\ )))
+                    ((and (looking-at "[\t ]*{")
+                          (if ml cperl-extra-newline-before-brace-multiline
+                            cperl-extra-newline-before-brace))
+                     (delete-horizontal-space)
+                     (insert "\n")
+                     (setq ret (point))
+                     (if (cperl-indent-line parse-data)
+                         (progn
+                           (cperl-fix-line-spacing end parse-data)
+                           (setq ret (point))))))
                    ;; Now we are before `{'
                    (if (looking-at "[ \t\n]*{[ \t]*[^ \t\n#]")
                        (progn
@@ -6748,19 +7097,23 @@ indentation and initial hashes.  Behaves usually outside of comment."
 
 (defun cperl-windowed-init ()
   "Initialization under windowed version."
-  (if (or (featurep 'ps-print) cperl-faces-init)
-      ;; Need to init anyway:
-      (or cperl-faces-init (cperl-init-faces))
-    (add-hook 'font-lock-mode-hook
-             (function
-              (lambda ()
-                (if (memq major-mode '(perl-mode cperl-mode))
-                    (progn
-                      (or cperl-faces-init (cperl-init-faces)))))))
-    (if (fboundp 'eval-after-load)
-       (eval-after-load
-           "ps-print"
-         '(or cperl-faces-init (cperl-init-faces))))))
+  (cond ((featurep 'ps-print)
+        (or cperl-faces-init
+            (progn
+              (and (boundp 'font-lock-multiline)
+                   (setq cperl-font-lock-multiline t))
+              (cperl-init-faces))))
+       ((not cperl-faces-init)
+        (add-hook 'font-lock-mode-hook
+                  (function
+                   (lambda ()
+                     (if (memq major-mode '(perl-mode cperl-mode))
+                         (progn
+                           (or cperl-faces-init (cperl-init-faces)))))))
+        (if (fboundp 'eval-after-load)
+            (eval-after-load
+                "ps-print"
+              '(or cperl-faces-init (cperl-init-faces)))))))
 
 (defun cperl-load-font-lock-keywords ()
   (or cperl-faces-init (cperl-init-faces))
@@ -6787,9 +7140,12 @@ indentation and initial hashes.  Behaves usually outside of comment."
   ;; Allow `cperl-find-pods-heres' to run.
   (or (boundp 'font-lock-constant-face)
       (cperl-force-face font-lock-constant-face
-                        "Face for constant and label names")
-      ;;(setq font-lock-constant-face 'font-lock-constant-face)
-      ))
+                        "Face for constant and label names"))
+  (or (boundp 'font-lock-warning-face)
+      (cperl-force-face font-lock-warning-face
+                       "Face for things which should stand out"))
+  ;;(setq font-lock-constant-face 'font-lock-constant-face)
+  )
 
 (defun cperl-init-faces ()
   (condition-case errs
@@ -7054,6 +7410,12 @@ indentation and initial hashes.  Behaves usually outside of comment."
                         cperl-array-face) ; arrays and hashes
                     font-lock-variable-name-face) ; Just to put something
                   t)
+                 ("\\(@\\|\\$#\\)\\(\\$+\\([a-zA-Z_:][a-zA-Z0-9_:]*\\|[^ \t\n]\\)\\)"
+                  (1 cperl-array-face)
+                  (2 font-lock-variable-name-face))
+                 ("\\(%\\)\\(\\$+\\([a-zA-Z_:][a-zA-Z0-9_:]*\\|[^ \t\n]\\)\\)"
+                  (1 cperl-hash-face)
+                  (2 font-lock-variable-name-face))
                  ;;("\\([smy]\\|tr\\)\\([^a-z_A-Z0-9]\\)\\(\\([^\n\\]*||\\)\\)\\2")
                       ;;; Too much noise from \s* @s[ and friends
                  ;;("\\(\\<\\([msy]\\|tr\\)[ \t]*\\([^ \t\na-zA-Z0-9_]\\)\\|\\(/\\)\\)"
@@ -7065,7 +7427,7 @@ indentation and initial hashes.  Behaves usually outside of comment."
          (if cperl-highlight-variables-indiscriminately
              (setq t-font-lock-keywords-1
                    (append t-font-lock-keywords-1
-                           (list '("[$*]{?\\(\\sw+\\)" 1
+                           (list '("\\([$*]{?\\sw+\\)" 1
                                    font-lock-variable-name-face)))))
          (setq perl-font-lock-keywords-1
                (if cperl-syntaxify-by-font-lock
@@ -7118,6 +7480,14 @@ indentation and initial hashes.  Behaves usually outside of comment."
                      [nil              nil             t               t       t]
                      nil
                      [nil              nil             t               t       t])
+               (list 'font-lock-warning-face
+                     ["Pink"           "Red"           "Gray50"        "LightGray"]
+                     ["gray20"         "gray90"
+                                                       "gray80"        "gray20"]
+                     [nil              nil             t               t       t]
+                     nil
+                     [nil              nil             t               t       t]
+                     )
                (list 'font-lock-constant-face
                      ["CadetBlue"      "Aquamarine"    "Gray50"        "LightGray"]
                      nil
@@ -7163,6 +7533,8 @@ indentation and initial hashes.  Behaves usually outside of comment."
                            "Face for data types")
          (cperl-force-face cperl-nonoverridable-face
                            "Face for data types from another group")
+         (cperl-force-face font-lock-warning-face
+                           "Face for things which should stand out")
          (cperl-force-face font-lock-comment-face
                            "Face for comments")
          (cperl-force-face font-lock-function-name-face
@@ -7391,79 +7763,211 @@ Style of printout regulated by the variable `cperl-ps-print-face-properties'."
 (defconst cperl-styles-entries
   '(cperl-indent-level cperl-brace-offset cperl-continued-brace-offset
     cperl-label-offset cperl-extra-newline-before-brace
+    cperl-extra-newline-before-brace-multiline
     cperl-merge-trailing-else
     cperl-continued-statement-offset))
 
+(defconst cperl-style-examples
+"##### Numbers etc are: cperl-indent-level cperl-brace-offset
+##### cperl-continued-brace-offset cperl-label-offset
+##### cperl-continued-statement-offset
+##### cperl-merge-trailing-else cperl-extra-newline-before-brace
+
+########### (Do not forget cperl-extra-newline-before-brace-multiline)
+
+### CPerl      (=GNU - extra-newline-before-brace + merge-trailing-else) 2/0/0/-2/2/t/nil
+if (foo) {
+  bar
+    baz;
+ label:
+  {
+    boon;
+  }
+} else {
+  stop;
+}
+
+### PerlStyle  (=CPerl with 4 as indent)               4/0/0/-4/4/t/nil
+if (foo) {
+    bar
+       baz;
+ label:
+    {
+       boon;
+    }
+} else {
+    stop;
+}
+
+### GNU                                                        2/0/0/-2/2/nil/t
+if (foo)
+  {
+    bar
+      baz;
+  label:
+    {
+      boon;
+    }
+  }
+else
+  {
+    stop;
+  }
+
+### C++                (=PerlStyle with braces aligned with control words) 4/0/-4/-4/4/nil/t
+if (foo)
+{
+    bar
+       baz;
+ label:
+    {
+       boon;
+    }
+}
+else
+{
+    stop;
+}
+
+### BSD                (=C++, but will not change preexisting merge-trailing-else
+###             and extra-newline-before-brace )               4/0/-4/-4/4
+if (foo)
+{
+    bar
+       baz;
+ label:
+    {
+       boon;
+    }
+}
+else
+{
+    stop;
+}
+
+### K&R                (=C++ with indent 5 - merge-trailing-else, but will not
+###             change preexisting extra-newline-before-brace) 5/0/-5/-5/5/nil
+if (foo)
+{
+     bar
+         baz;
+ label:
+     {
+         boon;
+     }
+}
+else
+{
+     stop;
+}
+
+### Whitesmith (=PerlStyle, but will not change preexisting
+###             extra-newline-before-brace and merge-trailing-else) 4/0/0/-4/4
+if (foo)
+    {
+       bar
+           baz;
+    label:
+       {
+           boon;
+       }
+    }
+else
+    {
+       stop;
+    }
+"
+"Examples of if/else with different indent styles (with v4.23).")
+
 (defconst cperl-style-alist
-  '(("CPerl"                        ; =GNU without extra-newline-before-brace
+  '(("CPerl" ;; =GNU - extra-newline-before-brace + cperl-merge-trailing-else
      (cperl-indent-level               .  2)
      (cperl-brace-offset               .  0)
      (cperl-continued-brace-offset     .  0)
      (cperl-label-offset               . -2)
+     (cperl-continued-statement-offset .  2)
      (cperl-extra-newline-before-brace .  nil)
-     (cperl-merge-trailing-else               .  t)
-     (cperl-continued-statement-offset .  2))
+     (cperl-extra-newline-before-brace-multiline .  nil)
+     (cperl-merge-trailing-else               .  t))
+
     ("PerlStyle"                       ; CPerl with 4 as indent
      (cperl-indent-level               .  4)
      (cperl-brace-offset               .  0)
      (cperl-continued-brace-offset     .  0)
      (cperl-label-offset               . -4)
+     (cperl-continued-statement-offset .  4)
      (cperl-extra-newline-before-brace .  nil)
-     (cperl-merge-trailing-else               .  t)
-     (cperl-continued-statement-offset .  4))
+     (cperl-extra-newline-before-brace-multiline .  nil)
+     (cperl-merge-trailing-else               .  t))
+
     ("GNU"
      (cperl-indent-level               .  2)
      (cperl-brace-offset               .  0)
      (cperl-continued-brace-offset     .  0)
      (cperl-label-offset               . -2)
+     (cperl-continued-statement-offset .  2)
      (cperl-extra-newline-before-brace .  t)
-     (cperl-merge-trailing-else               .  nil)
-     (cperl-continued-statement-offset .  2))
+     (cperl-extra-newline-before-brace-multiline .  t)
+     (cperl-merge-trailing-else               .  nil))
+
     ("K&R"
      (cperl-indent-level               .  5)
      (cperl-brace-offset               .  0)
      (cperl-continued-brace-offset     . -5)
      (cperl-label-offset               . -5)
+     (cperl-continued-statement-offset .  5)
      ;;(cperl-extra-newline-before-brace .  nil) ; ???
-     (cperl-merge-trailing-else               .  nil)
-     (cperl-continued-statement-offset .  5))
+     ;;(cperl-extra-newline-before-brace-multiline .  nil)
+     (cperl-merge-trailing-else               .  nil))
+
     ("BSD"
      (cperl-indent-level               .  4)
      (cperl-brace-offset               .  0)
      (cperl-continued-brace-offset     . -4)
      (cperl-label-offset               . -4)
+     (cperl-continued-statement-offset .  4)
      ;;(cperl-extra-newline-before-brace .  nil) ; ???
-     (cperl-continued-statement-offset .  4))
+     ;;(cperl-extra-newline-before-brace-multiline .  nil)
+     ;;(cperl-merge-trailing-else             .  nil) ; ???
+     )
+
     ("C++"
      (cperl-indent-level               .  4)
      (cperl-brace-offset               .  0)
      (cperl-continued-brace-offset     . -4)
      (cperl-label-offset               . -4)
      (cperl-continued-statement-offset .  4)
-     (cperl-merge-trailing-else               .  nil)
-     (cperl-extra-newline-before-brace .  t))
-    ("Current")
+     (cperl-extra-newline-before-brace .  t)
+     (cperl-extra-newline-before-brace-multiline .  t)
+     (cperl-merge-trailing-else               .  nil))
+
     ("Whitesmith"
      (cperl-indent-level               .  4)
      (cperl-brace-offset               .  0)
      (cperl-continued-brace-offset     .  0)
      (cperl-label-offset               . -4)
+     (cperl-continued-statement-offset .  4)
      ;;(cperl-extra-newline-before-brace .  nil) ; ???
-     (cperl-continued-statement-offset .  4)))
-  "(Experimental) list of variables to set to get a particular indentation style.
-Should be used via `cperl-set-style' or via Perl menu.")
+     ;;(cperl-extra-newline-before-brace-multiline .  nil)
+     ;;(cperl-merge-trailing-else             .  nil) ; ???
+     )
+    ("Current"))
+  "List of variables to set to get a particular indentation style.
+Should be used via `cperl-set-style' or via Perl menu.
+
+See examples in `cperl-style-examples'.")
 
 (defun cperl-set-style (style)
   "Set CPerl mode variables to use one of several different indentation styles.
 The arguments are a string representing the desired style.
 The list of styles is in `cperl-style-alist', available styles
-are GNU, K&R, BSD, C++ and Whitesmith.
+are CPerl, PerlStyle, GNU, K&R, BSD, C++ and Whitesmith.
 
 The current value of style is memorized (unless there is a memorized
 data already), may be restored by `cperl-set-style-back'.
 
 Chosing \"Current\" style will not change style, so this may be used for
-side-effect of memorizing only."
+side-effect of memorizing only.  Examples in `cperl-style-examples'."
   (interactive
    (let ((list (mapcar (function (lambda (elt) (list (car elt))))
                       cperl-style-alist)))
@@ -8688,8 +9192,8 @@ $~        The name of the current report format.
 \\  Creates reference to what follows, like \$var, or quotes non-\w in strings.
 \\0    Octal char, e.g. \\033.
 \\E    Case modification terminator.  See \\Q, \\L, and \\U.
-\\L    Lowercase until \\E .  See also \l, lc.
-\\U    Upcase until \\E .  See also \u, uc.
+\\L    Lowercase until \\E .  See also \\l, lc.
+\\U    Upcase until \\E .  See also \\u, uc.
 \\Q    Quote metacharacters until \\E .  See also quotemeta.
 \\a    Alarm character (octal 007).
 \\b    Backspace character (octal 010).
@@ -8751,7 +9255,7 @@ endservent
 eof[([FILEHANDLE])]
 ... eq ...     String equality.
 eval(EXPR) or eval { BLOCK }
-exec(LIST)
+exec([TRUENAME] ARGV0, ARGVs)     or     exec(SHELL_COMMAND_LINE)
 exit(EXPR)
 exp(EXPR)
 fcntl(FILEHANDLE,FUNCTION,SCALAR)
@@ -8887,7 +9391,7 @@ substr(EXPR,OFFSET[,LEN])
 symlink(OLDFILE,NEWFILE)
 syscall(LIST)
 sysread(FILEHANDLE,SCALAR,LENGTH[,OFFSET])
-system(LIST)
+system([TRUENAME] ARGV0 [,ARGV])     or     system(SHELL_COMMAND_LINE)
 syswrite(FILEHANDLE,SCALAR,LENGTH[,OFFSET])
 tell[(FILEHANDLE)]
 telldir(DIRHANDLE)
@@ -9285,91 +9789,191 @@ We suppose that the regexp is scanned already."
       (set-marker e (1- (point)))
       (cperl-beautify-regexp-piece b e nil deep))))
 
+(defun cperl-invert-if-unless-modifiers ()
+  "Change `B if A;' into `if (A) {B}' etc if possible.
+\(Unfinished.)"
+  (interactive)                                ; 
+  (let (A B pre-B post-B pre-if post-if pre-A post-A if-string
+         (w-rex "\\<\\(if\\|unless\\|while\\|until\\|for\\|foreach\\)\\>"))
+    (and (= (char-syntax (preceding-char)) ?w)
+        (forward-sexp -1))
+    (setq pre-if (point))
+    (cperl-backward-to-start-of-expr)
+    (setq pre-B (point))
+    (forward-sexp 1)           ; otherwise forward-to-end-of-expr is NOP
+    (cperl-forward-to-end-of-expr)
+    (setq post-A (point))
+    (goto-char pre-if)
+    (or (looking-at w-rex)
+       ;; Find the position
+       (progn (goto-char post-A)
+              (while (and
+                      (not (looking-at w-rex))
+                      (> (point) pre-B))
+                (forward-sexp -1))
+              (setq pre-if (point))))
+    (or (looking-at w-rex)
+       (error "Can't find `if', `unless', `while', `until', `for' or `foreach'"))
+    ;; 1 B 2 ... 3 B-com ... 4 if 5 ... if-com 6 ... 7 A 8
+    (setq if-string (buffer-substring (match-beginning 0) (match-end 0)))
+    ;; First, simple part: find code boundaries
+    (forward-sexp 1)
+    (setq post-if (point))
+    (forward-sexp -2)
+    (forward-sexp 1)
+    (setq post-B (point))
+    (cperl-backward-to-start-of-expr)
+    (setq pre-B (point))
+    (setq B (buffer-substring pre-B post-B))
+    (goto-char pre-if)
+    (forward-sexp 2)
+    (forward-sexp -1)
+    ;; May be after $, @, $# etc of a variable
+    (skip-chars-backward "$@%#")
+    (setq pre-A (point))
+    (cperl-forward-to-end-of-expr)
+    (setq post-A (point))
+    (setq A (buffer-substring pre-A post-A))
+    ;; Now modify (from end, to not break the stuff)
+    (skip-chars-forward " \t;")
+    (delete-region pre-A (point))      ; we move to pre-A
+    (insert "\n" B ";\n}")
+    (and (looking-at "[ \t]*#") (cperl-indent-for-comment))
+    (delete-region pre-if post-if)
+    (delete-region pre-B post-B)
+    (goto-char pre-B)
+    (insert if-string " (" A ") {")
+    (setq post-B (point))
+    (if (looking-at "[ \t]+$")
+       (delete-horizontal-space)
+      (if (looking-at "[ \t]*#")
+         (cperl-indent-for-comment)
+       (just-one-space)))
+    (forward-line 1)
+    (if (looking-at "[ \t]*$")
+       (progn                          ; delete line
+         (delete-horizontal-space)
+         (delete-region (point) (1+ (point)))))
+    (cperl-indent-line)
+    (goto-char (1- post-B))
+    (forward-sexp 1)
+    (cperl-indent-line)
+    (goto-char pre-B)))
+
 (defun cperl-invert-if-unless ()
-  "Change `if (A) {B}' into `B if A;' etc if possible."
+  "Change `if (A) {B}' into `B if A;' etc (or visa versa) if possible.
+If the cursor is not on the leading keyword of the BLOCK flavor of
+construct, will assume it is the STATEMENT flavor, so will try to find
+the appropriate statement modifier."
   (interactive)
-  (or (looking-at "\\<")
-      (forward-sexp -1))
+  (and (= (char-syntax (preceding-char)) ?w)
+       (forward-sexp -1))
   (if (looking-at "\\<\\(if\\|unless\\|while\\|until\\|for\\|foreach\\)\\>")
-      (let ((pos1 (point))
-           pos2 pos3 pos4 pos5 s1 s2 state p pos45
-           (s0 (buffer-substring (match-beginning 0) (match-end 0))))
+      (let ((pre-if (point))
+           pre-A post-A pre-B post-B A B state p end-B-code is-block B-comment
+           (if-string (buffer-substring (match-beginning 0) (match-end 0))))
        (forward-sexp 2)
-       (setq pos3 (point))
+       (setq post-A (point))
        (forward-sexp -1)
-       (setq pos2 (point))
-       (if (eq (following-char) ?\( )
+       (setq pre-A (point))
+       (setq is-block (and (eq (following-char) ?\( )
+                           (save-excursion
+                             (condition-case nil
+                                 (progn
+                                   (forward-sexp 2)
+                                   (forward-sexp -1)
+                                   (eq (following-char) ?\{ ))
+                               (error nil)))))
+       (if is-block
            (progn
-             (goto-char pos3)
+             (goto-char post-A)
              (forward-sexp 1)
-             (setq pos5 (point))
+             (setq post-B (point))
              (forward-sexp -1)
-             (setq pos4 (point))
-             ;; XXXX In fact may be `A if (B); {C}' ...
+             (setq pre-B (point))
              (if (and (eq (following-char) ?\{ )
                       (progn
-                        (cperl-backward-to-noncomment pos3)
+                        (cperl-backward-to-noncomment post-A)
                         (eq (preceding-char) ?\) )))
                  (if (condition-case nil
                          (progn
-                           (goto-char pos5)
+                           (goto-char post-B)
                            (forward-sexp 1)
                            (forward-sexp -1)
                            (looking-at "\\<els\\(e\\|if\\)\\>"))
                        (error nil))
                      (error
-                      "`%s' (EXPR) {BLOCK} with `else'/`elsif'" s0)
-                   (goto-char (1- pos5))
-                   (cperl-backward-to-noncomment pos4)
+                      "`%s' (EXPR) {BLOCK} with `else'/`elsif'" if-string)
+                   (goto-char (1- post-B))
+                   (cperl-backward-to-noncomment pre-B)
                    (if (eq (preceding-char) ?\;)
                        (forward-char -1))
-                   (setq pos45 (point))
-                   (goto-char pos4)
-                   (while (re-search-forward "\\<\\(for\\|foreach\\|if\\|unless\\|while\\|until\\)\\>\\|;" pos45 t)
+                   (setq end-B-code (point))
+                   (goto-char pre-B)
+                   (while (re-search-forward "\\<\\(for\\|foreach\\|if\\|unless\\|while\\|until\\)\\>\\|;" end-B-code t)
                      (setq p (match-beginning 0)
-                           s1 (buffer-substring p (match-end 0))
-                           state (parse-partial-sexp pos4 p))
+                           A (buffer-substring p (match-end 0))
+                           state (parse-partial-sexp pre-B p))
                      (or (nth 3 state)
                          (nth 4 state)
                          (nth 5 state)
-                         (error "`%s' inside `%s' BLOCK" s1 s0))
+                         (error "`%s' inside `%s' BLOCK" A if-string))
                      (goto-char (match-end 0)))
                    ;; Finally got it
-                   (goto-char (1+ pos4))
+                   (goto-char (1+ pre-B))
                    (skip-chars-forward " \t\n")
-                   (setq s2 (buffer-substring (point) pos45))
-                   (goto-char pos45)
+                   (setq B (buffer-substring (point) end-B-code))
+                   (goto-char end-B-code)
                    (or (looking-at ";?[ \t\n]*}")
                        (progn
                          (skip-chars-forward "; \t\n")
-                         (setq s2 (concat s2 "\n" (buffer-substring (point) (1- pos5))))))
-                   (and (equal s2 "")
-                        (setq s2 "1"))
-                   (goto-char (1- pos3))
-                   (cperl-backward-to-noncomment pos2)
+                         (setq B-comment
+                               (buffer-substring (point) (1- post-B)))))
+                   (and (equal B "")
+                        (setq B "1"))
+                   (goto-char (1- post-A))
+                   (cperl-backward-to-noncomment pre-A)
                    (or (looking-at "[ \t\n]*)")
-                       (goto-char (1- pos3)))
+                       (goto-char (1- post-A)))
                    (setq p (point))
-                   (goto-char (1+ pos2))
+                   (goto-char (1+ pre-A))
                    (skip-chars-forward " \t\n")
-                   (setq s1 (buffer-substring (point) p))
-                   (delete-region pos4 pos5)
-                   (delete-region pos2 pos3)
-                   (goto-char pos1)
-                   (insert s2 " ")
+                   (setq A (buffer-substring (point) p))
+                   (delete-region pre-B post-B)
+                   (delete-region pre-A post-A)
+                   (goto-char pre-if)
+                   (insert B " ")
+                   (and B-comment (insert B-comment " "))
                    (just-one-space)
                    (forward-word 1)
-                   (setq pos1 (point))
-                   (insert " " s1 ";")
+                   (setq pre-A (point))
+                   (insert " " A ";")
                    (delete-horizontal-space)
+                   (setq post-B (point))
+                   (if (looking-at "#")
+                       (indent-for-comment))
+                   (goto-char post-B)
                    (forward-char -1)
                    (delete-horizontal-space)
-                   (goto-char pos1)
+                   (goto-char pre-A)
                    (just-one-space)
-                   (cperl-indent-line))
-               (error "`%s' (EXPR) not with an {BLOCK}" s0)))
-         (error "`%s' not with an (EXPR)" s0)))
-    (error "Not at `if', `unless', `while', `until', `for' or `foreach'")))
+                   (goto-char pre-if)
+                   (setq pre-A (set-marker (make-marker) pre-A))
+                   (while (<= (point) (marker-position pre-A))
+                     (cperl-indent-line)
+                     (forward-line 1))
+                   (goto-char (marker-position pre-A))
+                   (if B-comment
+                       (progn
+                         (forward-line -1)
+                         (indent-for-comment)
+                         (goto-char (marker-position pre-A)))))
+               (error "`%s' (EXPR) not with an {BLOCK}" if-string)))
+         ;; (error "`%s' not with an (EXPR)" if-string)
+         (forward-sexp -1)
+         (cperl-invert-if-unless-modifiers)))
+    ;;(error "Not at `if', `unless', `while', `until', `for' or `foreach'")
+    (cperl-invert-if-unless-modifiers)))
 
 ;;; By Anthony Foiani <afoiani@uswest.com>
 ;;; Getting help on modules in C-h f ?
@@ -9466,6 +10070,47 @@ We suppose that the regexp is scanned already."
         (setq flist (cdr flist))))
     command))
 
+
+(defun cperl-next-interpolated-REx-1 ()
+  "Move point to next REx which has interpolated parts without //o.
+Skips RExes consisting of one interpolated variable.
+
+Note that skipped RExen are not performance hits."
+  (interactive "")
+  (cperl-next-interpolated-REx 1))
+
+(defun cperl-next-interpolated-REx-0 ()
+  "Move point to next REx which has interpolated parts without //o."
+  (interactive "")
+  (cperl-next-interpolated-REx 0))
+
+(defun cperl-next-interpolated-REx (&optional skip beg limit)
+  "Move point to next REx which has interpolated parts.
+SKIP is a list of possible types to skip, BEG and LIMIT are the starting
+point and the limit of search (default to point and end of buffer).
+
+SKIP may be a number, then it behaves as list of numbers up to SKIP; this
+semantic may be used as a numeric argument.
+
+Types are 0 for / $rex /o (interpolated once), 1 for /$rex/ (if $rex is
+a result of qr//, this is not a performance hit), t for the rest."
+  (interactive "P")
+  (if (numberp skip) (setq skip (list 0 skip)))
+  (or beg (setq beg (point)))
+  (or limit (setq limit (point-max)))  ; needed for n-s-p-c
+  (let (pp)
+    (and (eq (get-text-property beg 'syntax-type) 'string)
+        (setq beg (next-single-property-change beg 'syntax-type nil limit)))
+    (cperl-map-pods-heres
+     (function (lambda (s e p)
+                (if (memq (get-text-property s 'REx-interpolated) skip)
+                    t
+                  (setq pp s)
+                  nil)))       ; nil stops
+     'REx-interpolated beg limit)
+    (if pp (goto-char pp)
+      (message "No more interpolated REx"))))
+
 ;;; Initial version contributed by Trey Belew
 (defun cperl-here-doc-spell (&optional beg end)
   "Spell-check HERE-documents in the Perl buffer.
@@ -9786,7 +10431,7 @@ do extra unwind via `cperl-unwind-to-safe'."
          (cperl-fontify-syntaxically to)))))
 
 (defvar cperl-version
-  (let ((v  "$Revision: 5.16 $"))
+  (let ((v  "$Revision: 5.23 $"))
     (string-match ":\\s *\\([0-9.]+\\)" v)
     (substring v (match-beginning 1) (match-end 1)))
   "Version of IZ-supported CPerl package this file is based on.")