]> git.eshelyaron.com Git - emacs.git/commitdiff
Make syntax errors say the line/column they appear at
authorLars Ingebrigtsen <larsi@gnus.org>
Mon, 1 Feb 2021 16:04:17 +0000 (17:04 +0100)
committerLars Ingebrigtsen <larsi@gnus.org>
Mon, 1 Feb 2021 16:04:17 +0000 (17:04 +0100)
* src/lisp.h: Add count_lines prototype.
* src/lread.c (invalid_syntax_lisp): New function (bug#36970).
(invalid_syntax): Extend function to take a readcharfun parameter.
(read_emacs_mule_char, character_name_to_code): Pass in.
(read_escape, invalid_radix_integer, read1): Ditto.

* src/xdisp.c (count_lines): Add a more succinct shim over
display_count_lines.

src/lisp.h
src/lread.c
src/xdisp.c

index f6588685443f4400df6e853ef52f9627ac9c6247..409a1e706085541e230f2d1509181ef9e7a569e6 100644 (file)
@@ -3734,6 +3734,7 @@ extern void message_log_maybe_newline (void);
 extern void update_echo_area (void);
 extern void truncate_echo_area (ptrdiff_t);
 extern void redisplay (void);
+extern ptrdiff_t count_lines (ptrdiff_t start_byte, ptrdiff_t end_byte);
 
 void set_frame_cursor_types (struct frame *, Lisp_Object);
 extern void syms_of_xdisp (void);
index 72b68df6631f74eb29630314c16cef48df78a6b1..5d1676b0c9c6ad35e8c91ccecf5b45718a8f0fa5 100644 (file)
@@ -537,6 +537,34 @@ readbyte_from_string (int c, Lisp_Object readcharfun)
 }
 
 
+/* Signal Qinvalid_read_syntax error.
+   S is error string of length N (if > 0)  */
+
+static AVOID
+invalid_syntax_lisp (Lisp_Object s, Lisp_Object readcharfun)
+{
+  if (BUFFERP (readcharfun))
+    {
+      xsignal1 (Qinvalid_read_syntax,
+               CALLN (Fformat, build_string ("%s (line %d, column %d)"),
+                      s,
+                      /* We should already be in the readcharfun
+                         buffer when this error is called, so no need
+                         to switch to it first. */
+                      make_fixnum (count_lines (BEGV_BYTE, PT_BYTE) + 1),
+                      make_fixnum (current_column ())));
+    }
+  else
+    xsignal1 (Qinvalid_read_syntax, s);
+}
+
+static AVOID
+invalid_syntax (const char *s, Lisp_Object readcharfun)
+{
+  invalid_syntax_lisp (build_string (s), readcharfun);
+}
+
+
 /* Read one non-ASCII character from INFILE.  The character is
    encoded in `emacs-mule' and the first byte is already read in
    C.  */
@@ -594,8 +622,7 @@ read_emacs_mule_char (int c, int (*readbyte) (int, Lisp_Object), Lisp_Object rea
     }
   c = DECODE_CHAR (charset, code);
   if (c < 0)
-    Fsignal (Qinvalid_read_syntax,
-            list1 (build_string ("invalid multibyte form")));
+    invalid_syntax ("invalid multibyte form", readcharfun);
   return c;
 }
 
@@ -2330,16 +2357,6 @@ read_internal_start (Lisp_Object stream, Lisp_Object start, Lisp_Object end)
 }
 \f
 
-/* Signal Qinvalid_read_syntax error.
-   S is error string of length N (if > 0)  */
-
-static AVOID
-invalid_syntax (const char *s)
-{
-  xsignal1 (Qinvalid_read_syntax, build_string (s));
-}
-
-
 /* Use this for recursive reads, in contexts where internal tokens
    are not allowed.  */
 
@@ -2353,8 +2370,8 @@ read0 (Lisp_Object readcharfun)
   if (!c)
     return val;
 
-  xsignal1 (Qinvalid_read_syntax,
-           Fmake_string (make_fixnum (1), make_fixnum (c), Qnil));
+  invalid_syntax_lisp (Fmake_string (make_fixnum (1), make_fixnum (c), Qnil),
+                      readcharfun);
 }
 \f
 /* Grow a read buffer BUF that contains OFFSET useful bytes of data,
@@ -2384,7 +2401,8 @@ grow_read_buffer (char *buf, ptrdiff_t offset,
 /* Return the scalar value that has the Unicode character name NAME.
    Raise 'invalid-read-syntax' if there is no such character.  */
 static int
-character_name_to_code (char const *name, ptrdiff_t name_len)
+character_name_to_code (char const *name, ptrdiff_t name_len,
+                       Lisp_Object readcharfun)
 {
   /* For "U+XXXX", pass the leading '+' to string_to_number to reject
      monstrosities like "U+-0000".  */
@@ -2400,7 +2418,7 @@ character_name_to_code (char const *name, ptrdiff_t name_len)
     {
       AUTO_STRING (format, "\\N{%s}");
       AUTO_STRING_WITH_LEN (namestr, name, name_len);
-      xsignal1 (Qinvalid_read_syntax, CALLN (Fformat, format, namestr));
+      invalid_syntax_lisp (CALLN (Fformat, format, namestr), readcharfun);
     }
 
   return XFIXNUM (code);
@@ -2619,7 +2637,7 @@ read_escape (Lisp_Object readcharfun, bool stringp)
       {
         c = READCHAR;
         if (c != '{')
-          invalid_syntax ("Expected opening brace after \\N");
+          invalid_syntax ("Expected opening brace after \\N", readcharfun);
         char name[UNICODE_CHARACTER_NAME_LENGTH_BOUND + 1];
         bool whitespace = false;
         ptrdiff_t length = 0;
@@ -2634,8 +2652,9 @@ read_escape (Lisp_Object readcharfun, bool stringp)
               {
                 AUTO_STRING (format,
                              "Invalid character U+%04X in character name");
-                xsignal1 (Qinvalid_read_syntax,
-                          CALLN (Fformat, format, make_fixed_natnum (c)));
+               invalid_syntax_lisp (CALLN (Fformat, format,
+                                           make_fixed_natnum (c)),
+                                    readcharfun);
               }
             /* Treat multiple adjacent whitespace characters as a
                single space character.  This makes it easier to use
@@ -2651,15 +2670,15 @@ read_escape (Lisp_Object readcharfun, bool stringp)
               whitespace = false;
             name[length++] = c;
             if (length >= sizeof name)
-              invalid_syntax ("Character name too long");
+              invalid_syntax ("Character name too long", readcharfun);
           }
         if (length == 0)
-          invalid_syntax ("Empty character name");
+          invalid_syntax ("Empty character name", readcharfun);
        name[length] = '\0';
 
        /* character_name_to_code can invoke read1, recursively.
           This is why read1's buffer is not static.  */
-       return character_name_to_code (name, length);
+       return character_name_to_code (name, length, readcharfun);
       }
 
     default:
@@ -2697,10 +2716,11 @@ enum { stackbufsize = max (64,
                            + INT_STRLEN_BOUND (EMACS_INT) + 1)) };
 
 static void
-invalid_radix_integer (EMACS_INT radix, char stackbuf[VLA_ELEMS (stackbufsize)])
+invalid_radix_integer (EMACS_INT radix, char stackbuf[VLA_ELEMS (stackbufsize)],
+                      Lisp_Object readcharfun)
 {
   sprintf (stackbuf, invalid_radix_integer_format, radix);
-  invalid_syntax (stackbuf);
+  invalid_syntax (stackbuf, readcharfun);
 }
 
 /* Read an integer in radix RADIX using READCHARFUN to read
@@ -2760,7 +2780,7 @@ read_integer (Lisp_Object readcharfun, int radix,
   UNREAD (c);
 
   if (valid != 1)
-    invalid_radix_integer (radix, stackbuf);
+    invalid_radix_integer (radix, stackbuf, readcharfun);
 
   *p = '\0';
   return unbind_to (count, string_to_number (read_buffer, radix, NULL));
@@ -2896,7 +2916,7 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list)
              return ht;
            }
          UNREAD (c);
-         invalid_syntax ("#");
+         invalid_syntax ("#", readcharfun);
        }
       if (c == '^')
        {
@@ -2948,9 +2968,9 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list)
                    }
                  return tbl;
                }
-             invalid_syntax ("#^^");
+             invalid_syntax ("#^^", readcharfun);
            }
-         invalid_syntax ("#^");
+         invalid_syntax ("#^", readcharfun);
        }
       if (c == '&')
        {
@@ -2973,7 +2993,7 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list)
                         version.  */
                      && ! (XFIXNAT (length)
                            == (SCHARS (tmp) - 1) * BOOL_VECTOR_BITS_PER_CHAR)))
-               invalid_syntax ("#&...");
+               invalid_syntax ("#&...", readcharfun);
 
              val = make_uninit_bool_vector (XFIXNAT (length));
              data = bool_vector_uchar_data (val);
@@ -2984,7 +3004,7 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list)
                  &= (1 << (XFIXNUM (length) % BOOL_VECTOR_BITS_PER_CHAR)) - 1;
              return val;
            }
-         invalid_syntax ("#&...");
+         invalid_syntax ("#&...", readcharfun);
        }
       if (c == '[')
        {
@@ -3002,7 +3022,7 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list)
                      && VECTORP (AREF (tmp, COMPILED_CONSTANTS)))
                     || CONSP (AREF (tmp, COMPILED_BYTECODE)))
                 && FIXNATP (AREF (tmp, COMPILED_STACK_DEPTH))))
-           invalid_syntax ("Invalid byte-code object");
+           invalid_syntax ("Invalid byte-code object", readcharfun);
 
          if (STRINGP (AREF (tmp, COMPILED_BYTECODE))
              && STRING_MULTIBYTE (AREF (tmp, COMPILED_BYTECODE)))
@@ -3044,7 +3064,7 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list)
          /* Read the string itself.  */
          tmp = read1 (readcharfun, &ch, 0);
          if (ch != 0 || !STRINGP (tmp))
-           invalid_syntax ("#");
+           invalid_syntax ("#", readcharfun);
          /* Read the intervals and their properties.  */
          while (1)
            {
@@ -3059,7 +3079,7 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list)
              if (ch == 0)
                plist = read1 (readcharfun, &ch, 0);
              if (ch)
-               invalid_syntax ("Invalid string property list");
+               invalid_syntax ("Invalid string property list", readcharfun);
              Fset_text_properties (beg, end, plist, tmp);
            }
 
@@ -3207,7 +3227,7 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list)
              if (c == 'r' || c == 'R')
                {
                  if (! (2 <= n && n <= 36))
-                   invalid_radix_integer (n, stackbuf);
+                   invalid_radix_integer (n, stackbuf, readcharfun);
                  return read_integer (readcharfun, n, stackbuf);
                }
 
@@ -3301,7 +3321,7 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list)
        return read_integer (readcharfun, 2, stackbuf);
 
       UNREAD (c);
-      invalid_syntax ("#");
+      invalid_syntax ("#", readcharfun);
 
     case ';':
       while ((c = READCHAR) >= 0 && c != '\n');
@@ -3373,7 +3393,7 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list)
        if (ok)
          return make_fixnum (c);
 
-       invalid_syntax ("?");
+       invalid_syntax ("?", readcharfun);
       }
 
     case '"':
@@ -3459,7 +3479,7 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list)
 
                /* Any modifiers remaining are invalid.  */
                if (modifiers)
-                 invalid_syntax ("Invalid modifier in string");
+                 invalid_syntax ("Invalid modifier in string", readcharfun);
                p += CHAR_STRING (ch, (unsigned char *) p);
              }
            else
@@ -3999,7 +4019,7 @@ read_list (bool flag, Lisp_Object readcharfun)
            {
              if (ch == ']')
                return val;
-             invalid_syntax (") or . in a vector");
+             invalid_syntax (") or . in a vector", readcharfun);
            }
          if (ch == ')')
            return val;
@@ -4079,9 +4099,9 @@ read_list (bool flag, Lisp_Object readcharfun)
 
                  return val;
                }
-             invalid_syntax (". in wrong context");
+             invalid_syntax (". in wrong context", readcharfun);
            }
-         invalid_syntax ("] in a list");
+         invalid_syntax ("] in a list", readcharfun);
        }
       tem = list1 (elt);
       if (!NILP (tail))
index 32b359098aa6f2b85c820f7ae2e38bd2b37998ce..efca6f641fb45f8c73ead860928d7814a38093bd 100644 (file)
@@ -26969,6 +26969,15 @@ decode_mode_spec (struct window *w, register int c, int field_width,
     return "";
 }
 
+/* Return the number of lines between start_byte and end_byte in the
+   current buffer. */
+
+ptrdiff_t
+count_lines (ptrdiff_t start_byte, ptrdiff_t end_byte)
+{
+  ptrdiff_t ignored;
+  return display_count_lines (start_byte, end_byte, ZV, &ignored);
+}
 
 /* Count up to COUNT lines starting from START_BYTE.  COUNT negative
    means count lines back from START_BYTE.  But don't go beyond