From cffc6f3bd9b5dbb9825502928bd9dd58ddbac02e Mon Sep 17 00:00:00 2001 From: Chong Yidong Date: Sun, 13 Mar 2011 18:25:16 -0400 Subject: Fix BUF_* macros to handle indirect buffers properly (Bug#8219). * buffer.h (BUF_BEGV, BUF_BEGV_BYTE, BUF_ZV, BUF_ZV_BYTE, BUF_PT) (BUF_PT_BYTE): Rewrite to handle indirect buffers (Bug#8219). These macros can no longer be used for assignment. * buffer.c (Fget_buffer_create, Fmake_indirect_buffer): Assign struct members directly, instead of using BUF_BEGV etc. (record_buffer_markers, fetch_buffer_markers): New functions for recording and fetching special buffer markers. (set_buffer_internal_1, set_buffer_temp): Use them. * lread.c (unreadchar): Use SET_BUF_PT_BOTH. * insdel.c (adjust_point): Use SET_BUF_PT_BOTH. * intervals.c (temp_set_point_both): Use SET_BUF_PT_BOTH. (get_local_map): Use SET_BUF_BEGV_BOTH and SET_BUF_ZV_BOTH. * xdisp.c (hscroll_window_tree): (reconsider_clip_changes): Use PT instead of BUF_PT. --- src/buffer.h | 45 +++++++++++++++++++++++++++++++-------------- 1 file changed, 31 insertions(+), 14 deletions(-) (limited to 'src/buffer.h') diff --git a/src/buffer.h b/src/buffer.h index 65c7168d60a..0975d2e3adc 100644 --- a/src/buffer.h +++ b/src/buffer.h @@ -107,27 +107,46 @@ along with GNU Emacs. If not, see . */ #define BUF_BEG(buf) (BEG) #define BUF_BEG_BYTE(buf) (BEG_BYTE) -/* !!!FIXME: all the BUF_BEGV/BUF_ZV/BUF_PT macros are flawed: - on indirect (or base) buffers, that value is only correct if that buffer - is the current_buffer, or if the buffer's text hasn't been modified (via - an indirect buffer) since it was last current. */ +/* The BUF_BEGV[_BYTE], BUF_ZV[_BYTE], and BUF_PT[_BYTE] macros cannot + be used for assignment; use SET_BUF_* macros below for that. */ /* Position of beginning of accessible range of buffer. */ -#define BUF_BEGV(buf) ((buf)->begv) -#define BUF_BEGV_BYTE(buf) ((buf)->begv_byte) +#define BUF_BEGV(buf) \ + (buf == current_buffer ? BEGV \ + : NILP (BVAR (buf, begv_marker)) ? buf->begv \ + : marker_position (BVAR (buf, begv_marker))) + +#define BUF_BEGV_BYTE(buf) \ + (buf == current_buffer ? BEGV_BYTE \ + : NILP (BVAR (buf, begv_marker)) ? buf->begv_byte \ + : marker_byte_position (BVAR (buf, begv_marker))) /* Position of point in buffer. */ -#define BUF_PT(buf) ((buf)->pt) -#define BUF_PT_BYTE(buf) ((buf)->pt_byte) +#define BUF_PT(buf) \ + (buf == current_buffer ? PT \ + : NILP (BVAR (buf, pt_marker)) ? buf->pt \ + : marker_position (BVAR (buf, pt_marker))) + +#define BUF_PT_BYTE(buf) \ + (buf == current_buffer ? PT_BYTE \ + : NILP (BVAR (buf, pt_marker)) ? buf->pt_byte \ + : marker_byte_position (BVAR (buf, pt_marker))) + +/* Position of end of accessible range of buffer. */ +#define BUF_ZV(buf) \ + (buf == current_buffer ? ZV \ + : NILP (BVAR (buf, zv_marker)) ? buf->zv \ + : marker_position (BVAR (buf, zv_marker))) + +#define BUF_ZV_BYTE(buf) \ + (buf == current_buffer ? ZV_BYTE \ + : NILP (BVAR (buf, zv_marker)) ? buf->zv_byte \ + : marker_byte_position (BVAR (buf, zv_marker))) /* Position of gap in buffer. */ #define BUF_GPT(buf) ((buf)->text->gpt) #define BUF_GPT_BYTE(buf) ((buf)->text->gpt_byte) -/* Position of end of accessible range of buffer. */ -#define BUF_ZV(buf) ((buf)->zv) -#define BUF_ZV_BYTE(buf) ((buf)->zv_byte) - /* Position of end of buffer. */ #define BUF_Z(buf) ((buf)->text->z) #define BUF_Z_BYTE(buf) ((buf)->text->z_byte) @@ -235,8 +254,6 @@ extern void enlarge_buffer_text (struct buffer *, EMACS_INT); /* Macros for setting the BEGV, ZV or PT of a given buffer. - SET_BUF_PT* seet to be redundant. Get rid of them? - The ..._BOTH macros take both a charpos and a bytepos, which must correspond to each other. -- cgit v1.2.1 From 15206ed9236f4957cb62a0cfbd5397cf8f0cb76b Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Tue, 15 Mar 2011 00:04:00 -0700 Subject: Fix a race condition diagnosed by gcc -Wsequence-point (Bug#8254). An expression of the form (DOWNCASE (x) == DOWNCASE (y)), found in dired.c's scmp function, had undefined behavior. * lisp.h (DOWNCASE_TABLE, UPCASE_TABLE, DOWNCASE, UPPERCASEP): (NOCASEP, LOWERCASEP, UPCASE, UPCASE1): Move from here ... * buffer.h: ... to here, because these macros use current_buffer, and the new implementation with inline functions needs to have current_buffer in scope now, rather than later when the macros are used. (downcase, upcase1): New static inline functions. (DOWNCASE, UPCASE1): Reimplement using these functions. This avoids undefined behavior in expressions like DOWNCASE (x) == DOWNCASE (y), which previously suffered from race conditions in accessing the global variables case_temp1 and case_temp2. * casetab.c (case_temp1, case_temp2): Remove; no longer needed. * lisp.h (case_temp1, case_temp2): Remove their decls. * character.h (ASCII_CHAR_P): Move from here ... * lisp.h: ... to here, so that the inline functions mentioned above can use them. --- src/buffer.h | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) (limited to 'src/buffer.h') diff --git a/src/buffer.h b/src/buffer.h index 0975d2e3adc..996e4e59c27 100644 --- a/src/buffer.h +++ b/src/buffer.h @@ -1026,4 +1026,47 @@ extern int last_per_buffer_idx; #define PER_BUFFER_VALUE(BUFFER, OFFSET) \ (*(Lisp_Object *)((OFFSET) + (char *) (BUFFER))) + +/* Current buffer's map from characters to lower-case characters. */ + +#define DOWNCASE_TABLE BVAR (current_buffer, downcase_table) + +/* Current buffer's map from characters to upper-case characters. */ + +#define UPCASE_TABLE BVAR (current_buffer, upcase_table) + +/* Downcase a character, or make no change if that cannot be done. */ + +static inline EMACS_INT +downcase (int ch) +{ + Lisp_Object down = CHAR_TABLE_REF (DOWNCASE_TABLE, ch); + return NATNUMP (down) ? XFASTINT (down) : ch; +} +#define DOWNCASE(CH) downcase (CH) + +/* 1 if CH is upper case. */ + +#define UPPERCASEP(CH) (DOWNCASE (CH) != (CH)) +/* 1 if CH is neither upper nor lower case. */ + +#define NOCASEP(CH) (UPCASE1 (CH) == (CH)) + +/* 1 if CH is lower case. */ + +#define LOWERCASEP(CH) (!UPPERCASEP (CH) && !NOCASEP(CH)) + +/* Upcase a character, or make no change if that cannot be done. */ + +#define UPCASE(CH) (!UPPERCASEP (CH) ? UPCASE1 (CH) : (CH)) + +/* Upcase a character known to be not upper case. */ + +static inline EMACS_INT +upcase1 (int ch) +{ + Lisp_Object up = CHAR_TABLE_REF (UPCASE_TABLE, ch); + return NATNUMP (up) ? XFASTINT (up) : ch; +} +#define UPCASE1(CH) upcase1 (CH) -- cgit v1.2.1 From 5da9919f99ebacbc511113134ef8f687a562d5b8 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Tue, 15 Mar 2011 14:14:06 -0700 Subject: Use functions, not macros, for up- and down-casing. --- src/buffer.h | 58 +++++++++++++++++++++------------------------------------- 1 file changed, 21 insertions(+), 37 deletions(-) (limited to 'src/buffer.h') diff --git a/src/buffer.h b/src/buffer.h index 996e4e59c27..d80875a0811 100644 --- a/src/buffer.h +++ b/src/buffer.h @@ -1027,46 +1027,30 @@ extern int last_per_buffer_idx; #define PER_BUFFER_VALUE(BUFFER, OFFSET) \ (*(Lisp_Object *)((OFFSET) + (char *) (BUFFER))) -/* Current buffer's map from characters to lower-case characters. */ - -#define DOWNCASE_TABLE BVAR (current_buffer, downcase_table) - -/* Current buffer's map from characters to upper-case characters. */ - -#define UPCASE_TABLE BVAR (current_buffer, upcase_table) - -/* Downcase a character, or make no change if that cannot be done. */ - -static inline EMACS_INT -downcase (int ch) +/* Downcase a character C, or make no change if that cannot be done. */ +static inline int +downcase (int c) { - Lisp_Object down = CHAR_TABLE_REF (DOWNCASE_TABLE, ch); - return NATNUMP (down) ? XFASTINT (down) : ch; + Lisp_Object downcase_table = BVAR (current_buffer, downcase_table); + Lisp_Object down = CHAR_TABLE_REF (downcase_table, c); + return NATNUMP (down) ? XFASTINT (down) : c; } -#define DOWNCASE(CH) downcase (CH) - -/* 1 if CH is upper case. */ - -#define UPPERCASEP(CH) (DOWNCASE (CH) != (CH)) - -/* 1 if CH is neither upper nor lower case. */ -#define NOCASEP(CH) (UPCASE1 (CH) == (CH)) +/* 1 if C is upper case. */ +static inline int uppercasep (int c) { return downcase (c) != c; } -/* 1 if CH is lower case. */ - -#define LOWERCASEP(CH) (!UPPERCASEP (CH) && !NOCASEP(CH)) - -/* Upcase a character, or make no change if that cannot be done. */ - -#define UPCASE(CH) (!UPPERCASEP (CH) ? UPCASE1 (CH) : (CH)) - -/* Upcase a character known to be not upper case. */ - -static inline EMACS_INT -upcase1 (int ch) +/* Upcase a character C known to be not upper case. */ +static inline int +upcase1 (int c) { - Lisp_Object up = CHAR_TABLE_REF (UPCASE_TABLE, ch); - return NATNUMP (up) ? XFASTINT (up) : ch; + Lisp_Object upcase_table = BVAR (current_buffer, upcase_table); + Lisp_Object up = CHAR_TABLE_REF (upcase_table, c); + return NATNUMP (up) ? XFASTINT (up) : c; } -#define UPCASE1(CH) upcase1 (CH) + +/* 1 if C is lower case. */ +static inline int lowercasep (int c) +{ return !uppercasep (c) && upcase1 (c) != c; } + +/* Upcase a character C, or make no change if that cannot be done. */ +static inline int upcase (int c) { return uppercasep (c) ? c : upcase1 (c); } -- cgit v1.2.1