From e38e7b7bc121b96649518e5e986bba23697abc2d Mon Sep 17 00:00:00 2001 From: Lars Ingebrigtsen Date: Mon, 1 Feb 2021 17:04:17 +0100 Subject: [PATCH] Make syntax errors say the line/column they appear at * 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 | 1 + src/lread.c | 100 +++++++++++++++++++++++++++++++--------------------- src/xdisp.c | 9 +++++ 3 files changed, 70 insertions(+), 40 deletions(-) diff --git a/src/lisp.h b/src/lisp.h index f6588685443..409a1e70608 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -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); diff --git a/src/lread.c b/src/lread.c index 72b68df6631..5d1676b0c9c 100644 --- a/src/lread.c +++ b/src/lread.c @@ -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) } -/* 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); } /* 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)) diff --git a/src/xdisp.c b/src/xdisp.c index 32b359098aa..efca6f641fb 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -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 -- 2.39.2