diff options
| author | Paul Eggert | 2011-03-15 00:04:00 -0700 |
|---|---|---|
| committer | Paul Eggert | 2011-03-15 00:04:00 -0700 |
| commit | 15206ed9236f4957cb62a0cfbd5397cf8f0cb76b (patch) | |
| tree | c5b79dc24fd900342aaed46555ef28480014f502 /src/buffer.h | |
| parent | 4a6bea268fbac2fd64018374652f5b2c9b04b4fd (diff) | |
| download | emacs-15206ed9236f4957cb62a0cfbd5397cf8f0cb76b.tar.gz emacs-15206ed9236f4957cb62a0cfbd5397cf8f0cb76b.zip | |
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.
Diffstat (limited to 'src/buffer.h')
| -rw-r--r-- | src/buffer.h | 43 |
1 files changed, 43 insertions, 0 deletions
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; | |||
| 1026 | 1026 | ||
| 1027 | #define PER_BUFFER_VALUE(BUFFER, OFFSET) \ | 1027 | #define PER_BUFFER_VALUE(BUFFER, OFFSET) \ |
| 1028 | (*(Lisp_Object *)((OFFSET) + (char *) (BUFFER))) | 1028 | (*(Lisp_Object *)((OFFSET) + (char *) (BUFFER))) |
| 1029 | |||
| 1030 | /* Current buffer's map from characters to lower-case characters. */ | ||
| 1031 | |||
| 1032 | #define DOWNCASE_TABLE BVAR (current_buffer, downcase_table) | ||
| 1033 | |||
| 1034 | /* Current buffer's map from characters to upper-case characters. */ | ||
| 1035 | |||
| 1036 | #define UPCASE_TABLE BVAR (current_buffer, upcase_table) | ||
| 1037 | |||
| 1038 | /* Downcase a character, or make no change if that cannot be done. */ | ||
| 1039 | |||
| 1040 | static inline EMACS_INT | ||
| 1041 | downcase (int ch) | ||
| 1042 | { | ||
| 1043 | Lisp_Object down = CHAR_TABLE_REF (DOWNCASE_TABLE, ch); | ||
| 1044 | return NATNUMP (down) ? XFASTINT (down) : ch; | ||
| 1045 | } | ||
| 1046 | #define DOWNCASE(CH) downcase (CH) | ||
| 1047 | |||
| 1048 | /* 1 if CH is upper case. */ | ||
| 1049 | |||
| 1050 | #define UPPERCASEP(CH) (DOWNCASE (CH) != (CH)) | ||
| 1029 | 1051 | ||
| 1052 | /* 1 if CH is neither upper nor lower case. */ | ||
| 1053 | |||
| 1054 | #define NOCASEP(CH) (UPCASE1 (CH) == (CH)) | ||
| 1055 | |||
| 1056 | /* 1 if CH is lower case. */ | ||
| 1057 | |||
| 1058 | #define LOWERCASEP(CH) (!UPPERCASEP (CH) && !NOCASEP(CH)) | ||
| 1059 | |||
| 1060 | /* Upcase a character, or make no change if that cannot be done. */ | ||
| 1061 | |||
| 1062 | #define UPCASE(CH) (!UPPERCASEP (CH) ? UPCASE1 (CH) : (CH)) | ||
| 1063 | |||
| 1064 | /* Upcase a character known to be not upper case. */ | ||
| 1065 | |||
| 1066 | static inline EMACS_INT | ||
| 1067 | upcase1 (int ch) | ||
| 1068 | { | ||
| 1069 | Lisp_Object up = CHAR_TABLE_REF (UPCASE_TABLE, ch); | ||
| 1070 | return NATNUMP (up) ? XFASTINT (up) : ch; | ||
| 1071 | } | ||
| 1072 | #define UPCASE1(CH) upcase1 (CH) | ||