unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
From: Ivan Andrus <darthandrus@gmail.com>
To: Alan Mackenzie <acm@muc.de>
Cc: 15212@debbugs.gnu.org
Subject: bug#15212: 24.3.50; c++-mode doesn't support raw string literals
Date: Wed, 8 Jun 2016 19:38:01 -0600	[thread overview]
Message-ID: <8DEAEEEE-145C-4884-AC63-9934236A698A@gmail.com> (raw)
In-Reply-To: <20160606163203.GA19322@acm.fritz.box>

I have been in a lot of meetings so I haven’t given it the normal usage treatment, but I did spend some time trying to break it. 

You may know about this, but if you comment the first line of a multi-line string, the closing quote will still match (for the purposes of backward-sexp) with the commented opening quote.  The parentheses on the other hand don't match (which is what I would expect).  Personally, I think it’s a small price to pay.

Thanks again for your work on this.  I’ll keep testing it, but as far as I’m concerned you can push it as soon as you want.

-Ivan

> On Jun 6, 2016, at 10:32 AM, Alan Mackenzie <acm@muc.de> wrote:
> 
> Hello again, Ivan.
> 
> On Thu, Jun 02, 2016 at 04:07:41PM +0000, Alan Mackenzie wrote:
> 
> [ .... ]
> 
>> It is not yet a workable patch, since it fails to take proper account of
>> macros and comments.  Indeed, the fontification fails when the raw string
>> is inside a macro.  CC Mode has become somewhat unwieldy in this area,
>> and I'll be working on it in the next few days.
> 
>> Until then .....
> 
> In this Email is a patch which does support macros, and (at least to
> some extent) comments.  If there is an unbalanced raw string opener
> inside a macro, the rest of the macro gets string face, but the text
> after the macro should be unaffected by it.
> 
> The patch should be quite close to release condition.  As always, it
> should apply cleanly to the savannah master branch.  Again, as always,
> after applying the patch, please recompile (at least) cc-langs.el,
> cc-fonts.el, cc-engine.el, and cc-mode.el
> 
> Could you try it in your real code, please, and if you have time, try
> and break it.  I'm enclosing the current edition of my test file again.
> I look forward to hearing back from you.
> 
> 
> 
> diff -r d83a74c6ec31 cc-engine.el
> --- a/cc-engine.el	Sun May 29 11:59:26 2016 +0000
> +++ b/cc-engine.el	Mon Jun 06 16:15:05 2016 +0000
> @@ -85,8 +85,9 @@
> ;;
> ;; 'syntax-table
> ;;   Used to modify the syntax of some characters.  It is used to
> -;;   mark the "<" and ">" of angle bracket parens with paren syntax, and
> -;;   to "hide" obtrusive characters in preprocessor lines.
> +;;   mark the "<" and ">" of angle bracket parens with paren syntax, to
> +;;   "hide" obtrusive characters in preprocessor lines, and to mark C++
> +;;   raw strings to enable their fontification.
> ;;
> ;;   This property is used on single characters and is therefore
> ;;   always treated as front and rear nonsticky (or start and end open
> @@ -2295,7 +2296,8 @@
>   ;;     (STATE TYPE (BEG . END))     if TO is in a literal; or
>   ;;     (STATE)                      otherwise,
>   ;; where STATE is the parsing state at TO, TYPE is the type of the literal
> -  ;; (one of 'c, 'c++, 'string) and (BEG . END) is the boundaries of the literal.
> +  ;; (one of 'c, 'c++, 'string) and (BEG . END) is the boundaries of the literal,
> +  ;; including the delimiters.
>   ;;
>   ;; Unless NOT-IN-DELIMITER is non-nil, when TO is inside a two-character
>   ;; comment opener, this is recognized as being in a comment literal.
> @@ -5673,6 +5675,9 @@
> ;; Set by c-common-init in cc-mode.el.
> (defvar c-new-BEG)
> (defvar c-new-END)
> +;; Set by c-after-change in cc-mode.el.
> +(defvar c-old-BEG)
> +(defvar c-old-END)
> 
> (defun c-before-change-check-<>-operators (beg end)
>   ;; Unmark certain pairs of "< .... >" which are currently marked as
> @@ -5793,6 +5798,329 @@
> 				       'c-decl-arg-start)))))))
>       (or (c-forward-<>-arglist nil)
> 	  (forward-char)))))
> +
> +\f
> +;; Functions to handle C++ raw strings.
> +;;
> +;; A valid C++ raw string looks like
> +;;     R"<id>(<contents>)<id>"
> +;; , where <id> is an identifier from 0 to 16 characters long, not containing
> +;; spaces, control characters, double quote or left/right paren.  <contents>
> +;; can include anything which isn't the terminating )<id>", including new
> +;; lines, "s, parentheses, etc.
> +;;
> +;; CC Mode handles C++ raw strings by the use of `syntax-table' text
> +;; properties as follows:
> +;;
> +;; (i) On a validly terminated raw string, no `syntax-table' text properties
> +;;   are applied to the opening and closing delimiters, but any " in the
> +;;   contents is given the property value "punctuation" (`(1)') to prevent it
> +;;   interacting with the "s in the delimiters.
> +;;
> +;;   The font locking routine `c-font-lock-c++-raw-strings' (in cc-fonts.el)
> +;;   recognizes valid raw strings, and fontifies the delimiters (apart from
> +;;   the parentheses) with the default face and the parentheses and the
> +;;   <contents> with font-lock-string-face.
> +;;
> +;; (ii) A valid, but unterminated, raw string opening delimiter gets the
> +;;   "punctuation" value (`(1)') of the `syntax-table' text property, and the
> +;;   open parenthesis gets the "string fence" value (`(15)').
> +;;
> +;;   `c-font-lock-c++-raw-strings' puts c-font-lock-warning-face on the entire
> +;;   unmatched opening delimiter (from the R up to the open paren), and allows
> +;;   the rest of the buffer to get font-lock-string-face, caused by the
> +;;   unmatched "string fence" `syntax-table' text property value.
> +;;
> +;; (iii) Inside a macro, a valid raw string is handled as in (i).  An
> +;;   unmatched opening delimiter is handled slightly differently.  In addition
> +;;   to the "punctuation" and "string fence" properties on the delimiter,
> +;;   another "string fence" `syntax-table' property is applied to the last
> +;;   possible character of the macro before the terminating linefeed (if there
> +;;   is such a character after the "(").  This "last possible" character is
> +;;   never a backslash escaping the end of line.  If the character preceding
> +;;   this "last possible" character is itself a backslash, this preceding
> +;;   character gets a "punctuation" `syntax-table' value.  If the "(" is
> +;;   already at the end of the macro, it gets the "punctuaion" value, and no
> +;;   "string fence"s are used.
> +;;
> +;;   The effect on the fontification of either of these tactics is that rest of
> +;;   the macro (if any) after the "(" gets font-lock-string-face, but the rest
> +;;   of the file is fontified normally.
> +
> +
> +(defun c-raw-string-pos ()
> +  ;; Get POINT's relationship to any containing raw string.
> +  ;; If point isn't in a raw string, return nil.
> +  ;; Otherwise, return the following list:
> +  ;;
> +  ;;   (POS B\" B\( E\) E\")
> +  ;;
> +  ;; , where POS is the symbol `open-delim' if point is in the opening
> +  ;; delimiter, the symbol `close-delim' if it's in the closing delimiter, and
> +  ;; nil if it's in the string body.  B\", B\(, E\), E\" are the positions of
> +  ;; the opening and closing quotes and parentheses of a correctly terminated
> +  ;; raw string.  (N.B.: E\) and E\" are NOT on the "outside" of these
> +  ;; characters.)  If the raw string is not terminated, E\) and E\" are set to
> +  ;; nil.
> +  ;;
> +  ;; Note: this routine is dependant upon the correct syntax-table text
> +  ;; properties being set.
> +  (let* ((safe (c-state-semi-safe-place (point)))
> +	 (state (c-state-pp-to-literal safe (point)))
> +	 open-quote-pos open-paren-pos close-paren-pos close-quote-pos id)
> +    (save-excursion
> +      (when
> +	  (and
> +	   (cond
> +	    ((null (cadr state))
> +	     (or (eq (char-after) ?\")
> +		 (search-backward "\"" (max (- (point) 17) (point-min)) t)))
> +	    ((and (eq (cadr state) 'string)
> +		  (goto-char (car (nth 2 state)))
> +		  (or (eq (char-after) ?\")
> +		      (search-backward "\"" (max (- (point) 17) (point-min)) t))
> +		  (not (bobp)))))
> +	   (eq (char-before) ?R)
> +	   (looking-at "\"\\([^ ()\\\n\r\t]\\{,16\\}\\)("))
> +	(setq open-quote-pos (point)
> +	      open-paren-pos (match-end 1)
> +	      id (match-string-no-properties 1))
> +	(goto-char (1+ open-paren-pos))
> +	(when (and (not (c-get-char-property open-paren-pos 'syntax-table))
> +		   (search-forward (concat ")" id "\"") nil t))
> +	  (setq close-paren-pos (match-beginning 0)
> +		close-quote-pos (1- (point))))))
> +    (and open-quote-pos
> +	 (list
> +	  (cond
> +	   ((<= (point) open-paren-pos)
> +	    'open-delim)
> +	   ((and close-paren-pos
> +		 (> (point) close-paren-pos))
> +	    'close-delim)
> +	   (t nil))
> +	  open-quote-pos open-paren-pos close-paren-pos close-quote-pos))))
> +
> +(defun c-depropertize-raw-string (id open-quote open-paren bound)
> +  ;; Point is immediately after a raw string opening delimiter.  Remove any
> +  ;; `syntax-table' text properties associated with the delimiter (if its
> +  ;; unmatched) or the raw string.
> +  ;;
> +  ;; ID, a string, is the delimiter's identifier.  OPEN-QUOTE and OPEN-PAREN
> +  ;; are the buffer positions of the delimiter's components.  BOUND is the
> +  ;; bound for searching for a matching closing delimiter; it is usually nil,
> +  ;; but if we're inside a macro, it's the end of the macro.
> +  ;;
> +  ;; Point is moved to after the (terminated) raw string, or left after the
> +  ;; unmatched opening delimiter, as the case may be.  The return value is of
> +  ;; no significance.
> +  (let ((open-paren-prop (c-get-char-property open-paren 'syntax-table)))
> +    (cond
> +     ((null open-paren-prop)
> +      ;; A terminated raw string
> +      (if (search-forward (concat ")" id "\"") nil t)
> +	  (c-clear-char-property-with-value
> +	   (1+ open-paren) (match-beginning 0) 'syntax-table '(1))))
> +     ((or (and (equal open-paren-prop '(15)) (null bound))
> +	  (equal open-paren-prop '(1)))
> +      ;; An unterminated raw string either not in a macro, or in a macro with
> +      ;; the open parenthesis right up against the end of macro
> +      (c-clear-char-property open-quote 'syntax-table)
> +      (c-clear-char-property open-paren 'syntax-table))
> +     (t
> +      ;; An unterminated string in a macro, with at least one char after the
> +      ;; open paren
> +      (c-clear-char-property open-quote 'syntax-table)
> +      (c-clear-char-property open-paren 'syntax-table)
> +      (let ((string-fence-pos
> +	     (save-excursion
> +	       (goto-char (1+ open-paren))
> +	       (c-search-forward-char-property 'syntax-table '(15) bound))))
> +	(when string-fence-pos
> +	  (c-clear-char-property string-fence-pos 'syntax-table)))
> +      ))))
> +
> +(defun c-depropertize-raw-strings-in-region (start finish)
> +  ;; Remove any `syntax-table' text properties associated with C++ raw strings
> +  ;; contained in the region (START FINISH).  Point is undefined at entry and
> +  ;; exit, and the return value has no significance.
> +  (goto-char start)
> +  (while (and (< (point) finish)
> +	      (re-search-forward
> +	       (concat "\\("				     ; 1
> +		       c-anchored-cpp-prefix		     ; 2
> +		       "\\)\\|\\("			     ; 3
> +		       "R\"\\([^ ()\\\n\r\t]\\{,16\\}\\)("   ; 4
> +		       "\\)")
> +	       finish t))
> +    (when (save-excursion
> +	    (goto-char (match-beginning 0)) (not (c-in-literal)))
> +      (if (match-beginning 4)		; the id
> +	  ;; We've found a raw string
> +	  (c-depropertize-raw-string
> +	   (match-string-no-properties 4) ; id
> +	   (1+ (match-beginning 3))	  ; open quote
> +	   (match-end 4)		  ; open paren
> +	   nil)				  ; bound
> +	;; We've found a CPP construct.  Search for raw strings within it.
> +	(goto-char (match-beginning 2)) ; the "#"
> +	(c-end-of-macro)
> +	(let ((eom (point)))
> +	  (goto-char (match-end 2))	; after the "#".
> +	  (while (and (< (point) eom)
> +		      (c-syntactic-re-search-forward
> +		       "R\"\\([^ ()\\\n\r\t]\\{,16\\}\\)(" eom t))
> +	    (c-depropertize-raw-string
> +	     (match-string-no-properties 1) ; id
> +	     (1+ (match-beginning 0))	    ; open quote
> +	     (match-end 1)		    ; open paren
> +	     eom)))))))			    ; bound.
> +
> +(defun c-before-change-check-c++-raw-strings (beg end)
> +  ;; This function clears `syntax-table' text properties from C++ raw strings
> +  ;; in the region (c-new-BEG c-new-END).  BEG and END are the standard
> +  ;; arguments supplied to any before-change function.
> +  ;;
> +  ;; Point is undefined on both entry and exit, and the return value has no
> +  ;; significance.
> +  ;;
> +  ;; This function is called as a before-change function solely due to its
> +  ;; membership of the C++ value of `c-get-state-before-change-functions'.
> +  (c-save-buffer-state
> +      ((beg-rs (progn (goto-char beg) (c-raw-string-pos)))
> +       (beg-plus (if (null beg-rs)
> +		     beg
> +		   (max beg
> +			(1+ (or (nth 4 beg-rs) (nth 2 beg-rs))))))
> +       (end-rs (progn (goto-char end) (c-raw-string-pos))) ; FIXME!!!
> +					; Optimize this so that we don't call
> +					; `c-raw-string-pos' twice when once
> +					; will do.  (2016-06-02).
> +       (end-minus (if (null end-rs)
> +		      end
> +		    (min end (cadr end-rs))))
> +       )
> +    (when beg-rs
> +      (setq c-new-BEG (min c-new-BEG (1- (cadr beg-rs)))))
> +    (c-depropertize-raw-strings-in-region c-new-BEG beg-plus)
> +
> +    (when end-rs
> +      (setq c-new-END (max c-new-END
> +			   (1+ (or (nth 4 end-rs)
> +				   (nth 2 end-rs))))))
> +    (c-depropertize-raw-strings-in-region end-minus c-new-END)))
> +
> +(defun c-propertize-raw-string-opener (id open-quote open-paren bound)
> +  ;; Point is immediately after a raw string opening delimiter.  Apply any
> +  ;; pertinent `syntax-table' text properties to the delimiter and also the
> +  ;; raw string, should there be a valid matching closing delimiter.
> +  ;;
> +  ;; ID, a string, is the delimiter's identifier.  OPEN-QUOTE and OPEN-PAREN
> +  ;; are the buffer positions of the delimiter's components.  BOUND is the
> +  ;; bound for searching for a matching closing delimiter; it is usually nil,
> +  ;; but if we're inside a macro, it's the end of the macro.
> +  ;;
> +  ;; Point is moved to after the (terminated) raw string, or left after the
> +  ;; unmatched opening delimiter, as the case may be.  The return value is of
> +  ;; no significance.
> +  (if (search-forward (concat ")" id "\"") bound t)
> +      (let ((end-string (match-beginning 0))
> +	    (after-quote (match-end 0))
> +	    )
> +	(goto-char open-paren)
> +	(while (progn (skip-syntax-forward "^\"" end-string)
> +		      (< (point) end-string))
> +	  (c-put-char-property (point) 'syntax-table '(1)) ; punctuation
> +	  (forward-char))
> +	(goto-char after-quote))
> +    (c-put-char-property open-quote 'syntax-table '(1))	     ; punctuation
> +    (c-put-char-property open-paren 'syntax-table '(15))     ; generic string
> +    (when bound
> +      ;; In a CPP construct, we try to apply a generic-string `syntax-table'
> +      ;; text property to the last possible character in the string, so that
> +      ;; only characters within the macro get "stringed out".
> +      (goto-char bound)
> +      (if (save-restriction
> +	    (narrow-to-region (1+ open-paren) (point-max))
> +	    (re-search-backward
> +	     (eval-when-compile
> +	       (concat "\\("		; 1
> +		       "\\(\\`[^\\]?\\|[^\\][^\\]\\)\\(\\\\\\(.\\|\n\\)\\)*" ; 2-4
> +		       "\\(\\\\.\\)"	; 5
> +		       "\\|"
> +		       "\\(\\`\\|[^\\]\\|\\(\\`[^\\]?\\|[^\\][^\\]\\)\\(\\\\\\(.\\|\n\\)\\)+\\)" ; 6-9
> +		       "\\([^\\]\\)"	; 10
> +		       "\\)"
> +		       "\\(\\\\\n\\)*\\=")) ; 11
> +             (1+ open-paren) t))
> +	  (if (match-beginning 10)
> +	      (c-put-char-property (match-beginning 10) 'syntax-table '(15))
> +	    (c-put-char-property (match-beginning 5) 'syntax-table '(1))
> +	    (c-put-char-property (1+ (match-beginning 5)) 'syntax-table '(15)))
> +	(c-put-char-property open-paren 'syntax-table '(1)))
> +
> +								; )
> +      (goto-char bound))))
> +
> +(defun c-after-change-re-mark-raw-strings (beg end old-len)
> +  ;; This function applies `syntax-table' text properties to C++ raw strings
> +  ;; beginning in the region (c-new-BEG c-new-END).  BEG, END, and OLD-LEN are
> +  ;; the standard arguments supplied to any after-change function.
> +  ;;
> +  ;; Point is undefined on both entry and exit, and the return value has no
> +  ;; significance.
> +  ;; 
> +  ;; This function is called as an after-change function solely due to its
> +  ;; membership of the C++ value of `c-before-font-lock-functions'.
> +  (c-save-buffer-state ()
> +    ;; If the region (c-new-BEG c-new-END) has expanded, remove
> +    ;; `syntax-table' text-properties from the new piece(s).
> +    (when (< c-new-BEG c-old-BEG)
> +      (let ((beg-rs (progn (goto-char c-old-BEG) (c-raw-string-pos))))
> +	(c-depropertize-raw-strings-in-region
> +	 c-new-BEG
> +	 (if beg-rs
> +	     (1+ (or (nth 4 beg-rs) (nth 2 beg-rs)))
> +	   c-old-BEG))))
> +    (when (> c-new-END c-old-END)
> +      (let ((end-rs (progn (goto-char c-old-END) (c-raw-string-pos))))
> +	(c-depropertize-raw-strings-in-region
> +	 (if end-rs
> +	     (cadr end-rs)
> +	   c-old-END)
> +	 c-new-END)))
> +    (goto-char c-new-BEG)
> +    (while (and (< (point) c-new-END)
> +		(re-search-forward
> +		 (concat "\\("				       ; 1
> +			 c-anchored-cpp-prefix		       ; 2
> +			 "\\)\\|\\("			       ; 3
> +			 "R\"\\([^ ()\\\n\r\t]\\{,16\\}\\)("   ; 4
> +			 "\\)")
> +		 c-new-END t))
> +      (when (save-excursion
> +	      (goto-char (match-beginning 0)) (not (c-in-literal)))
> +	(if (match-beginning 4)		; the id
> +	    ;; We've found a raw string.
> +	    (c-propertize-raw-string-opener
> +	     (match-string-no-properties 4) ; id
> +	     (1+ (match-beginning 3))	    ; open quote
> +	     (match-end 4)		    ; open paren
> +	     nil)			    ; bound
> +	  ;; We've found a CPP construct.  Search for raw strings within it.
> +	  (goto-char (match-beginning 2)) ; the "#"
> +	  (c-end-of-macro)
> +	  (let ((eom (point)))
> +	    (goto-char (match-end 2))	; after the "#".
> +	    (while (and (< (point) eom)
> +			(c-syntactic-re-search-forward
> +			 "R\"\\([^ ()\\\n\r\t]\\{,16\\}\\)(" eom t))
> +	      (c-propertize-raw-string-opener
> +	       (match-string-no-properties 1) ; id
> +	       (1+ (match-beginning 0))	      ; open quote
> +	       (match-end 1)		      ; open paren
> +	       eom))))))))		      ; bound
> +
> 
> ;; Handling of small scale constructs like types and names.
> 
> diff -r d83a74c6ec31 cc-fonts.el
> --- a/cc-fonts.el	Sun May 29 11:59:26 2016 +0000
> +++ b/cc-fonts.el	Mon Jun 06 16:15:05 2016 +0000
> @@ -717,6 +717,10 @@
> 	(concat ".\\(" c-string-limit-regexp "\\)")
> 	'((c-font-lock-invalid-string)))
> 
> +      ;; Fontify C++ raw strings.
> +      ,@(when (c-major-mode-is 'c++-mode)
> +	  '(c-font-lock-c++-raw-strings))
> +
>       ;; Fontify keyword constants.
>       ,@(when (c-lang-const c-constant-kwds)
> 	  (let ((re (c-make-keywords-re nil (c-lang-const c-constant-kwds))))
> @@ -1572,6 +1576,44 @@
> 	    (c-forward-syntactic-ws)
> 	    (c-font-lock-declarators limit t in-typedef)))))))
> 
> +(defun c-font-lock-c++-raw-strings (limit)
> +  ;; Fontify C++ raw strings.
> +  ;;
> +  ;; This function will be called from font-lock for a region bounded by POINT
> +  ;; and LIMIT, as though it were to identify a keyword for
> +  ;; font-lock-keyword-face.  It always returns NIL to inhibit this and
> +  ;; prevent a repeat invocation.  See elisp/lispref page "Search-based
> +  ;; Fontification".
> +  (while (search-forward-regexp
> +	  "R\\(\"\\)\\([^ ()\\\n\r\t]\\{,16\\}\\)(" limit t)
> +    (when ;; (eq (c-get-char-property (1- (point)) 'face)
> +	;;     'font-lock-string-face)
> +	(or (and (eobp)
> +		 (eq (c-get-char-property (1- (point)) 'face)
> +		     'font-lock-warning-face))
> +	    (eq (c-get-char-property (point) 'face) 'font-lock-string-face)
> +	    (and (equal (c-get-char-property (match-end 2) 'syntax-table) '(1))
> +		 (equal (c-get-char-property (match-beginning 1) 'syntax-table)
> +			'(1))))
> +      (let ((paren-prop (c-get-char-property (1- (point)) 'syntax-table)))
> +	(if paren-prop
> +	    (progn
> +	      (c-put-font-lock-face (match-beginning 0) (match-end 0)
> +				    'font-lock-warning-face)
> +	      (when
> +		  (and
> +		   (equal paren-prop '(15))
> +		   (not (c-search-forward-char-property 'syntax-table '(15) limit)))
> +		(goto-char limit)))
> +	  (c-put-font-lock-face (match-beginning 1) (match-end 2) 'default)
> +	  (when (search-forward-regexp
> +		 (concat ")\\(" (regexp-quote (match-string-no-properties 2))
> +			 "\\)\"")
> +		 limit t)
> +	    (c-put-font-lock-face (match-beginning 1) (point)
> +				  'default))))))
> +  nil)
> +
> (c-lang-defconst c-simple-decl-matchers
>   "Simple font lock matchers for types and declarations.  These are used
> on level 2 only and so aren't combined with `c-complex-decl-matchers'."
> diff -r d83a74c6ec31 cc-langs.el
> --- a/cc-langs.el	Sun May 29 11:59:26 2016 +0000
> +++ b/cc-langs.el	Mon Jun 06 16:15:05 2016 +0000
> @@ -457,9 +457,12 @@
>   ;; The value here may be a list of functions or a single function.
>   t nil
>   c++ '(c-extend-region-for-CPP
> +	c-before-change-check-c++-raw-strings
> 	c-before-change-check-<>-operators
> +	c-depropertize-CPP
> 	c-invalidate-macro-cache)
>   (c objc) '(c-extend-region-for-CPP
> +	     c-depropertize-CPP
> 	     c-invalidate-macro-cache)
>   ;; java 'c-before-change-check-<>-operators
>   awk 'c-awk-record-region-clear-NL)
> @@ -493,6 +496,7 @@
> 	     c-neutralize-syntax-in-and-mark-CPP
> 	     c-change-expand-fl-region)
>   c++ '(c-extend-font-lock-region-for-macros
> +	c-after-change-re-mark-raw-strings
> 	c-neutralize-syntax-in-and-mark-CPP
> 	c-restore-<>-properties
> 	c-change-expand-fl-region)
> diff -r d83a74c6ec31 cc-mode.el
> --- a/cc-mode.el	Sun May 29 11:59:26 2016 +0000
> +++ b/cc-mode.el	Mon Jun 06 16:15:05 2016 +0000
> @@ -649,6 +649,14 @@
> (make-variable-buffer-local 'c-new-BEG)
> (defvar c-new-END 0)
> (make-variable-buffer-local 'c-new-END)
> +;; The following two variables record the values of `c-new-BEG' and
> +;; `c-new-END' just after `c-new-END' has been adjusted for the length of text
> +;; inserted or removed.  They may be read by any after-change function (but
> +;; should not be altered by one).
> +(defvar c-old-BEG 0)
> +(make-variable-buffer-local 'c-old-BEG)
> +(defvar c-old-END 0)
> +(make-variable-buffer-local 'c-old-END)
> 
> (defun c-common-init (&optional mode)
>   "Common initialization for all CC Mode modes.
> @@ -859,6 +867,31 @@
>   (memq (cadr (backtrace-frame 3))
> 	'(put-text-property remove-list-of-text-properties)))
> 
> +(defun c-depropertize-CPP (beg end)
> +  ;; Remove the punctuation syntax-table text property from the CPP parts of
> +  ;; (c-new-BEG c-new-END).
> +  ;;
> +  ;; This function is in the C/C++/ObjC values of
> +  ;; `c-get-state-before-change-functions' and is called exclusively as a
> +  ;; before change function.
> +  (goto-char c-new-BEG)
> +  (while (and (< (point) beg)
> +	      (search-forward-regexp c-anchored-cpp-prefix beg t))
> +    (goto-char (match-beginning 1))
> +    (let ((m-beg (point)))
> +      (c-end-of-macro)
> +      (c-clear-char-property-with-value
> +       m-beg (min (point) beg) 'syntax-table '(1))))
> +
> +  (goto-char end)
> +  (while (and (< (point) c-new-END)
> +	      (search-forward-regexp c-anchored-cpp-prefix c-new-END t))
> +    (goto-char (match-beginning 1))
> +    (let ((m-beg (point)))
> +      (c-end-of-macro)
> +      (c-clear-char-property-with-value
> +       m-beg (min (point) c-new-END) 'syntax-table '(1)))))
> +
> (defun c-extend-region-for-CPP (beg end)
>   ;; Adjust `c-new-BEG', `c-new-END' respectively to the beginning and end of
>   ;; any preprocessor construct they may be in. 
> @@ -949,9 +982,9 @@
>   ;; Note: SPEED _MATTERS_ IN THIS FUNCTION!!!
>   ;;
>   ;; This function might make hidden buffer changes.
> -  (c-save-buffer-state (limits )
> +  (c-save-buffer-state (limits)
>     ;; Clear 'syntax-table properties "punctuation":
> -    (c-clear-char-property-with-value c-new-BEG c-new-END 'syntax-table '(1))
> +    ;; (c-clear-char-property-with-value c-new-BEG c-new-END 'syntax-table '(1))
> 
>     ;; CPP "comment" markers:
>     (if (memq 'category-properties c-emacs-features) ; GNU Emacs.
> @@ -1101,8 +1134,8 @@
> 
>   ;; (c-new-BEG c-new-END) will be the region to fontify.  It may become
>   ;; larger than (beg end).
> -  ;; (setq c-new-BEG beg  c-new-END end)
>   (setq c-new-END (- (+ c-new-END (- end beg)) old-len))
> +  (setq c-old-BEG c-new-BEG  c-old-END c-new-END)
> 
>   (unless (c-called-from-text-property-change-p)
>     (setq c-just-done-before-change nil)
> 
> 
> 
>>> -Ivan
> 
> -- 
> Alan Mackenzie (Nuremberg, Germany).
> 
> <raw-string.cc>






  parent reply	other threads:[~2016-06-09  1:38 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-08-29 21:00 bug#15212: 24.3.50; c++-mode doesn't support raw string literals Ivan Andrus
2016-03-30  3:14 ` Ivan Andrus
2016-04-03 18:36   ` Alan Mackenzie
2016-05-24 17:12     ` Ivan Andrus
2016-05-28 14:40       ` Alan Mackenzie
2016-05-29 21:36         ` Alan Mackenzie
2016-05-31 14:22           ` Ivan Andrus
2016-05-31 21:32             ` Alan Mackenzie
2016-05-31 23:52               ` Michael Welsh Duggan
2016-06-02 16:36                 ` Alan Mackenzie
2016-05-31 22:21             ` Alan Mackenzie
2016-06-01  5:21               ` Ivan Andrus
2016-06-02 16:07                 ` Alan Mackenzie
     [not found]                 ` <20160602160741.GC4067@acm.fritz.box>
2016-06-06 16:32                   ` Alan Mackenzie
     [not found]                   ` <20160606163203.GA19322@acm.fritz.box>
2016-06-07 22:06                     ` Michael Welsh Duggan
2016-06-07 22:21                       ` Alan Mackenzie
2016-06-09  1:38                     ` Ivan Andrus [this message]
2016-06-09 15:04                       ` Alan Mackenzie
2016-06-09 15:06   ` Alan Mackenzie

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=8DEAEEEE-145C-4884-AC63-9934236A698A@gmail.com \
    --to=darthandrus@gmail.com \
    --cc=15212@debbugs.gnu.org \
    --cc=acm@muc.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).