From 75a65c7eb471bb7c6a5b7dc14a762ff997a5d354 Mon Sep 17 00:00:00 2001 From: Stefan Monnier Date: Fri, 8 Feb 2013 12:42:09 -0500 Subject: [PATCH] * src/lread.c (skip_dyn_bytes): New function. (read1): Use it. Use getc instead of READCHAR to read bytes. (load_each_byte): Remove. Update users. Fixes: debbugs:12598 --- src/ChangeLog | 6 ++++++ src/doc.c | 14 ++++++------- src/lread.c | 67 ++++++++++++++++++++++++++++++++++++----------------------- 3 files changed, 54 insertions(+), 33 deletions(-) diff --git a/src/ChangeLog b/src/ChangeLog index 420cb5aed63..46f872ba29d 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,9 @@ +2013-02-08 Stefan Monnier + + * lread.c (skip_dyn_bytes): New function (bug#12598). + (read1): Use it. Use getc instead of READCHAR to read bytes. + (load_each_byte): Remove. Update users. + 2013-02-08 Dmitry Antipov * search.c (scan_buffer): Calculate end byte position just once. diff --git a/src/doc.c b/src/doc.c index 16c0d4090a0..fa2eca66a1d 100644 --- a/src/doc.c +++ b/src/doc.c @@ -176,9 +176,9 @@ get_doc_string (Lisp_Object filepos, bool unibyte, bool definition) if (space_left <= 0) { ptrdiff_t in_buffer = p - get_doc_string_buffer; - get_doc_string_buffer = - xpalloc (get_doc_string_buffer, &get_doc_string_buffer_size, - 16 * 1024, -1, 1); + get_doc_string_buffer + = xpalloc (get_doc_string_buffer, &get_doc_string_buffer_size, + 16 * 1024, -1, 1); p = get_doc_string_buffer + in_buffer; space_left = (get_doc_string_buffer_size - 1 - (p - get_doc_string_buffer)); @@ -279,10 +279,10 @@ Invalid data in documentation file -- %c followed by code %03o", else { /* The data determines whether the string is multibyte. */ - ptrdiff_t nchars = - multibyte_chars_in_text (((unsigned char *) get_doc_string_buffer - + offset), - to - (get_doc_string_buffer + offset)); + ptrdiff_t nchars + = multibyte_chars_in_text (((unsigned char *) get_doc_string_buffer + + offset), + to - (get_doc_string_buffer + offset)); return make_string_from_bytes (get_doc_string_buffer + offset, nchars, to - (get_doc_string_buffer + offset)); diff --git a/src/lread.c b/src/lread.c index 09eccb0fb30..c62c62a5e5a 100644 --- a/src/lread.c +++ b/src/lread.c @@ -96,11 +96,6 @@ static Lisp_Object Qload_in_progress; It must be set to nil before all top-level calls to read0. */ static Lisp_Object read_objects; -/* True means READCHAR should read bytes one by one (not character) - when READCHARFUN is Qget_file_char or Qget_emacs_mule_file_char. - This is set by read1 temporarily while handling #@NUMBER. */ -static bool load_each_byte; - /* List of descriptors now open for Fload. */ static Lisp_Object load_descriptor_list; @@ -328,7 +323,7 @@ readchar (Lisp_Object readcharfun, bool *multibyte) return c; } c = (*readbyte) (-1, readcharfun); - if (c < 0 || load_each_byte) + if (c < 0) return c; if (multibyte) *multibyte = 1; @@ -353,6 +348,30 @@ readchar (Lisp_Object readcharfun, bool *multibyte) return STRING_CHAR (buf); } +static void +skip_dyn_bytes (Lisp_Object readcharfun, ptrdiff_t n) +{ + if (EQ (readcharfun, Qget_file_char) + || EQ (readcharfun, Qget_emacs_mule_file_char)) + { + block_input (); /* FIXME: Not sure if it's needed. */ + fseek (instream, n, SEEK_CUR); + unblock_input (); + } + else + { /* We're not reading directly from a file. In that case, it's difficult + to reliably count bytes, since these are usually meant for the file's + encoding, whereas we're now typically in the internal encoding. + But luckily, skip_dyn_bytes is used to skip over a single + dynamic-docstring (or dynamic byte-code) which is always quoted such + that \037 is the final char. */ + int c; + do { + c = READCHAR; + } while (c >= 0 && c != '\037'); + } +} + /* Unread the character C in the way appropriate for the stream READCHARFUN. If the stream is a user function, call it with the char as argument. */ @@ -407,14 +426,7 @@ unreadchar (Lisp_Object readcharfun, int c) else if (EQ (readcharfun, Qget_file_char) || EQ (readcharfun, Qget_emacs_mule_file_char)) { - if (load_each_byte) - { - block_input (); - ungetc (c, instream); - unblock_input (); - } - else - unread_char = c; + unread_char = c; } else call1 (readcharfun, make_number (c)); @@ -2388,7 +2400,6 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list) bool multibyte; *pch = 0; - load_each_byte = 0; retry: @@ -2598,7 +2609,7 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list) return tmp; } - /* #@NUMBER is used to skip NUMBER following characters. + /* #@NUMBER is used to skip NUMBER following bytes. That's used in .elc files to skip over doc strings and function definitions. */ if (c == '@') @@ -2606,7 +2617,6 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list) enum { extra = 100 }; ptrdiff_t i, nskip = 0; - load_each_byte = 1; /* Read a decimal integer. */ while ((c = READCHAR) >= 0 && c >= '0' && c <= '9') @@ -2616,8 +2626,15 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list) nskip *= 10; nskip += c - '0'; } - UNREAD (c); - + if (nskip > 0) + /* We can't use UNREAD here, because in the code below we side-step + READCHAR. Instead, assume the first char after #@NNN occupies + a single byte, which is the case normally since it's just + a space. */ + nskip--; + else + UNREAD (c); + if (load_force_doc_strings && (EQ (readcharfun, Qget_file_char) || EQ (readcharfun, Qget_emacs_mule_file_char))) @@ -2659,19 +2676,17 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list) saved_doc_string_position = file_tell (instream); /* Copy that many characters into saved_doc_string. */ + block_input (); for (i = 0; i < nskip && c >= 0; i++) - saved_doc_string[i] = c = READCHAR; + saved_doc_string[i] = c = getc (instream); + unblock_input (); saved_doc_string_length = i; } else - { - /* Skip that many characters. */ - for (i = 0; i < nskip && c >= 0; i++) - c = READCHAR; - } + /* Skip that many bytes. */ + skip_dyn_bytes (readcharfun, nskip); - load_each_byte = 0; goto retry; } if (c == '!') -- 2.11.4.GIT