From d84b4f83a55e3b1a12e399ad199cc36cd013dcb3 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Tue, 3 Sep 2019 21:54:58 -0700 Subject: [PATCH] Prefer functions to macros in buffer.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In buffer.h, prefer inline functions to function-like macros when either will do. This helps avoid confusion about how many times an arg is evaluated. On my platform, this patch improves performance of ‘make compile-always’ by 5.7%. Also, prefer enum constants to object-like macros when either will do. * src/buffer.h (BEG, BEG_BYTE, GAP_BYTES_DFL, GAP_BYTES_MIN) (MAX_PER_BUFFER_VARS, NONEXISTENT_MODTIME_NSECS) (UNKNOWN_MODTIME_NSECS, BUFFER_LISP_SIZE, BUFFER_REST_SIZE): Now enum constants, instead of macros. (BUFFER_CEILING_OF, BUFFER_FLOOR_OF, BUF_BEG, BUF_BEG_BYTE) (BUF_BEGV, BUF_BEGV_BYTE, BUF_PT, BUF_PT_BYTE, BUF_ZV) (BUF_ZV_BYTE, BUF_GPT_ADDR, BUF_Z_ADDR, BUF_GAP_END_ADDR) (BUF_COMPUTE_UNCHANGED, SET_PT, TEMP_SET_PT, SET_PT_BOTH) (TEMP_SET_PT_BOTH, BUF_TEMP_SET_PT, SET_BUF_BEGV, SET_BUF_ZV) (SET_BUF_BEGV_BOTH, SET_BUF_ZV_BOTH, SET_BUF_PT_BOTH) (BYTE_POS_ADDR, CHAR_POS_ADDR, CHAR_TO_BYTE, BYTE_TO_CHAR) (PTR_BYTE_POS, FETCH_CHAR, FETCH_CHAR_AS_MULTIBYTE) (BUF_BYTE_ADDRESS, BUF_CHAR_ADDRESS, BUF_PTR_BYTE_POS) (BUF_FETCH_CHAR, BUF_FETCH_CHAR_AS_MULTIBYTE, BUF_FETCH_BYTE) (BUFFER_PVEC_INIT, BUFFER_LIVE_P, BUFFER_HIDDEN_P) (BUFFER_CHECK_INDIRECTION, OVERLAY_POSITION, PER_BUFFER_VALUE_P) (SET_PER_BUFFER_VALUE_P, PER_BUFFER_IDX): Now inline functions instead of macros. --- src/buffer.h | 661 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 395 insertions(+), 266 deletions(-) diff --git a/src/buffer.h b/src/buffer.h index 14de70c648..82d9350bfc 100644 --- a/src/buffer.h +++ b/src/buffer.h @@ -31,12 +31,11 @@ #define EMACS_BUFFER_H /* Accessing the parameters of the current buffer. */ -/* These macros come in pairs, one for the char position +/* These constants and macros come in pairs, one for the char position and one for the byte position. */ /* Position of beginning of buffer. */ -#define BEG (1) -#define BEG_BYTE (BEG) +enum { BEG = 1, BEG_BYTE = BEG }; /* Position of beginning of accessible range of buffer. */ #define BEGV (current_buffer->begv) @@ -96,59 +95,7 @@ #define OVERLAY_MODIFF (current_buffer->text->overlay_modiff) /* Modification count as of last visit or save. */ #define SAVE_MODIFF (current_buffer->text->save_modiff) - -/* BUFFER_CEILING_OF (resp. BUFFER_FLOOR_OF), when applied to n, return - the max (resp. min) p such that - - BYTE_POS_ADDR (p) - BYTE_POS_ADDR (n) == p - n */ - -#define BUFFER_CEILING_OF(BYTEPOS) \ - (((BYTEPOS) < GPT_BYTE && GPT < ZV ? GPT_BYTE : ZV_BYTE) - 1) -#define BUFFER_FLOOR_OF(BYTEPOS) \ - (BEGV <= GPT && GPT_BYTE <= (BYTEPOS) ? GPT_BYTE : BEGV_BYTE) -/* Similar macros to operate on a specified buffer. - Note that many of these evaluate the buffer argument more than once. */ - -/* Position of beginning of buffer. */ -#define BUF_BEG(buf) (BEG) -#define BUF_BEG_BYTE(buf) (BEG_BYTE) - -/* 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 == 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 == 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) @@ -161,15 +108,6 @@ #define BUF_Z_BYTE(buf) ((buf)->text->z_byte) /* Address of beginning of buffer. */ #define BUF_BEG_ADDR(buf) ((buf)->text->beg) -/* Address of beginning of gap of buffer. */ -#define BUF_GPT_ADDR(buf) ((buf)->text->beg + (buf)->text->gpt_byte - BEG_BYTE) - -/* Address of end of buffer. */ -#define BUF_Z_ADDR(buf) ((buf)->text->beg + (buf)->text->gap_size + (buf)->text->z_byte - BEG_BYTE) - -/* Address of end of gap in buffer. */ -#define BUF_GAP_END_ADDR(buf) ((buf)->text->beg + (buf)->text->gpt_byte + (buf)->text->gap_size - BEG_BYTE) - /* Size of gap. */ #define BUF_GAP_SIZE(buf) ((buf)->text->gap_size) @@ -209,43 +147,8 @@ #define OVERLAY_UNCHANGED_MODIFIED \ BUF_OVERLAY_UNCHANGED_MODIFIED (current_buffer) #define BEG_UNCHANGED BUF_BEG_UNCHANGED (current_buffer) #define END_UNCHANGED BUF_END_UNCHANGED (current_buffer) - -/* Compute how many characters at the top and bottom of BUF are - unchanged when the range START..END is modified. This computation - must be done each time BUF is modified. */ - -#define BUF_COMPUTE_UNCHANGED(buf, start, end) \ - do \ - { \ - if (BUF_UNCHANGED_MODIFIED (buf) == BUF_MODIFF (buf) \ - && (BUF_OVERLAY_UNCHANGED_MODIFIED (buf) \ - == BUF_OVERLAY_MODIFF (buf))) \ - { \ - BUF_BEG_UNCHANGED (buf) = (start) - BUF_BEG (buf); \ - BUF_END_UNCHANGED (buf) = BUF_Z (buf) - (end); \ - } \ - else \ - { \ - if (BUF_Z (buf) - (end) < BUF_END_UNCHANGED (buf)) \ - BUF_END_UNCHANGED (buf) = BUF_Z (buf) - (end); \ - if ((start) - BUF_BEG (buf) < BUF_BEG_UNCHANGED (buf)) \ - BUF_BEG_UNCHANGED (buf) = (start) - BUF_BEG (buf); \ - } \ - } \ - while (false) - -/* Macros to set PT in the current buffer, or another buffer. */ - -#define SET_PT(position) (set_point (position)) -#define TEMP_SET_PT(position) (temp_set_point (current_buffer, (position))) - -#define SET_PT_BOTH(position, byte) (set_point_both (position, byte)) -#define TEMP_SET_PT_BOTH(position, byte) \ - (temp_set_point_both (current_buffer, (position), (byte))) - -#define BUF_TEMP_SET_PT(buffer, position) \ - (temp_set_point ((buffer), (position))) +/* Functions to set PT in the current buffer, or another buffer. */ extern void set_point (ptrdiff_t); extern void temp_set_point (struct buffer *, ptrdiff_t); @@ -255,39 +158,32 @@ #define BUF_TEMP_SET_PT(buffer, position) \ extern void set_point_from_marker (Lisp_Object); extern void enlarge_buffer_text (struct buffer *, ptrdiff_t); +INLINE void +SET_PT (ptrdiff_t position) +{ + set_point (position); +} +INLINE void +TEMP_SET_PT (ptrdiff_t position) +{ + temp_set_point (current_buffer, position); +} +INLINE void +SET_PT_BOTH (ptrdiff_t position, ptrdiff_t byte) +{ + set_point_both (position, byte); +} +INLINE void +TEMP_SET_PT_BOTH (ptrdiff_t position, ptrdiff_t byte) +{ + temp_set_point_both (current_buffer, position, byte); +} +INLINE void +BUF_TEMP_SET_PT (struct buffer *buffer, ptrdiff_t position) +{ + temp_set_point (buffer, position); +} -/* Macros for setting the BEGV, ZV or PT of a given buffer. - - The ..._BOTH macros take both a charpos and a bytepos, - which must correspond to each other. - - The macros without ..._BOTH take just a charpos, - and compute the bytepos from it. */ - -#define SET_BUF_BEGV(buf, charpos) \ - ((buf)->begv_byte = buf_charpos_to_bytepos ((buf), (charpos)), \ - (buf)->begv = (charpos)) - -#define SET_BUF_ZV(buf, charpos) \ - ((buf)->zv_byte = buf_charpos_to_bytepos ((buf), (charpos)), \ - (buf)->zv = (charpos)) - -#define SET_BUF_BEGV_BOTH(buf, charpos, byte) \ - ((buf)->begv = (charpos), \ - (buf)->begv_byte = (byte)) - -#define SET_BUF_ZV_BOTH(buf, charpos, byte) \ - ((buf)->zv = (charpos), \ - (buf)->zv_byte = (byte)) - -#define SET_BUF_PT_BOTH(buf, charpos, byte) \ - ((buf)->pt = (charpos), \ - (buf)->pt_byte = (byte)) - -/* Macros to access a character or byte in the current buffer, - or convert between a byte position and an address. - These macros do not check that the position is in range. */ - /* Maximum number of bytes in a buffer. A buffer cannot contain more bytes than a 1-origin fixnum can represent, nor can it be so large that C pointer arithmetic stops working. @@ -298,115 +194,21 @@ #define BUF_BYTES_MAX \ /* Maximum gap size after compact_buffer, in bytes. Also used in make_gap_larger to get some extra reserved space. */ -#define GAP_BYTES_DFL 2000 +enum { GAP_BYTES_DFL = 2000 }; /* Minimum gap size after compact_buffer, in bytes. Also used in make_gap_smaller to avoid too small gap size. */ -#define GAP_BYTES_MIN 20 - -/* Return the address of byte position N in current buffer. */ - -#define BYTE_POS_ADDR(n) \ - (((n) >= GPT_BYTE ? GAP_SIZE : 0) + (n) + BEG_ADDR - BEG_BYTE) - -/* Return the address of char position N. */ - -#define CHAR_POS_ADDR(n) \ - (((n) >= GPT ? GAP_SIZE : 0) \ - + buf_charpos_to_bytepos (current_buffer, n) \ - + BEG_ADDR - BEG_BYTE) - -/* Convert a character position to a byte position. */ - -#define CHAR_TO_BYTE(charpos) \ - (buf_charpos_to_bytepos (current_buffer, charpos)) - -/* Convert a byte position to a character position. */ - -#define BYTE_TO_CHAR(bytepos) \ - (buf_bytepos_to_charpos (current_buffer, bytepos)) +enum { GAP_BYTES_MIN = 20 }; /* For those very rare cases where you may have a "random" pointer into the middle of a multibyte char, this moves to the next boundary. */ extern ptrdiff_t advance_to_char_boundary (ptrdiff_t byte_pos); -/* Convert PTR, the address of a byte in the buffer, into a byte position. */ - -#define PTR_BYTE_POS(ptr) \ - ((ptr) - (current_buffer)->text->beg \ - - (ptr - (current_buffer)->text->beg <= GPT_BYTE - BEG_BYTE ? 0 : GAP_SIZE) \ - + BEG_BYTE) - -/* Return character at byte position POS. See the caveat WARNING for - FETCH_MULTIBYTE_CHAR below. */ - -#define FETCH_CHAR(pos) \ - (!NILP (BVAR (current_buffer, enable_multibyte_characters)) \ - ? FETCH_MULTIBYTE_CHAR ((pos)) \ - : FETCH_BYTE ((pos))) - -/* Return the byte at byte position N. */ +/* Return the byte at byte position N. + Do not check that the position is in range. */ #define FETCH_BYTE(n) *(BYTE_POS_ADDR ((n))) - -/* Return character at byte position POS. If the current buffer is unibyte - and the character is not ASCII, make the returning character - multibyte. */ - -#define FETCH_CHAR_AS_MULTIBYTE(pos) \ - (!NILP (BVAR (current_buffer, enable_multibyte_characters)) \ - ? FETCH_MULTIBYTE_CHAR ((pos)) \ - : UNIBYTE_TO_CHAR (FETCH_BYTE ((pos)))) - - -/* Macros for accessing a character or byte, - or converting between byte positions and addresses, - in a specified buffer. */ - -/* Return the address of character at byte position POS in buffer BUF. - Note that both arguments can be computed more than once. */ - -#define BUF_BYTE_ADDRESS(buf, pos) \ - ((buf)->text->beg + (pos) - BEG_BYTE \ - + ((pos) >= (buf)->text->gpt_byte ? (buf)->text->gap_size : 0)) - -/* Return the address of character at char position POS in buffer BUF. - Note that both arguments can be computed more than once. */ - -#define BUF_CHAR_ADDRESS(buf, pos) \ - ((buf)->text->beg + buf_charpos_to_bytepos ((buf), (pos)) - BEG_BYTE \ - + ((pos) >= (buf)->text->gpt ? (buf)->text->gap_size : 0)) - -/* Convert PTR, the address of a char in buffer BUF, - into a character position. */ - -#define BUF_PTR_BYTE_POS(buf, ptr) \ - ((ptr) - (buf)->text->beg \ - - (ptr - (buf)->text->beg <= BUF_GPT_BYTE (buf) - BEG_BYTE \ - ? 0 : BUF_GAP_SIZE ((buf))) \ - + BEG_BYTE) - -/* Return the character at byte position POS in buffer BUF. */ - -#define BUF_FETCH_CHAR(buf, pos) \ - (!NILP (buf->enable_multibyte_characters) \ - ? BUF_FETCH_MULTIBYTE_CHAR ((buf), (pos)) \ - : BUF_FETCH_BYTE ((buf), (pos))) - -/* Return character at byte position POS in buffer BUF. If BUF is - unibyte and the character is not ASCII, make the returning - character multibyte. */ - -#define BUF_FETCH_CHAR_AS_MULTIBYTE(buf, pos) \ - (! NILP (BVAR ((buf), enable_multibyte_characters)) \ - ? BUF_FETCH_MULTIBYTE_CHAR ((buf), (pos)) \ - : UNIBYTE_TO_CHAR (BUF_FETCH_BYTE ((buf), (pos)))) - -/* Return the byte at byte position N in buffer BUF. */ - -#define BUF_FETCH_BYTE(buf, n) \ - *(BUF_BYTE_ADDRESS ((buf), (n))) /* Define the actual buffer data structures. */ @@ -482,6 +284,13 @@ #define BUF_FETCH_BYTE(buf, n) \ #define BVAR(buf, field) ((buf)->field ## _) +/* Max number of builtin per-buffer variables. */ +enum { MAX_PER_BUFFER_VARS = 50 }; + +/* Special values for struct buffer.modtime. */ +enum { NONEXISTENT_MODTIME_NSECS = -1 }; +enum { UNKNOWN_MODTIME_NSECS = -2 }; + /* This is the structure that the buffer Lisp object points to. */ struct buffer @@ -796,7 +605,6 @@ #define BVAR(buf, field) ((buf)->field ## _) for a buffer-local variable is stored in that variable's slot in buffer_local_flags as a Lisp integer. If the index is -1, this means the variable is always local in all buffers. */ -#define MAX_PER_BUFFER_VARS 50 char local_flags[MAX_PER_BUFFER_VARS]; /* Set to the modtime of the visited file when read or written. @@ -804,8 +612,6 @@ #define MAX_PER_BUFFER_VARS 50 visited file was nonexistent. modtime.tv_nsec == UNKNOWN_MODTIME_NSECS means visited file modtime unknown; in no case complain about any mismatch on next save attempt. */ -#define NONEXISTENT_MODTIME_NSECS (-1) -#define UNKNOWN_MODTIME_NSECS (-2) struct timespec modtime; /* Size of the file when modtime was set. This is used to detect the @@ -1018,49 +824,281 @@ bset_width_table (struct buffer *b, Lisp_Object val) b->width_table_ = val; } +/* BUFFER_CEILING_OF (resp. BUFFER_FLOOR_OF), when applied to n, return + the max (resp. min) p such that + + BYTE_POS_ADDR (p) - BYTE_POS_ADDR (n) == p - n */ + +INLINE ptrdiff_t +BUFFER_CEILING_OF (ptrdiff_t bytepos) +{ + return (bytepos < GPT_BYTE && GPT < ZV ? GPT_BYTE : ZV_BYTE) - 1; +} + +INLINE ptrdiff_t +BUFFER_FLOOR_OF (ptrdiff_t bytepos) +{ + return BEGV <= GPT && GPT_BYTE <= bytepos ? GPT_BYTE : BEGV_BYTE; +} + +/* The BUF_BEGV[_BYTE], BUF_ZV[_BYTE], and BUF_PT[_BYTE] functions cannot + be used for assignment; use SET_BUF_* functions below for that. */ + +/* Position of beginning of accessible range of buffer. */ +INLINE ptrdiff_t +BUF_BEGV (struct buffer *buf) +{ + return (buf == current_buffer ? BEGV + : NILP (BVAR (buf, begv_marker)) ? buf->begv + : marker_position (BVAR (buf, begv_marker))); +} + +INLINE ptrdiff_t +BUF_BEGV_BYTE (struct buffer *buf) +{ + return (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. */ +INLINE ptrdiff_t +BUF_PT (struct buffer *buf) +{ + return (buf == current_buffer ? PT + : NILP (BVAR (buf, pt_marker)) ? buf->pt + : marker_position (BVAR (buf, pt_marker))); +} + +INLINE ptrdiff_t +BUF_PT_BYTE (struct buffer *buf) +{ + return (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. */ +INLINE ptrdiff_t +BUF_ZV (struct buffer *buf) +{ + return (buf == current_buffer ? ZV + : NILP (BVAR (buf, zv_marker)) ? buf->zv + : marker_position (BVAR (buf, zv_marker))); +} + +INLINE ptrdiff_t +BUF_ZV_BYTE (struct buffer *buf) +{ + return (buf == current_buffer ? ZV_BYTE + : NILP (BVAR (buf, zv_marker)) ? buf->zv_byte + : marker_byte_position (BVAR (buf, zv_marker))); +} + +/* Similar functions to operate on a specified buffer. */ + +/* Position of beginning of buffer. */ +INLINE ptrdiff_t +BUF_BEG (struct buffer *buf) +{ + return BEG; +} + +INLINE ptrdiff_t +BUF_BEG_BYTE (struct buffer *buf) +{ + return BEG_BYTE; +} + +/* Address of beginning of gap of buffer. */ +INLINE unsigned char * +BUF_GPT_ADDR (struct buffer *buf) +{ + return buf->text->beg + buf->text->gpt_byte - BEG_BYTE; +} + +/* Address of end of buffer. */ +INLINE unsigned char * +BUF_Z_ADDR (struct buffer *buf) +{ + return buf->text->beg + buf->text->gap_size + buf->text->z_byte - BEG_BYTE; +} + +/* Address of end of gap in buffer. */ +INLINE unsigned char * +BUF_GAP_END_ADDR (struct buffer *buf) +{ + return buf->text->beg + buf->text->gpt_byte + buf->text->gap_size - BEG_BYTE; +} + +/* Compute how many characters at the top and bottom of BUF are + unchanged when the range START..END is modified. This computation + must be done each time BUF is modified. */ + +INLINE void +BUF_COMPUTE_UNCHANGED (struct buffer *buf, ptrdiff_t start, ptrdiff_t end) +{ + if (BUF_UNCHANGED_MODIFIED (buf) == BUF_MODIFF (buf) + && (BUF_OVERLAY_UNCHANGED_MODIFIED (buf) + == BUF_OVERLAY_MODIFF (buf))) + { + buf->text->beg_unchanged = start - BUF_BEG (buf); + buf->text->end_unchanged = BUF_Z (buf) - (end); + } + else + { + if (BUF_Z (buf) - end < BUF_END_UNCHANGED (buf)) + buf->text->end_unchanged = BUF_Z (buf) - end; + if (start - BUF_BEG (buf) < BUF_BEG_UNCHANGED (buf)) + buf->text->beg_unchanged = start - BUF_BEG (buf); + } +} + +/* Functions for setting the BEGV, ZV or PT of a given buffer. + + The ..._BOTH functions take both a charpos and a bytepos, + which must correspond to each other. + + The functions without ..._BOTH take just a charpos, + and compute the bytepos from it. */ + +INLINE void +SET_BUF_BEGV (struct buffer *buf, ptrdiff_t charpos) +{ + buf->begv_byte = buf_charpos_to_bytepos (buf, charpos); + buf->begv = charpos; +} + +INLINE void +SET_BUF_ZV (struct buffer *buf, ptrdiff_t charpos) +{ + buf->zv_byte = buf_charpos_to_bytepos (buf, charpos); + buf->zv = charpos; +} + +INLINE void +SET_BUF_BEGV_BOTH (struct buffer *buf, ptrdiff_t charpos, ptrdiff_t byte) +{ + buf->begv = charpos; + buf->begv_byte = byte; +} + +INLINE void +SET_BUF_ZV_BOTH (struct buffer *buf, ptrdiff_t charpos, ptrdiff_t byte) +{ + buf->zv = charpos; + buf->zv_byte = byte; +} + +INLINE void +SET_BUF_PT_BOTH (struct buffer *buf, ptrdiff_t charpos, ptrdiff_t byte) +{ + buf->pt = charpos; + buf->pt_byte = byte; +} + +/* Functions to access a character or byte in the current buffer, + or convert between a byte position and an address. + These functions do not check that the position is in range. */ + +/* Return the address of byte position N in current buffer. */ + +INLINE unsigned char * +BYTE_POS_ADDR (ptrdiff_t n) +{ + return (n < GPT_BYTE ? 0 : GAP_SIZE) + n + BEG_ADDR - BEG_BYTE; +} + +/* Return the address of char position N. */ + +INLINE unsigned char * +CHAR_POS_ADDR (ptrdiff_t n) +{ + return ((n < GPT ? 0 : GAP_SIZE) + + buf_charpos_to_bytepos (current_buffer, n) + + BEG_ADDR - BEG_BYTE); +} + +/* Convert a character position to a byte position. */ + +INLINE ptrdiff_t +CHAR_TO_BYTE (ptrdiff_t charpos) +{ + return buf_charpos_to_bytepos (current_buffer, charpos); +} + +/* Convert a byte position to a character position. */ + +INLINE ptrdiff_t +BYTE_TO_CHAR (ptrdiff_t bytepos) +{ + return buf_bytepos_to_charpos (current_buffer, bytepos); +} + +/* Convert PTR, the address of a byte in the buffer, into a byte position. */ + +INLINE ptrdiff_t +PTR_BYTE_POS (unsigned char const *ptr) +{ + ptrdiff_t byte = ptr - current_buffer->text->beg; + return byte - (byte <= GPT_BYTE - BEG_BYTE ? 0 : GAP_SIZE) + BEG_BYTE; +} + /* Number of Lisp_Objects at the beginning of struct buffer. If you add, remove, or reorder Lisp_Objects within buffer structure, make sure that this is still correct. */ -#define BUFFER_LISP_SIZE \ - PSEUDOVECSIZE (struct buffer, cursor_in_non_selected_windows_) +enum { BUFFER_LISP_SIZE = PSEUDOVECSIZE (struct buffer, + cursor_in_non_selected_windows_) }; /* Allocated size of the struct buffer part beyond leading Lisp_Objects, in word_size units. */ -#define BUFFER_REST_SIZE (VECSIZE (struct buffer) - BUFFER_LISP_SIZE) +enum { BUFFER_REST_SIZE = VECSIZE (struct buffer) - BUFFER_LISP_SIZE }; /* Initialize the pseudovector header of buffer object. BUFFER_LISP_SIZE is required for GC, but BUFFER_REST_SIZE is set up just to be consistent with other pseudovectors. */ -#define BUFFER_PVEC_INIT(b) \ - XSETPVECTYPESIZE (b, PVEC_BUFFER, BUFFER_LISP_SIZE, BUFFER_REST_SIZE) +INLINE void +BUFFER_PVEC_INIT (struct buffer *b) +{ + XSETPVECTYPESIZE (b, PVEC_BUFFER, BUFFER_LISP_SIZE, BUFFER_REST_SIZE); +} /* Convenient check whether buffer B is live. */ -#define BUFFER_LIVE_P(b) (!NILP (BVAR (b, name))) +INLINE bool +BUFFER_LIVE_P (struct buffer *b) +{ + return !NILP (BVAR (b, name)); +} /* Convenient check whether buffer B is hidden (i.e. its name starts with a space). Caller must ensure that B is live. */ -#define BUFFER_HIDDEN_P(b) (SREF (BVAR (b, name), 0) == ' ') +INLINE bool +BUFFER_HIDDEN_P (struct buffer *b) +{ + return SREF (BVAR (b, name), 0) == ' '; +} /* Verify indirection counters. */ -#define BUFFER_CHECK_INDIRECTION(b) \ - do { \ - if (BUFFER_LIVE_P (b)) \ - { \ - if (b->base_buffer) \ - { \ - eassert (b->indirections == -1); \ - eassert (b->base_buffer->indirections > 0); \ - } \ - else \ - eassert (b->indirections >= 0); \ - } \ - } while (false) +INLINE void +BUFFER_CHECK_INDIRECTION (struct buffer *b) +{ + if (BUFFER_LIVE_P (b)) + { + if (b->base_buffer) + { + eassert (b->indirections == -1); + eassert (b->base_buffer->indirections > 0); + } + else + eassert (b->indirections >= 0); + } +} /* Chain of all buffers, including killed ones. */ @@ -1157,7 +1195,9 @@ record_unwind_current_buffer (void) /* Get overlays at POSN into array OVERLAYS with NOVERLAYS elements. If NEXTP is non-NULL, return next overlay there. - See overlay_at arg CHANGE_REQ for meaning of CHRQ arg. */ + See overlay_at arg CHANGE_REQ for meaning of CHRQ arg. + This macro might evaluate its args multiple times, + and it treat some args as lvalues. */ #define GET_OVERLAYS_AT(posn, overlays, noverlays, nextp, chrq) \ do { \ @@ -1207,6 +1247,10 @@ buffer_has_overlays (void) { return current_buffer->overlays_before || current_buffer->overlays_after; } + +/* Functions for accessing a character or byte, + or converting between byte positions and addresses, + in a specified buffer. */ /* Return character code of multi-byte form at byte position POS. If POS doesn't point the head of valid multi-byte form, only the byte at @@ -1232,6 +1276,80 @@ BUF_FETCH_MULTIBYTE_CHAR (struct buffer *buf, ptrdiff_t pos) return STRING_CHAR (p); } +/* Return character at byte position POS. + If the current buffer is unibyte and the character is not ASCII, + make the returning character multibyte. */ + +INLINE int +FETCH_CHAR_AS_MULTIBYTE (ptrdiff_t pos) +{ + return (!NILP (BVAR (current_buffer, enable_multibyte_characters)) + ? FETCH_MULTIBYTE_CHAR (pos) + : UNIBYTE_TO_CHAR (FETCH_BYTE (pos))); +} + +/* Return character at byte position POS. + See the caveat WARNING for FETCH_MULTIBYTE_CHAR above. */ + +INLINE int +FETCH_CHAR (ptrdiff_t pos) +{ + return (!NILP (BVAR (current_buffer, enable_multibyte_characters)) + ? FETCH_MULTIBYTE_CHAR (pos) + : FETCH_BYTE (pos)); +} + +/* Return the address of character at byte position POS in buffer BUF. + Note that both arguments can be computed more than once. */ + +INLINE unsigned char * +BUF_BYTE_ADDRESS (struct buffer *buf, ptrdiff_t pos) +{ + return (buf->text->beg + pos - BEG_BYTE + + (pos < buf->text->gpt_byte ? 0 : buf->text->gap_size)); +} + +/* Return the address of character at char position POS in buffer BUF. + Note that both arguments can be computed more than once. */ + +INLINE unsigned char * +BUF_CHAR_ADDRESS (struct buffer *buf, ptrdiff_t pos) +{ + return (buf->text->beg + buf_charpos_to_bytepos (buf, pos) - BEG_BYTE + + (pos < buf->text->gpt ? 0 : buf->text->gap_size)); +} + +/* Convert PTR, the address of a char in buffer BUF, + into a character position. */ + +INLINE ptrdiff_t +BUF_PTR_BYTE_POS (struct buffer *buf, unsigned char *ptr) +{ + ptrdiff_t byte = ptr - buf->text->beg; + return (byte - (byte <= BUF_GPT_BYTE (buf) - BEG_BYTE ? 0 : BUF_GAP_SIZE (buf)) + + BEG_BYTE); +} + +/* Return the byte at byte position N in buffer BUF. */ + +INLINE unsigned char +BUF_FETCH_BYTE (struct buffer *buf, ptrdiff_t n) +{ + return *BUF_BYTE_ADDRESS (buf, n); +} + +/* Return character at byte position POS in buffer BUF. If BUF is + unibyte and the character is not ASCII, make the returning + character multibyte. */ + +INLINE int +BUF_FETCH_CHAR_AS_MULTIBYTE (struct buffer *buf, ptrdiff_t pos) +{ + return (! NILP (BVAR (buf, enable_multibyte_characters)) + ? BUF_FETCH_MULTIBYTE_CHAR (buf, pos) + : UNIBYTE_TO_CHAR (BUF_FETCH_BYTE (buf, pos))); +} + /* Return number of windows showing B. */ INLINE int @@ -1260,8 +1378,11 @@ #define OVERLAY_PLIST(OV) XOVERLAY (OV)->plist /* Return the actual buffer position for the marker P. We assume you know which buffer it's pointing into. */ -#define OVERLAY_POSITION(P) \ - (MARKERP (P) ? marker_position (P) : (emacs_abort (), 0)) +INLINE ptrdiff_t +OVERLAY_POSITION (Lisp_Object p) +{ + return marker_position (p); +} /*********************************************************************** @@ -1297,16 +1418,22 @@ #define PER_BUFFER_VAR_IDX(VAR) \ /* Value is true if the variable with index IDX has a local value in buffer B. */ -#define PER_BUFFER_VALUE_P(B, IDX) \ - (eassert (valid_per_buffer_idx (IDX)), \ - (B)->local_flags[IDX]) +INLINE bool +PER_BUFFER_VALUE_P (struct buffer *b, int idx) +{ + eassert (valid_per_buffer_idx (idx)); + return b->local_flags[idx]; +} /* Set whether per-buffer variable with index IDX has a buffer-local value in buffer B. VAL zero means it hasn't. */ -#define SET_PER_BUFFER_VALUE_P(B, IDX, VAL) \ - (eassert (valid_per_buffer_idx (IDX)), \ - (B)->local_flags[IDX] = (VAL)) +INLINE void +SET_PER_BUFFER_VALUE_P (struct buffer *b, int idx, bool val) +{ + eassert (valid_per_buffer_idx (idx)); + b->local_flags[idx] = val; +} /* Return the index value of the per-buffer variable at offset OFFSET in the buffer structure. @@ -1326,11 +1453,13 @@ #define SET_PER_BUFFER_VALUE_P(B, IDX, VAL) \ new buffer. If a slot in this structure corresponding to a DEFVAR_PER_BUFFER is - zero, that is a bug */ + zero, that is a bug. */ - -#define PER_BUFFER_IDX(OFFSET) \ - XFIXNUM (*(Lisp_Object *)((OFFSET) + (char *) &buffer_local_flags)) +INLINE int +PER_BUFFER_IDX (ptrdiff_t offset) +{ + return XFIXNUM (*(Lisp_Object *) (offset + (char *) &buffer_local_flags)); +} /* Functions to get and set default value of the per-buffer variable at offset OFFSET in the buffer structure. */ -- 2.17.1