]> git.eshelyaron.com Git - emacs.git/commitdiff
Fix round tripping of read->print for symbols with strange quotes
authorNoam Postavsky <npostavs@gmail.com>
Tue, 23 Jan 2018 23:50:23 +0000 (18:50 -0500)
committerNoam Postavsky <npostavs@gmail.com>
Sun, 28 Jan 2018 15:43:01 +0000 (10:43 -0500)
Since 2017-07-22 "Signal error for symbol names with strange
quotes (Bug#2967)", symbol names beginning with certain quote
characters require an escaping backslash.  However, the corresponding
change for printing missed, so that (eq (read (prin1-to-string SYM))
SYM) does not give `t' for such symbols.
* src/character.c (confusable_symbol_character_p): New function,
extracted from test `read1'.
* src/lread.c (read1): Use it.
* src/print.c (print_object): Use it to print a backslash for symbols
starting with characters that `read1' requires to be escaped.
* test/src/print-tests.el (print-read-roundtrip): New test.
* etc/NEWS.26:
* etc/NEWS: Clarify the announcement for the earlier reader
change (Bug#30217).

etc/NEWS
etc/NEWS.26
src/character.c
src/character.h
src/lread.c
src/print.c
test/src/print-tests.el

index 2888acd4dcb8fe5f8e722025917f01f801fafd7d..80ddf10488c17af40c4ef75f8e21e8ecf4714647 100644 (file)
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -229,6 +229,15 @@ as new-style, bind the new variable 'force-new-style-backquotes' to t.
 ** 'print-quoted' now defaults to t, so if you want to see
 (quote x) instead of 'x you will have to bind it to nil where applicable.
 
+** To avoid confusion caused by "smart quotes", the reader signals an
+error when reading Lisp symbols which begin with one of the following
+quotation characters: ‘’‛“”‟〞"'.  A symbol beginning with such a
+character can be written by escaping the quotation character with a
+backslash.  For example:
+
+    (read "‘smart") => (invalid-read-syntax "strange quote" "‘")
+    (read "\\‘smart") == (intern "‘smart")
+
 ** Internal parsing commands now use syntax-ppss and disregard
 open-paren-in-column-0-is-defun-start.  This affects mostly things like
 forward-comment, scan-sexps, and forward-sexp when parsing backward.
index 46762d65e18b89b0618f3f5e5e41f749248b9274..76e6316ca2e4528eb6f7b0e1da3a6317fcf7e357 100644 (file)
@@ -1377,11 +1377,6 @@ second argument instead of its first.
 renamed to 'lread--old-style-backquotes'.  No user code should use
 this variable.
 
----
-** To avoid confusion caused by "smart quotes", the reader no longer
-accepts Lisp symbols which begin with the following quotation
-characters: ‘’‛“”‟〞"', unless they are escaped with backslash.
-
 +++
 ** 'default-file-name-coding-system' now defaults to a coding system
 that does not process CRLF.  For example, it defaults to 'utf-8-unix'
index fa817a503172a9ca311edeb738b64c72af830c97..4a934c7801c86a76fd4796e9d80f6efb999c3334 100644 (file)
@@ -1050,6 +1050,32 @@ blankp (int c)
   return XINT (category) == UNICODE_CATEGORY_Zs; /* separator, space */
 }
 
+
+/* Return true for characters that would read as symbol characters,
+   but graphically may be confused with some kind of punctuation.  We
+   require an escaping backslash, when such characters begin a
+   symbol.  */
+bool
+confusable_symbol_character_p (int ch)
+{
+  switch (ch)
+    {
+    case 0x2018: /* LEFT SINGLE QUOTATION MARK */
+    case 0x2019: /* RIGHT SINGLE QUOTATION MARK */
+    case 0x201B: /* SINGLE HIGH-REVERSED-9 QUOTATION MARK */
+    case 0x201C: /* LEFT DOUBLE QUOTATION MARK */
+    case 0x201D: /* RIGHT DOUBLE QUOTATION MARK */
+    case 0x201F: /* DOUBLE HIGH-REVERSED-9 QUOTATION MARK */
+    case 0x301E: /* DOUBLE PRIME QUOTATION MARK */
+    case 0xFF02: /* FULLWIDTH QUOTATION MARK */
+    case 0xFF07: /* FULLWIDTH APOSTROPHE */
+      return true;
+
+    default:
+      return false;
+    }
+}
+
 signed char HEXDIGIT_CONST hexdigit[UCHAR_MAX + 1] =
   {
 #if HEXDIGIT_IS_CONST
index c716885d46b8dc0700a61dc46f3758804a2e7196..d9e2d7bfc6794ba2780a34e5a3a063313aa683bf 100644 (file)
@@ -682,6 +682,8 @@ extern bool graphicp (int);
 extern bool printablep (int);
 extern bool blankp (int);
 
+extern bool confusable_symbol_character_p (int ch);
+
 /* Return a translation table of id number ID.  */
 #define GET_TRANSLATION_TABLE(id) \
   (XCDR (XVECTOR (Vtranslation_table_vector)->contents[(id)]))
index 28d4bf9a4fe059cfb69cf06acf11adc44c1df071..3b0a17c90be3cd6adc1f2cee6e37d53b8eb81a66 100644 (file)
@@ -3473,20 +3473,9 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list)
         if (!quoted && multibyte)
           {
             int ch = STRING_CHAR ((unsigned char *) read_buffer);
-            switch (ch)
-              {
-              case 0x2018: /* LEFT SINGLE QUOTATION MARK */
-              case 0x2019: /* RIGHT SINGLE QUOTATION MARK */
-              case 0x201B: /* SINGLE HIGH-REVERSED-9 QUOTATION MARK */
-              case 0x201C: /* LEFT DOUBLE QUOTATION MARK */
-              case 0x201D: /* RIGHT DOUBLE QUOTATION MARK */
-              case 0x201F: /* DOUBLE HIGH-REVERSED-9 QUOTATION MARK */
-              case 0x301E: /* DOUBLE PRIME QUOTATION MARK */
-              case 0xFF02: /* FULLWIDTH QUOTATION MARK */
-              case 0xFF07: /* FULLWIDTH APOSTROPHE */
-                xsignal2 (Qinvalid_read_syntax, build_string ("strange quote"),
-                          CALLN (Fstring, make_number (ch)));
-              }
+            if (confusable_symbol_character_p (ch))
+              xsignal2 (Qinvalid_read_syntax, build_string ("strange quote"),
+                        CALLN (Fstring, make_number (ch)));
           }
        {
          Lisp_Object result;
index 0e1980d84be4fea349df0b4c26bbf62c77857d95..71579673248994a14ba0053d78c56396daa31ffa 100644 (file)
@@ -1971,7 +1971,8 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag)
                    || c == ';' || c == '#' || c == '(' || c == ')'
                    || c == ',' || c == '.' || c == '`'
                    || c == '[' || c == ']' || c == '?' || c <= 040
-                   || confusing)
+                    || confusing
+                   || (i == 1 && confusable_symbol_character_p (c)))
                  {
                    printchar ('\\', printcharfun);
                    confusing = false;
index 46368c69ada98ac3f6a8a9cd954ba8ae9e912237..01e65028bc7c1d1511ceebe28a2e52c8807e2cd4 100644 (file)
@@ -58,5 +58,9 @@
                        (buffer-string))
                      "--------\n"))))
 
+(ert-deftest print-read-roundtrip ()
+  (let ((sym '\’bar))
+    (should (eq (read (prin1-to-string sym)) sym))))
+
 (provide 'print-tests)
 ;;; print-tests.el ends here