aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMattias EngdegÄrd2022-06-02 11:46:18 +0200
committerMattias EngdegÄrd2022-06-02 16:57:02 +0200
commit52e527a02f40686f355d18ab2ba2d1d7c9fa0fbc (patch)
tree9ab242f73ebfc7c55bc93ea89dc986bc248548e6
parent4bacd2a64575ccd55fd9ef8b4648f440243d597a (diff)
downloademacs-52e527a02f40686f355d18ab2ba2d1d7c9fa0fbc.tar.gz
emacs-52e527a02f40686f355d18ab2ba2d1d7c9fa0fbc.zip
Make ?\LF generate 10, not -1 (bug#55738)
The old -1 value was an artefact of the reader implementation. * src/lread.c (read_escape): Remove the `stringp` argument; assume character literal syntax. Never return -1. (read_string_literal): Handle string-specific escape semantics here and simplify. * test/src/lread-tests.el (lread-escaped-lf): New test.
-rw-r--r--src/lread.c60
-rw-r--r--test/src/lread-tests.el5
2 files changed, 34 insertions, 31 deletions
diff --git a/src/lread.c b/src/lread.c
index 52fc0fff307..4b7d38a8e6c 100644
--- a/src/lread.c
+++ b/src/lread.c
@@ -2633,7 +2633,7 @@ enum { UNICODE_CHARACTER_NAME_LENGTH_BOUND = 200 };
2633 If the escape sequence forces unibyte, return eight-bit char. */ 2633 If the escape sequence forces unibyte, return eight-bit char. */
2634 2634
2635static int 2635static int
2636read_escape (Lisp_Object readcharfun, bool stringp) 2636read_escape (Lisp_Object readcharfun)
2637{ 2637{
2638 int c = READCHAR; 2638 int c = READCHAR;
2639 /* \u allows up to four hex digits, \U up to eight. Default to the 2639 /* \u allows up to four hex digits, \U up to eight. Default to the
@@ -2663,12 +2663,6 @@ read_escape (Lisp_Object readcharfun, bool stringp)
2663 return '\t'; 2663 return '\t';
2664 case 'v': 2664 case 'v':
2665 return '\v'; 2665 return '\v';
2666 case '\n':
2667 return -1;
2668 case ' ':
2669 if (stringp)
2670 return -1;
2671 return ' ';
2672 2666
2673 case 'M': 2667 case 'M':
2674 c = READCHAR; 2668 c = READCHAR;
@@ -2676,7 +2670,7 @@ read_escape (Lisp_Object readcharfun, bool stringp)
2676 error ("Invalid escape character syntax"); 2670 error ("Invalid escape character syntax");
2677 c = READCHAR; 2671 c = READCHAR;
2678 if (c == '\\') 2672 if (c == '\\')
2679 c = read_escape (readcharfun, 0); 2673 c = read_escape (readcharfun);
2680 return c | meta_modifier; 2674 return c | meta_modifier;
2681 2675
2682 case 'S': 2676 case 'S':
@@ -2685,7 +2679,7 @@ read_escape (Lisp_Object readcharfun, bool stringp)
2685 error ("Invalid escape character syntax"); 2679 error ("Invalid escape character syntax");
2686 c = READCHAR; 2680 c = READCHAR;
2687 if (c == '\\') 2681 if (c == '\\')
2688 c = read_escape (readcharfun, 0); 2682 c = read_escape (readcharfun);
2689 return c | shift_modifier; 2683 return c | shift_modifier;
2690 2684
2691 case 'H': 2685 case 'H':
@@ -2694,7 +2688,7 @@ read_escape (Lisp_Object readcharfun, bool stringp)
2694 error ("Invalid escape character syntax"); 2688 error ("Invalid escape character syntax");
2695 c = READCHAR; 2689 c = READCHAR;
2696 if (c == '\\') 2690 if (c == '\\')
2697 c = read_escape (readcharfun, 0); 2691 c = read_escape (readcharfun);
2698 return c | hyper_modifier; 2692 return c | hyper_modifier;
2699 2693
2700 case 'A': 2694 case 'A':
@@ -2703,19 +2697,19 @@ read_escape (Lisp_Object readcharfun, bool stringp)
2703 error ("Invalid escape character syntax"); 2697 error ("Invalid escape character syntax");
2704 c = READCHAR; 2698 c = READCHAR;
2705 if (c == '\\') 2699 if (c == '\\')
2706 c = read_escape (readcharfun, 0); 2700 c = read_escape (readcharfun);
2707 return c | alt_modifier; 2701 return c | alt_modifier;
2708 2702
2709 case 's': 2703 case 's':
2710 c = READCHAR; 2704 c = READCHAR;
2711 if (stringp || c != '-') 2705 if (c != '-')
2712 { 2706 {
2713 UNREAD (c); 2707 UNREAD (c);
2714 return ' '; 2708 return ' ';
2715 } 2709 }
2716 c = READCHAR; 2710 c = READCHAR;
2717 if (c == '\\') 2711 if (c == '\\')
2718 c = read_escape (readcharfun, 0); 2712 c = read_escape (readcharfun);
2719 return c | super_modifier; 2713 return c | super_modifier;
2720 2714
2721 case 'C': 2715 case 'C':
@@ -2726,7 +2720,7 @@ read_escape (Lisp_Object readcharfun, bool stringp)
2726 case '^': 2720 case '^':
2727 c = READCHAR; 2721 c = READCHAR;
2728 if (c == '\\') 2722 if (c == '\\')
2729 c = read_escape (readcharfun, 0); 2723 c = read_escape (readcharfun);
2730 if ((c & ~CHAR_MODIFIER_MASK) == '?') 2724 if ((c & ~CHAR_MODIFIER_MASK) == '?')
2731 return 0177 | (c & CHAR_MODIFIER_MASK); 2725 return 0177 | (c & CHAR_MODIFIER_MASK);
2732 else if (! ASCII_CHAR_P ((c & ~CHAR_MODIFIER_MASK))) 2726 else if (! ASCII_CHAR_P ((c & ~CHAR_MODIFIER_MASK)))
@@ -3011,7 +3005,7 @@ read_char_literal (Lisp_Object readcharfun)
3011 } 3005 }
3012 3006
3013 if (ch == '\\') 3007 if (ch == '\\')
3014 ch = read_escape (readcharfun, 0); 3008 ch = read_escape (readcharfun);
3015 3009
3016 int modifiers = ch & CHAR_MODIFIER_MASK; 3010 int modifiers = ch & CHAR_MODIFIER_MASK;
3017 ch &= ~CHAR_MODIFIER_MASK; 3011 ch &= ~CHAR_MODIFIER_MASK;
@@ -3065,14 +3059,24 @@ read_string_literal (char stackbuf[VLA_ELEMS (stackbufsize)],
3065 3059
3066 if (ch == '\\') 3060 if (ch == '\\')
3067 { 3061 {
3068 ch = read_escape (readcharfun, 1); 3062 /* First apply string-specific escape rules: */
3069 3063 ch = READCHAR;
3070 /* CH is -1 if \ newline or \ space has just been seen. */ 3064 switch (ch)
3071 if (ch == -1)
3072 { 3065 {
3066 case 's':
3067 /* `\s' is always a space in strings. */
3068 ch = ' ';
3069 break;
3070 case ' ':
3071 case '\n':
3072 /* `\SPC' and `\LF' generate no characters at all. */
3073 if (p == read_buffer) 3073 if (p == read_buffer)
3074 cancel = true; 3074 cancel = true;
3075 continue; 3075 continue;
3076 default:
3077 UNREAD (ch);
3078 ch = read_escape (readcharfun);
3079 break;
3076 } 3080 }
3077 3081
3078 int modifiers = ch & CHAR_MODIFIER_MASK; 3082 int modifiers = ch & CHAR_MODIFIER_MASK;
@@ -3084,19 +3088,13 @@ read_string_literal (char stackbuf[VLA_ELEMS (stackbufsize)],
3084 force_multibyte = true; 3088 force_multibyte = true;
3085 else /* I.e. ASCII_CHAR_P (ch). */ 3089 else /* I.e. ASCII_CHAR_P (ch). */
3086 { 3090 {
3087 /* Allow `\C- ' and `\C-?'. */ 3091 /* Allow `\C-SPC' and `\^SPC'. This is done here because
3088 if (modifiers == CHAR_CTL) 3092 the literals ?\C-SPC and ?\^SPC (rather inconsistently)
3093 yield (' ' | CHAR_CTL); see bug#55738. */
3094 if (modifiers == CHAR_CTL && ch == ' ')
3089 { 3095 {
3090 if (ch == ' ') 3096 ch = 0;
3091 { 3097 modifiers = 0;
3092 ch = 0;
3093 modifiers = 0;
3094 }
3095 else if (ch == '?')
3096 {
3097 ch = 127;
3098 modifiers = 0;
3099 }
3100 } 3098 }
3101 if (modifiers & CHAR_SHIFT) 3099 if (modifiers & CHAR_SHIFT)
3102 { 3100 {
diff --git a/test/src/lread-tests.el b/test/src/lread-tests.el
index 47351c1d116..99eec9d5487 100644
--- a/test/src/lread-tests.el
+++ b/test/src/lread-tests.el
@@ -317,4 +317,9 @@ literals (Bug#20852)."
317 (should (equal (read-from-string "#_") 317 (should (equal (read-from-string "#_")
318 '(## . 2)))) 318 '(## . 2))))
319 319
320(ert-deftest lread-escaped-lf ()
321 ;; ?\LF should produce LF (only inside string literals do we ignore \LF).
322 (should (equal (read-from-string "?\\\n") '(?\n . 3)))
323 (should (equal (read-from-string "\"a\\\nb\"") '("ab" . 6))))
324
320;;; lread-tests.el ends here 325;;; lread-tests.el ends here