Skip to content

Commit dfed333

Browse files
committed
Remove fixnum restriction on some display vars
This is a minor patch to remove some fixnum restrictions. Many more such patches are needed, but one thing at a time. * doc/emacs/custom.texi (Examining): Update fill-column example. * src/buffer.c (fill-column, left-margin, tab-width) (buffer-saved-size, left-margin-width, right-margin-width) (left-fringe-width, right-fringe-width, scroll-bar-width) (scroll-bar-height, buffer-display-count): Allow any integer; do not restrict to fixnums. * src/character.h (SANE_TAB_WIDTH): Do not assume tab_width is a nonnegative fixnum. (sanitize_tab_width): Take a Lisp_Object integer, not an EMACS_INT. Only use changed. * src/data.c (store_symval_forwarding): Remove unnecessary SYMBOLP since the predicate (e.g., Qintegerp) is always a symbol (leave the test in as an eassert). Avoid assignments inside if-conditions. * src/fileio.c (Fdo_auto_save): Do not assume buffer-saved-size is a fixnum. Avoid undefined behavior on EMACS_INT overflow by multiplying a fixnum by at most 4, not by at most 13. * src/window.c (set_window_buffer): When buffer-display-count is too large for a fixnum, make it a bignum. * src/xdisp.c (FILL_COLUMN_INDICATOR_NEEDED): Remove macro, ... (fill_column_indicator_column): ... replacing with this new function. All uses changed. The function is a bit pickier, to prevent problems with non-character fixnums and columns out of range for int, and to remove the assumption that integers are in fixnum range. (append_space_for_newline, extend_face_to_end_of_line): Avoid undefined behavior with signed integer overflow. Simplify.
1 parent 5c21832 commit dfed333

File tree

8 files changed

+101
-110
lines changed

8 files changed

+101
-110
lines changed

doc/emacs/custom.texi

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -801,6 +801,7 @@ Its value is 70
801801
Automatically becomes buffer-local when set.
802802
This variable is safe as a file local variable if its value
803803
satisfies the predicate ‘integerp’.
804+
Probably introduced at or before Emacs version 18.
804805
805806
Documentation:
806807
Column beyond which automatic line-wrapping should happen.

src/buffer.c

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5603,17 +5603,17 @@ Use the command `abbrev-mode' to change this variable. */);
56035603
doc: /* Non-nil if searches and matches should ignore case. */);
56045604

56055605
DEFVAR_PER_BUFFER ("fill-column", &BVAR (current_buffer, fill_column),
5606-
Qfixnump,
5606+
Qintegerp,
56075607
doc: /* Column beyond which automatic line-wrapping should happen.
56085608
Interactively, you can set the buffer local value using \\[set-fill-column]. */);
56095609

56105610
DEFVAR_PER_BUFFER ("left-margin", &BVAR (current_buffer, left_margin),
5611-
Qfixnump,
5611+
Qintegerp,
56125612
doc: /* Column for the default `indent-line-function' to indent to.
56135613
Linefeed indents to this column in Fundamental mode. */);
56145614

56155615
DEFVAR_PER_BUFFER ("tab-width", &BVAR (current_buffer, tab_width),
5616-
Qfixnump,
5616+
Qintegerp,
56175617
doc: /* Distance between tab stops (for display of tab characters), in columns.
56185618
NOTE: This controls the display width of a TAB character, and not
56195619
the size of an indentation step.
@@ -5784,7 +5784,7 @@ If it is nil, that means don't auto-save this buffer. */);
57845784
Backing up is done before the first time the file is saved. */);
57855785

57865786
DEFVAR_PER_BUFFER ("buffer-saved-size", &BVAR (current_buffer, save_length),
5787-
Qfixnump,
5787+
Qintegerp,
57885788
doc: /* Length of current buffer when last read in, saved or auto-saved.
57895789
0 initially.
57905790
-1 means auto-saving turned off until next real save.
@@ -5858,23 +5858,23 @@ In addition, a char-table has six extra slots to control the display of:
58585858
See also the functions `display-table-slot' and `set-display-table-slot'. */);
58595859

58605860
DEFVAR_PER_BUFFER ("left-margin-width", &BVAR (current_buffer, left_margin_cols),
5861-
Qfixnump,
5861+
Qintegerp,
58625862
doc: /* Width in columns of left marginal area for display of a buffer.
58635863
A value of nil means no marginal area.
58645864
58655865
Setting this variable does not take effect until a new buffer is displayed
58665866
in a window. To make the change take effect, call `set-window-buffer'. */);
58675867

58685868
DEFVAR_PER_BUFFER ("right-margin-width", &BVAR (current_buffer, right_margin_cols),
5869-
Qfixnump,
5869+
Qintegerp,
58705870
doc: /* Width in columns of right marginal area for display of a buffer.
58715871
A value of nil means no marginal area.
58725872
58735873
Setting this variable does not take effect until a new buffer is displayed
58745874
in a window. To make the change take effect, call `set-window-buffer'. */);
58755875

58765876
DEFVAR_PER_BUFFER ("left-fringe-width", &BVAR (current_buffer, left_fringe_width),
5877-
Qfixnump,
5877+
Qintegerp,
58785878
doc: /* Width of this buffer's left fringe (in pixels).
58795879
A value of 0 means no left fringe is shown in this buffer's window.
58805880
A value of nil means to use the left fringe width from the window's frame.
@@ -5883,7 +5883,7 @@ Setting this variable does not take effect until a new buffer is displayed
58835883
in a window. To make the change take effect, call `set-window-buffer'. */);
58845884

58855885
DEFVAR_PER_BUFFER ("right-fringe-width", &BVAR (current_buffer, right_fringe_width),
5886-
Qfixnump,
5886+
Qintegerp,
58875887
doc: /* Width of this buffer's right fringe (in pixels).
58885888
A value of 0 means no right fringe is shown in this buffer's window.
58895889
A value of nil means to use the right fringe width from the window's frame.
@@ -5900,12 +5900,12 @@ Setting this variable does not take effect until a new buffer is displayed
59005900
in a window. To make the change take effect, call `set-window-buffer'. */);
59015901

59025902
DEFVAR_PER_BUFFER ("scroll-bar-width", &BVAR (current_buffer, scroll_bar_width),
5903-
Qfixnump,
5903+
Qintegerp,
59045904
doc: /* Width of this buffer's vertical scroll bars in pixels.
59055905
A value of nil means to use the scroll bar width from the window's frame. */);
59065906

59075907
DEFVAR_PER_BUFFER ("scroll-bar-height", &BVAR (current_buffer, scroll_bar_height),
5908-
Qfixnump,
5908+
Qintegerp,
59095909
doc: /* Height of this buffer's horizontal scroll bars in pixels.
59105910
A value of nil means to use the scroll bar height from the window's frame. */);
59115911

@@ -6175,7 +6175,7 @@ Setting this variable is very fast, much faster than scanning all the text in
61756175
the buffer looking for properties to change. */);
61766176

61776177
DEFVAR_PER_BUFFER ("buffer-display-count",
6178-
&BVAR (current_buffer, display_count), Qfixnump,
6178+
&BVAR (current_buffer, display_count), Qintegerp,
61796179
doc: /* A number incremented each time this buffer is displayed in a window.
61806180
The function `set-window-buffer' increments it. */);
61816181

src/character.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -558,12 +558,13 @@ enum
558558

559559
/* Return a non-outlandish value for the tab width. */
560560

561-
#define SANE_TAB_WIDTH(buf) \
562-
sanitize_tab_width (XFIXNAT (BVAR (buf, tab_width)))
561+
#define SANE_TAB_WIDTH(buf) sanitize_tab_width (BVAR (buf, tab_width))
562+
563563
INLINE int
564-
sanitize_tab_width (EMACS_INT width)
564+
sanitize_tab_width (Lisp_Object width)
565565
{
566-
return 0 < width && width <= 1000 ? width : 8;
566+
return (FIXNUMP (width) && 0 < XFIXNUM (width) && XFIXNUM (width) <= 1000
567+
? XFIXNUM (width) : 8);
567568
}
568569

569570
/* Return the width of ASCII character C. The width is measured by

src/data.c

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1122,20 +1122,21 @@ store_symval_forwarding (lispfwd valcontents, Lisp_Object newval,
11221122
int offset = XBUFFER_OBJFWD (valcontents)->offset;
11231123
Lisp_Object predicate = XBUFFER_OBJFWD (valcontents)->predicate;
11241124

1125-
if (!NILP (newval))
1125+
if (!NILP (newval) && !NILP (predicate))
11261126
{
1127-
if (SYMBOLP (predicate))
1127+
eassert (SYMBOLP (predicate));
1128+
Lisp_Object choiceprop = Fget (predicate, Qchoice);
1129+
if (!NILP (choiceprop))
11281130
{
1129-
Lisp_Object prop;
1130-
1131-
if ((prop = Fget (predicate, Qchoice), !NILP (prop)))
1132-
{
1133-
if (NILP (Fmemq (newval, prop)))
1134-
wrong_choice (prop, newval);
1135-
}
1136-
else if ((prop = Fget (predicate, Qrange), !NILP (prop)))
1131+
if (NILP (Fmemq (newval, choiceprop)))
1132+
wrong_choice (choiceprop, newval);
1133+
}
1134+
else
1135+
{
1136+
Lisp_Object rangeprop = Fget (predicate, Qrange);
1137+
if (CONSP (rangeprop))
11371138
{
1138-
Lisp_Object min = XCAR (prop), max = XCDR (prop);
1139+
Lisp_Object min = XCAR (rangeprop), max = XCDR (rangeprop);
11391140
if (! NUMBERP (newval)
11401141
|| NILP (CALLN (Fleq, min, newval, max)))
11411142
wrong_range (min, max, newval);

src/fileio.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5802,6 +5802,7 @@ A non-nil CURRENT-ONLY argument means save only current buffer. */)
58025802
&& BUF_SAVE_MODIFF (b) < BUF_MODIFF (b)
58035803
&& BUF_AUTOSAVE_MODIFF (b) < BUF_MODIFF (b)
58045804
/* -1 means we've turned off autosaving for a while--see below. */
5805+
&& FIXNUMP (BVAR (b, save_length))
58055806
&& XFIXNUM (BVAR (b, save_length)) >= 0
58065807
&& (do_handled_files
58075808
|| NILP (Ffind_file_name_handler (BVAR (b, auto_save_file_name),
@@ -5815,13 +5816,17 @@ A non-nil CURRENT-ONLY argument means save only current buffer. */)
58155816
&& before_time.tv_sec - b->auto_save_failure_time < 1200)
58165817
continue;
58175818

5819+
enum { growth_factor = 4 };
5820+
verify (BUF_BYTES_MAX <= EMACS_INT_MAX / growth_factor);
5821+
58185822
set_buffer_internal (b);
58195823
if (NILP (Vauto_save_include_big_deletions)
5820-
&& (XFIXNAT (BVAR (b, save_length)) * 10
5821-
> (BUF_Z (b) - BUF_BEG (b)) * 13)
5824+
&& FIXNUMP (BVAR (b, save_length))
58225825
/* A short file is likely to change a large fraction;
58235826
spare the user annoying messages. */
58245827
&& XFIXNAT (BVAR (b, save_length)) > 5000
5828+
&& (growth_factor * (BUF_Z (b) - BUF_BEG (b))
5829+
< (growth_factor - 1) * XFIXNAT (BVAR (b, save_length)))
58255830
/* These messages are frequent and annoying for `*mail*'. */
58265831
&& !NILP (BVAR (b, filename))
58275832
&& NILP (no_message))

src/lisp.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2679,7 +2679,7 @@ struct Lisp_Buffer_Objfwd
26792679
{
26802680
enum Lisp_Fwd_Type type; /* = Lisp_Fwd_Buffer_Obj */
26812681
int offset;
2682-
/* One of Qnil, Qfixnump, Qsymbolp, Qstringp, Qfloatp or Qnumberp. */
2682+
/* One of Qnil, Qintegerp, Qsymbolp, Qstringp, Qfloatp or Qnumberp. */
26832683
Lisp_Object predicate;
26842684
};
26852685

src/window.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3947,8 +3947,8 @@ set_window_buffer (Lisp_Object window, Lisp_Object buffer,
39473947
b->display_error_modiff = 0;
39483948

39493949
/* Update time stamps of buffer display. */
3950-
if (FIXNUMP (BVAR (b, display_count)))
3951-
bset_display_count (b, make_fixnum (XFIXNUM (BVAR (b, display_count)) + 1));
3950+
if (INTEGERP (BVAR (b, display_count)))
3951+
bset_display_count (b, Fadd1 (BVAR (b, display_count)));
39523952
bset_display_time (b, Fcurrent_time ());
39533953

39543954
w->window_end_pos = 0;

src/xdisp.c

Lines changed: 62 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -376,17 +376,26 @@ static Lisp_Object list_of_error;
376376
|| it->s[IT_BYTEPOS (*it)] == '\t')) \
377377
|| (IT_BYTEPOS (*it) < ZV_BYTE \
378378
&& (*BYTE_POS_ADDR (IT_BYTEPOS (*it)) == ' ' \
379-
|| *BYTE_POS_ADDR (IT_BYTEPOS (*it)) == '\t')))) \
380-
381-
/* Test all the conditions needed to print the fill column indicator. */
382-
#define FILL_COLUMN_INDICATOR_NEEDED(it) \
383-
Vdisplay_fill_column_indicator \
384-
&& (it->continuation_lines_width == 0) \
385-
&& (!NILP (Vdisplay_fill_column_indicator_column)) \
386-
&& FIXNATP (Vdisplay_fill_column_indicator_character) \
387-
&& ((EQ (Vdisplay_fill_column_indicator_column, Qt) \
388-
&& FIXNATP (BVAR (current_buffer, fill_column))) \
389-
|| (FIXNATP (Vdisplay_fill_column_indicator_column)))
379+
|| *BYTE_POS_ADDR (IT_BYTEPOS (*it)) == '\t'))))
380+
381+
/* If all the conditions needed to print the fill column indicator are
382+
met, return the (nonnegative) column number, else return a negative
383+
value. */
384+
static int
385+
fill_column_indicator_column (struct it *it)
386+
{
387+
if (Vdisplay_fill_column_indicator
388+
&& it->continuation_lines_width == 0
389+
&& CHARACTERP (Vdisplay_fill_column_indicator_character))
390+
{
391+
Lisp_Object col = (EQ (Vdisplay_fill_column_indicator_column, Qt)
392+
? BVAR (current_buffer, fill_column)
393+
: Vdisplay_fill_column_indicator_column);
394+
if (RANGED_FIXNUMP (0, col, INT_MAX))
395+
return XFIXNUM (col);
396+
}
397+
return -1;
398+
}
390399

391400
/* True means print newline to stdout before next mini-buffer message. */
392401

@@ -20160,37 +20169,31 @@ append_space_for_newline (struct it *it, bool default_face_p)
2016020169
/* Corner case for when display-fill-column-indicator-mode
2016120170
is active and the extra character should be added in the
2016220171
same place than the line. */
20163-
if ((it->w->pseudo_window_p == 0)
20164-
&& FILL_COLUMN_INDICATOR_NEEDED(it))
20172+
int indicator_column = (it->w->pseudo_window_p == 0
20173+
? fill_column_indicator_column (it)
20174+
: -1);
20175+
if (0 <= indicator_column)
2016520176
{
20166-
int fill_column_indicator_column = -1;
20167-
20168-
if (EQ (Vdisplay_fill_column_indicator_column, Qt))
20169-
fill_column_indicator_column =
20170-
XFIXNAT (BVAR (current_buffer, fill_column));
20171-
else
20172-
fill_column_indicator_column =
20173-
XFIXNAT (Vdisplay_fill_column_indicator_column);
20174-
2017520177
struct font *font =
2017620178
default_face->font ?
2017720179
default_face->font : FRAME_FONT (it->f);
2017820180
const int char_width =
2017920181
font->average_width ?
2018020182
font->average_width : font->space_width;
2018120183

20182-
const int column_x =
20183-
char_width * fill_column_indicator_column +
20184-
it->lnum_pixel_width;
20185-
20186-
if (it->current_x == column_x)
20184+
int column_x;
20185+
if (!INT_MULTIPLY_WRAPV (indicator_column, char_width,
20186+
&column_x)
20187+
&& !INT_ADD_WRAPV (it->lnum_pixel_width, column_x,
20188+
&column_x)
20189+
&& it->current_x == column_x)
2018720190
{
2018820191
it->c = it->char_to_display =
2018920192
XFIXNAT (Vdisplay_fill_column_indicator_character);
2019020193
it->face_id =
2019120194
merge_faces (it->w, Qfill_column_indicator,
2019220195
0, saved_face_id);
20193-
face = FACE_FROM_ID(it->f, it->face_id);
20196+
face = FACE_FROM_ID (it->f, it->face_id);
2019420197
goto produce_glyphs;
2019520198
}
2019620199
}
@@ -20422,30 +20425,22 @@ extend_face_to_end_of_line (struct it *it)
2042220425
/* Display fill column indicator if not in modeline or
2042320426
toolbar and display fill column indicator mode is
2042420427
active. */
20425-
if ((it->w->pseudo_window_p == 0)
20426-
&& FILL_COLUMN_INDICATOR_NEEDED(it))
20428+
int indicator_column = (it->w->pseudo_window_p == 0
20429+
? fill_column_indicator_column (it)
20430+
: -1);
20431+
if (0 <= indicator_column)
2042720432
{
20428-
int fill_column_indicator_column = -1;
20429-
20430-
if (EQ (Vdisplay_fill_column_indicator_column, Qt))
20431-
fill_column_indicator_column =
20432-
XFIXNAT (BVAR (current_buffer, fill_column));
20433-
else
20434-
fill_column_indicator_column =
20435-
XFIXNAT (Vdisplay_fill_column_indicator_column);
20436-
2043720433
struct font *font =
2043820434
default_face->font ? default_face->font : FRAME_FONT (f);
2043920435
const int char_width =
2044020436
font->average_width ?
2044120437
font->average_width : font->space_width;
2044220438

20443-
const int column_x =
20444-
char_width * fill_column_indicator_column +
20445-
it->lnum_pixel_width;
20446-
20447-
if ((it->current_x <= column_x)
20448-
&& (column_x <= it->last_visible_x))
20439+
int column_x;
20440+
if (!INT_MULTIPLY_WRAPV (indicator_column, char_width, &column_x)
20441+
&& !INT_ADD_WRAPV (it->lnum_pixel_width, column_x, &column_x)
20442+
&& it->current_x <= column_x
20443+
&& column_x <= it->last_visible_x)
2044920444
{
2045020445
const char saved_char = it->char_to_display;
2045120446
const struct text_pos saved_pos = it->position;
@@ -20625,45 +20620,33 @@ extend_face_to_end_of_line (struct it *it)
2062520620
it->face_id = face->id;
2062620621

2062720622
/* Display fill-column indicator if needed. */
20628-
if (FILL_COLUMN_INDICATOR_NEEDED(it))
20623+
int indicator_column = fill_column_indicator_column (it);
20624+
if (0 <= indicator_column
20625+
&& INT_ADD_WRAPV (it->lnum_pixel_width, indicator_column,
20626+
&indicator_column))
20627+
indicator_column = -1;
20628+
do
2062920629
{
20630-
int fill_column_indicator_column = -1;
20630+
int saved_face_id;
20631+
bool indicate = it->current_x == indicator_column;
20632+
if (indicate)
20633+
{
20634+
saved_face_id = it->face_id;
20635+
it->face_id =
20636+
merge_faces (it->w, Qfill_column_indicator, 0, saved_face_id);
20637+
it->c = it->char_to_display =
20638+
XFIXNAT (Vdisplay_fill_column_indicator_character);
20639+
}
2063120640

20632-
/* Vdisplay_fill_column_indicator_column accepts the special
20633-
value t to use the default fill-column variable. The
20634-
conditions are all defined in the macro
20635-
FILL_COLUMN_INDICATOR_NEEDED. */
20636-
if (EQ (Vdisplay_fill_column_indicator_column, Qt))
20637-
fill_column_indicator_column =
20638-
XFIXNAT (BVAR (current_buffer, fill_column)) + it->lnum_pixel_width;
20639-
else
20640-
fill_column_indicator_column =
20641-
XFIXNAT (Vdisplay_fill_column_indicator_column) + it->lnum_pixel_width;
20641+
PRODUCE_GLYPHS (it);
2064220642

20643-
do
20643+
if (indicate)
2064420644
{
20645-
if (it->current_x == fill_column_indicator_column)
20646-
{
20647-
const int saved_face_id = it->face_id;
20648-
it->face_id =
20649-
merge_faces (it->w, Qfill_column_indicator, 0, saved_face_id);
20650-
it->c = it->char_to_display =
20651-
XFIXNAT (Vdisplay_fill_column_indicator_character);
20652-
PRODUCE_GLYPHS (it);
20653-
it->face_id = saved_face_id;
20654-
it->c = it->char_to_display = ' ';
20655-
}
20656-
else
20657-
PRODUCE_GLYPHS (it);
20658-
} while (it->current_x <= it->last_visible_x);
20645+
it->face_id = saved_face_id;
20646+
it->c = it->char_to_display = ' ';
20647+
}
2065920648
}
20660-
else
20661-
{
20662-
do
20663-
{
20664-
PRODUCE_GLYPHS (it);
20665-
} while (it->current_x <= it->last_visible_x);
20666-
}
20649+
while (it->current_x <= it->last_visible_x);
2066720650

2066820651
if (WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0
2066920652
&& (it->glyph_row->used[RIGHT_MARGIN_AREA]

0 commit comments

Comments
 (0)