]> git.eshelyaron.com Git - emacs.git/commitdiff
DEFVAR_INT variables are now intmax_t
authorPaul Eggert <eggert@cs.ucla.edu>
Wed, 27 Feb 2019 09:14:27 +0000 (01:14 -0800)
committerPaul Eggert <eggert@cs.ucla.edu>
Wed, 27 Feb 2019 09:23:30 +0000 (01:23 -0800)
Formerly they were fixnums, which led to problems when dealing
with values that might not fit on 32-bit platforms, such as
string-chars-consed or floats_consed.  64-bit counters should
be good enough for these (for a while, anyway...).
While we’re at it, fix some unlikely integer overflow bugs
that have been in the code for a while.
* lib-src/make-docfile.c (write_globals):
* src/data.c (do_symval_forwarding, store_symval_forwarding):
* src/eval.c (restore_stack_limits, call_debugger):
* src/frame.h (struct frame.cost_calculation_baud_rate):
* src/keyboard.c (last_auto_save, bind_polling_period, read_char):
* src/lisp.h (struct Lisp_Intfwd.intvar):
* src/lread.c (defvar_int):
* src/pdumper.c (dump_fwd_int):
* src/thread.h (struct thread_state.m_lisp_eval_depth):
* src/undo.c (truncate_undo_list):
* src/xselect.c (wait_for_property_change)
(x_get_foreign_selection):
* src/xterm.c (x_emacs_to_x_modifiers):
DEFVAR_INT variables now have the C type intmax_t, not EMACS_INT.
* src/data.c (store_symval_forwarding):
* src/gnutls.c (Fgnutls_boot):
* src/keyboard.c (bind_polling_period):
* src/macros.c (pop_kbd_macro, Fexecute_kbd_macro):
* src/undo.c (truncate_undo_list):
Allow any integer that fits into intmax_t, instead of
requiring it to be a Lisp fixnum.
* src/dispnew.c (update_window):
* src/frame.c (x_figure_window_size):
* src/gnutls.c (init_gnutls_functions)
(emacs_gnutls_handle_error):
* src/keyboard.c (make_lisp_event):
* src/nsterm.m (ns_dumpglyphs_image):
* src/profiler.c (make_log):
* src/scroll.c (calculate_scrolling)
(calculate_direct_scrolling):
* src/termcap.c (tputs):
* src/xterm.c (x_draw_image_relief):
Avoid implementation-defined behavior on conversion of
out-of-range integers.
* src/eval.c (when_entered_debugger): Now intmax_t.
(max_ensure_room): New function, that avoids signed integer overflow.
(call_debugger, signal_or_quit): Use it.
* src/fileio.c (Fdo_auto_save):
* src/keyboard.c (make_lisp_event):
* src/term.c (calculate_costs):
* src/xdisp.c (build_desired_tool_bar_string)
(hscroll_window_tree, try_scrolling, decode_mode_spec)
(x_produce_glyphs):
Avoid signed integer overflow.
* src/lisp.h (clip_to_bounds): Generalize to intmax_t.
* src/pdumper.c (dump_emacs_reloc_immediate_emacs_int): Remove, ...
(dump_emacs_reloc_immediate_intmax_t): ... replacing with this
function.  All uses changed.
* src/profiler.c (make_log): Omit args.  All callers changed.
* src/termcap.c: Include stdlib.h, for atoi.
Include intprops.h.
* src/window.c (sanitize_next_screen_context_lines): New function.
(window_scroll_pixel_based, window_scroll_line_based):
Use it to avoid signed integer overflow.

24 files changed:
lib-src/make-docfile.c
src/data.c
src/dispnew.c
src/eval.c
src/fileio.c
src/frame.c
src/frame.h
src/gnutls.c
src/keyboard.c
src/lisp.h
src/lread.c
src/macros.c
src/nsterm.m
src/pdumper.c
src/profiler.c
src/scroll.c
src/term.c
src/termcap.c
src/thread.h
src/undo.c
src/window.c
src/xdisp.c
src/xselect.c
src/xterm.c

index c68173eb66c9f9472f97ce489ec5902c53c3376e..05a08473c3f77fb7aa953b100a8fcd012edd4c3a 100644 (file)
@@ -700,7 +700,7 @@ write_globals (void)
       switch (globals[i].type)
        {
        case EMACS_INTEGER:
-         type = "EMACS_INT";
+         type = "intmax_t";
          break;
        case BOOLEAN:
          type = "bool";
index 65f2b0f2f1bf2f0174dfaed7709d3172b6a388fe..15b6106cfe83524ac757a12119352d1607b0eebc 100644 (file)
@@ -985,7 +985,7 @@ do_symval_forwarding (union Lisp_Fwd *valcontents)
   switch (XFWDTYPE (valcontents))
     {
     case Lisp_Fwd_Int:
-      return make_fixnum (*XFIXNUMFWD (valcontents)->intvar);
+      return make_int (*XFIXNUMFWD (valcontents)->intvar);
 
     case Lisp_Fwd_Bool:
       return (*XBOOLFWD (valcontents)->boolvar ? Qt : Qnil);
@@ -1076,8 +1076,13 @@ store_symval_forwarding (union Lisp_Fwd *valcontents, register Lisp_Object newva
   switch (XFWDTYPE (valcontents))
     {
     case Lisp_Fwd_Int:
-      CHECK_FIXNUM (newval);
-      *XFIXNUMFWD (valcontents)->intvar = XFIXNUM (newval);
+      {
+       intmax_t i;
+       CHECK_INTEGER (newval);
+       if (! integer_to_intmax (newval, &i))
+         xsignal1 (Qoverflow_error, newval);
+       *XFIXNUMFWD (valcontents)->intvar = i;
+      }
       break;
 
     case Lisp_Fwd_Bool:
index 300f1c2d70aabfac7e83c6e77bcdb2ffeba40d14..9220213b907ffba772aabdc9e966257af4233e4f 100644 (file)
@@ -3389,7 +3389,7 @@ update_window (struct window *w, bool force_p)
 {
   struct glyph_matrix *desired_matrix = w->desired_matrix;
   bool paused_p;
-  int preempt_count = baud_rate / 2400 + 1;
+  int preempt_count = clip_to_bounds (1, baud_rate / 2400 + 1, INT_MAX);
   struct redisplay_interface *rif = FRAME_RIF (XFRAME (WINDOW_FRAME (w)));
 #ifdef GLYPH_DEBUG
   /* Check that W's frame doesn't have glyph matrices.  */
@@ -4485,16 +4485,13 @@ update_frame_1 (struct frame *f, bool force_p, bool inhibit_id_p,
   struct glyph_matrix *desired_matrix = f->desired_matrix;
   int i;
   bool pause_p;
-  int preempt_count = baud_rate / 2400 + 1;
+  int preempt_count = clip_to_bounds (1, baud_rate / 2400 + 1, INT_MAX);
 
   eassert (current_matrix && desired_matrix);
 
   if (baud_rate != FRAME_COST_BAUD_RATE (f))
     calculate_costs (f);
 
-  if (preempt_count <= 0)
-    preempt_count = 1;
-
   if (!force_p && detect_input_pending_ignore_squeezables ())
     {
       pause_p = 1;
index b6cdfc911d0030de2fb90986e0daa1e5f4c7370d..bf16a709b1511e91b5539c40f9a9a78af48207a3 100644 (file)
@@ -56,26 +56,6 @@ Lisp_Object Vautoload_queue;
    is shutting down.  */
 Lisp_Object Vrun_hooks;
 
-/* The commented-out variables below are macros defined in thread.h.  */
-
-/* Current number of specbindings allocated in specpdl, not counting
-   the dummy entry specpdl[-1].  */
-
-/* ptrdiff_t specpdl_size; */
-
-/* Pointer to beginning of specpdl.  A dummy entry specpdl[-1] exists
-   only so that its address can be taken.  */
-
-/* union specbinding *specpdl; */
-
-/* Pointer to first unused element in specpdl.  */
-
-/* union specbinding *specpdl_ptr; */
-
-/* Depth in Lisp evaluations and function calls.  */
-
-/* static EMACS_INT lisp_eval_depth; */
-
 /* The value of num_nonmacro_input_events as of the last time we
    started to enter the debugger.  If we decide to enter the debugger
    again when this is still equal to num_nonmacro_input_events, then we
@@ -83,7 +63,7 @@ Lisp_Object Vrun_hooks;
    signal the error instead of entering an infinite loop of debugger
    invocations.  */
 
-static EMACS_INT when_entered_debugger;
+static intmax_t when_entered_debugger;
 
 /* The function from which the last `signal' was called.  Set in
    Fsignal.  */
@@ -285,13 +265,23 @@ init_eval (void)
   when_entered_debugger = -1;
 }
 
+/* Ensure that *M is at least A + B if possible, or is its maximum
+   value otherwise.  */
+
+static void
+max_ensure_room (intmax_t *m, intmax_t a, intmax_t b)
+{
+  intmax_t sum = INT_ADD_WRAPV (a, b, &sum) ? INTMAX_MAX : sum;
+  *m = max (*m, sum);
+}
+
 /* Unwind-protect function used by call_debugger.  */
 
 static void
 restore_stack_limits (Lisp_Object data)
 {
-  max_specpdl_size = XFIXNUM (XCAR (data));
-  max_lisp_eval_depth = XFIXNUM (XCDR (data));
+  integer_to_intmax (XCAR (data), &max_specpdl_size);
+  integer_to_intmax (XCDR (data), &max_lisp_eval_depth);
 }
 
 static void grow_specpdl (void);
@@ -304,21 +294,19 @@ call_debugger (Lisp_Object arg)
   bool debug_while_redisplaying;
   ptrdiff_t count = SPECPDL_INDEX ();
   Lisp_Object val;
-  EMACS_INT old_depth = max_lisp_eval_depth;
+  intmax_t old_depth = max_lisp_eval_depth;
   /* Do not allow max_specpdl_size less than actual depth (Bug#16603).  */
-  EMACS_INT old_max = max (max_specpdl_size, count);
+  intmax_t old_max = max (max_specpdl_size, count);
 
   /* The previous value of 40 is too small now that the debugger
      prints using cl-prin1 instead of prin1.  Printing lists nested 8
      deep (which is the value of print-level used in the debugger)
      currently requires 77 additional frames.  See bug#31919.  */
-  if (lisp_eval_depth + 100 > max_lisp_eval_depth)
-    max_lisp_eval_depth = lisp_eval_depth + 100;
+  max_ensure_room (&max_lisp_eval_depth, lisp_eval_depth, 100);
 
   /* While debugging Bug#16603, previous value of 100 was found
      too small to avoid specpdl overflow in the debugger itself.  */
-  if (max_specpdl_size - 200 < count)
-    max_specpdl_size = count + 200;
+  max_ensure_room (&max_specpdl_size, count, 200);
 
   if (old_max == count)
     {
@@ -329,8 +317,7 @@ call_debugger (Lisp_Object arg)
 
   /* Restore limits after leaving the debugger.  */
   record_unwind_protect (restore_stack_limits,
-                        Fcons (make_fixnum (old_max),
-                               make_fixnum (old_depth)));
+                        Fcons (make_int (old_max), make_int (old_depth)));
 
 #ifdef HAVE_WINDOW_SYSTEM
   if (display_hourglass_p)
@@ -1654,11 +1641,8 @@ signal_or_quit (Lisp_Object error_symbol, Lisp_Object data, bool keyboard_quit)
       && specpdl_ptr < specpdl + specpdl_size)
     {
       /* Edebug takes care of restoring these variables when it exits.  */
-      if (lisp_eval_depth + 20 > max_lisp_eval_depth)
-       max_lisp_eval_depth = lisp_eval_depth + 20;
-
-      if (SPECPDL_INDEX () + 40 > max_specpdl_size)
-       max_specpdl_size = SPECPDL_INDEX () + 40;
+      max_ensure_room (&max_lisp_eval_depth, lisp_eval_depth, 20);
+      max_ensure_room (&max_specpdl_size, SPECPDL_INDEX (), 40);
 
       call2 (Vsignal_hook_function, error_symbol, data);
     }
index 55c9f26b7539b73644ecb51d89dddd6d68053c98..cac8ed0aeef696f7aeb9471d67a7792098fa421c 100644 (file)
@@ -5706,8 +5706,9 @@ A non-nil CURRENT-ONLY argument means save only current buffer.  */)
   bool old_message_p = 0;
   struct auto_save_unwind auto_save_unwind;
 
-  if (max_specpdl_size < specpdl_size + 40)
-    max_specpdl_size = specpdl_size + 40;
+  intmax_t sum = INT_ADD_WRAPV (specpdl_size, 40, &sum) ? INTMAX_MAX : sum;
+  if (max_specpdl_size < sum)
+    max_specpdl_size = sum;
 
   if (minibuf_level)
     no_message = Qt;
index aa1a15ff006a3b4a2ef2f77d058611d19cae1232..d1d6993e94b85364aadb80bf13946c01a27d7ba2 100644 (file)
@@ -5309,9 +5309,9 @@ x_figure_window_size (struct frame *f, Lisp_Object parms, bool toolbar_p, int *x
        {
          int margin, relief;
 
-         relief = (tool_bar_button_relief >= 0
-                   ? tool_bar_button_relief
-                   : DEFAULT_TOOL_BAR_BUTTON_RELIEF);
+         relief = (tool_bar_button_relief < 0
+                   ? DEFAULT_TOOL_BAR_BUTTON_RELIEF
+                   : min (tool_bar_button_relief, 1000000));
 
          if (RANGED_FIXNUMP (1, Vtool_bar_button_margin, INT_MAX))
            margin = XFIXNAT (Vtool_bar_button_margin);
index b7cbdd955717744c2b8dfa3c84fc45c3aeb2f13e..544e0bef17ac0351fda8373634fbc194ebf84426 100644 (file)
@@ -580,7 +580,7 @@ struct frame
   int config_scroll_bar_lines;
 
   /* The baud rate that was used to calculate costs for this frame.  */
-  int cost_calculation_baud_rate;
+  intmax_t cost_calculation_baud_rate;
 
   /* Frame opacity
      alpha[0]: alpha transparency of the active frame
index 63dbcf4162b7722c9a8b966fb0055ed42b90877d..2951c8d074ccfafffe6c08588e4d1ad4c33d1938 100644 (file)
@@ -395,8 +395,7 @@ init_gnutls_functions (void)
 #   endif
 #  endif        /* HAVE_GNUTLS3 */
 
-  max_log_level = global_gnutls_log_level;
-
+  max_log_level = clip_to_bounds (INT_MIN, global_gnutls_log_level, INT_MAX);
   {
     Lisp_Object name = CAR_SAFE (Fget (Qgnutls, QCloaded_from));
     GNUTLS_LOG2 (1, max_log_level, "GnuTLS library loaded:",
@@ -760,7 +759,8 @@ emacs_gnutls_handle_error (gnutls_session_t session, int err)
 
   check_memory_full (err);
 
-  int max_log_level = global_gnutls_log_level;
+  int max_log_level
+    = clip_to_bounds (INT_MIN, global_gnutls_log_level, INT_MAX);
 
   /* TODO: use gnutls-error-fatalp and gnutls-error-string.  */
 
@@ -1691,14 +1691,17 @@ one trustfile (usually a CA bundle).  */)
 
   state = XPROCESS (proc)->gnutls_state;
 
-  if (TYPE_RANGED_FIXNUMP (int, loglevel))
+  if (INTEGERP (loglevel))
     {
       gnutls_global_set_log_function (gnutls_log_function);
 # ifdef HAVE_GNUTLS3
       gnutls_global_set_audit_log_function (gnutls_audit_log_function);
 # endif
-      gnutls_global_set_log_level (XFIXNUM (loglevel));
-      max_log_level = XFIXNUM (loglevel);
+      int level = (FIXNUMP (loglevel)
+                  ? clip_to_bounds (INT_MIN, XFIXNUM (loglevel), INT_MAX)
+                  : NILP (Fnatnump (loglevel)) ? INT_MIN : INT_MAX);
+      gnutls_global_set_log_level (level);
+      max_log_level = level;
       XPROCESS (proc)->gnutls_log_level = max_log_level;
     }
 
index 1d67c3eaabdd12105c68b8634c632bee1df850f6..3af487cf0705443f5da3eecc589f9a03b9fe8540 100644 (file)
@@ -208,7 +208,7 @@ struct buffer *buffer_before_last_command_or_undo;
 
 /* Value of num_nonmacro_input_events as of last auto save.  */
 
-static EMACS_INT last_auto_save;
+static intmax_t last_auto_save;
 
 /* The value of point when the last command was started. */
 static ptrdiff_t last_point_position;
@@ -1213,7 +1213,7 @@ some_mouse_moved (void)
 
   if (ignore_mouse_drag_p)
     {
-      /* ignore_mouse_drag_p = 0; */
+      /* ignore_mouse_drag_p = false; */
       return 0;
     }
 
@@ -1301,7 +1301,7 @@ command_loop_1 (void)
         loop.  (This flag is set in xdisp.c whenever the tool bar is
         resized, because the resize moves text up or down, and would
         generate false mouse drag events if we don't ignore them.)  */
-      ignore_mouse_drag_p = 0;
+      ignore_mouse_drag_p = false;
 
       /* If minibuffer on and echo area in use,
         wait a short time and redraw minibuffer.  */
@@ -1966,14 +1966,14 @@ void
 bind_polling_period (int n)
 {
 #ifdef POLL_FOR_INPUT
-  EMACS_INT new = polling_period;
+  intmax_t new = polling_period;
 
   if (n > new)
     new = n;
 
   stop_other_atimers (poll_timer);
   stop_polling ();
-  specbind (Qpolling_period, make_fixnum (new));
+  specbind (Qpolling_period, make_int (new));
   /* Start a new alarm with the new period.  */
   start_polling ();
 #endif
@@ -2422,7 +2422,7 @@ read_char (int commandflag, Lisp_Object map,
          goto exit;
        }
 
-      c = Faref (Vexecuting_kbd_macro, make_fixnum (executing_kbd_macro_index));
+      c = Faref (Vexecuting_kbd_macro, make_int (executing_kbd_macro_index));
       if (STRINGP (Vexecuting_kbd_macro)
          && (XFIXNAT (c) & 0x80) && (XFIXNAT (c) <= 0xff))
        XSETFASTINT (c, CHAR_META | (XFIXNAT (c) & ~0x80));
@@ -5585,7 +5585,7 @@ make_lispy_event (struct input_event *event)
             double-click-fuzz as is.  On other frames, interpret it
             as a multiple of 1/8 characters.  */
          struct frame *f;
-         int fuzz;
+         intmax_t fuzz;
 
          if (WINDOWP (event->frame_or_window))
            f = XFRAME (XWINDOW (event->frame_or_window)->frame);
@@ -5628,7 +5628,7 @@ make_lispy_event (struct input_event *event)
              double_click_count = 1;
            button_down_time = event->timestamp;
            *start_pos_ptr = Fcopy_alist (position);
-           ignore_mouse_drag_p = 0;
+           ignore_mouse_drag_p = false;
          }
 
        /* Now we're releasing a button - check the co-ordinates to
@@ -5644,11 +5644,14 @@ make_lispy_event (struct input_event *event)
            if (!CONSP (start_pos))
              return Qnil;
 
-           event->modifiers &= ~up_modifier;
+           unsigned click_or_drag_modifier = click_modifier;
 
+           if (ignore_mouse_drag_p)
+             ignore_mouse_drag_p = false;
+           else
              {
                Lisp_Object new_down, down;
-               EMACS_INT xdiff = double_click_fuzz, ydiff = double_click_fuzz;
+               intmax_t xdiff = double_click_fuzz, ydiff = double_click_fuzz;
 
                /* The third element of every position
                   should be the (x,y) pair.  */
@@ -5662,39 +5665,37 @@ make_lispy_event (struct input_event *event)
                    ydiff = XFIXNUM (XCDR (new_down)) - XFIXNUM (XCDR (down));
                  }
 
-               if (ignore_mouse_drag_p)
-                 {
-                   event->modifiers |= click_modifier;
-                   ignore_mouse_drag_p = 0;
-                 }
-               else if (xdiff < double_click_fuzz && xdiff > - double_click_fuzz
-                        && ydiff < double_click_fuzz && ydiff > - double_click_fuzz
-                 /* Maybe the mouse has moved a lot, caused scrolling, and
-                    eventually ended up at the same screen position (but
-                    not buffer position) in which case it is a drag, not
-                    a click.  */
-                   /* FIXME: OTOH if the buffer position has changed
-                      because of a timer or process filter rather than
-                      because of mouse movement, it should be considered as
-                      a click.  But mouse-drag-region completely ignores
-                      this case and it hasn't caused any real problem, so
-                      it's probably OK to ignore it as well.  */
-                   && EQ (Fcar (Fcdr (start_pos)), Fcar (Fcdr (position))))
-                 /* Mouse hasn't moved (much).  */
-                 event->modifiers |= click_modifier;
-               else
+               if (! (0 < double_click_fuzz
+                      && - double_click_fuzz < xdiff
+                      && xdiff < double_click_fuzz
+                      && - double_click_fuzz < ydiff
+                      && ydiff < double_click_fuzz
+                      /* Maybe the mouse has moved a lot, caused scrolling, and
+                         eventually ended up at the same screen position (but
+                         not buffer position) in which case it is a drag, not
+                         a click.  */
+                      /* FIXME: OTOH if the buffer position has changed
+                         because of a timer or process filter rather than
+                         because of mouse movement, it should be considered as
+                         a click.  But mouse-drag-region completely ignores
+                         this case and it hasn't caused any real problem, so
+                         it's probably OK to ignore it as well.  */
+                      && EQ (Fcar (Fcdr (start_pos)), Fcar (Fcdr (position)))))
                  {
+                   /* Mouse has moved enough.  */
                    button_down_time = 0;
-                   event->modifiers |= drag_modifier;
+                   click_or_drag_modifier = drag_modifier;
                  }
-
-               /* Don't check is_double; treat this as multiple
-                  if the down-event was multiple.  */
-               if (double_click_count > 1)
-                 event->modifiers |= ((double_click_count > 2)
-                                      ? triple_modifier
-                                      : double_modifier);
              }
+
+           /* Don't check is_double; treat this as multiple if the
+              down-event was multiple.  */
+           event->modifiers
+             = ((event->modifiers & ~up_modifier)
+                | click_or_drag_modifier
+                | (double_click_count < 2 ? 0
+                   : double_click_count == 2 ? double_modifier
+                   : triple_modifier));
          }
        else
          /* Every mouse event should either have the down_modifier or
@@ -5743,7 +5744,7 @@ make_lispy_event (struct input_event *event)
             double-click-fuzz as is.  On other frames, interpret it
             as a multiple of 1/8 characters.  */
          struct frame *fr;
-         int fuzz;
+         intmax_t fuzz;
          int symbol_num;
          bool is_double;
 
index 3b481089cfd9bc1ee3f0fc6ebc436ff4c72f2eae..388cd04163abedec467a9d813556f7a4699cac77 100644 (file)
@@ -1260,8 +1260,8 @@ INLINE bool
 #define FIXNUM_OVERFLOW_P(i) \
   (! ((0 <= (i) || MOST_NEGATIVE_FIXNUM <= (i)) && (i) <= MOST_POSITIVE_FIXNUM))
 
-INLINE ptrdiff_t
-clip_to_bounds (ptrdiff_t lower, EMACS_INT num, ptrdiff_t upper)
+INLINE intmax_t
+clip_to_bounds (intmax_t lower, intmax_t num, intmax_t upper)
 {
   return num < lower ? lower : num <= upper ? num : upper;
 }
@@ -2664,7 +2664,7 @@ make_uint (uintmax_t n)
 struct Lisp_Intfwd
   {
     enum Lisp_Fwd_Type type;   /* = Lisp_Fwd_Int */
-    EMACS_INT *intvar;
+    intmax_t *intvar;
   };
 
 /* Boolean forwarding pointer to an int variable.
@@ -3099,7 +3099,7 @@ enum maxargs
 extern void defvar_lisp (struct Lisp_Objfwd *, const char *, Lisp_Object *);
 extern void defvar_lisp_nopro (struct Lisp_Objfwd *, const char *, Lisp_Object *);
 extern void defvar_bool (struct Lisp_Boolfwd *, const char *, bool *);
-extern void defvar_int (struct Lisp_Intfwd *, const char *, EMACS_INT *);
+extern void defvar_int (struct Lisp_Intfwd *, const char *, intmax_t *);
 extern void defvar_kboard (struct Lisp_Kboard_Objfwd *, const char *, int);
 
 /* Macros we use to define forwarded Lisp variables.
index 6389e3ed48e03dc1d406799f9494b2b20594fcd3..8b0d693daf2b7257e1ec1369e41d25525ed2ff0a 100644 (file)
@@ -4422,11 +4422,11 @@ defalias (struct Lisp_Subr *sname, char *string)
 #endif /* NOTDEF */
 
 /* Define an "integer variable"; a symbol whose value is forwarded to a
-   C variable of type EMACS_INT.  Sample call (with "xx" to fool make-docfile):
+   C variable of type intmax_t.  Sample call (with "xx" to fool make-docfile):
    DEFxxVAR_INT ("emacs-priority", &emacs_priority, "Documentation");  */
 void
 defvar_int (struct Lisp_Intfwd *i_fwd,
-           const char *namestring, EMACS_INT *address)
+           const char *namestring, intmax_t *address)
 {
   Lisp_Object sym;
   sym = intern_c_string (namestring);
index eaf9c83fb887c3ddcc9ca4d59da6c4ad1a9cfe41..2d927ffc40890831752fd20f41d7c49d58bf209d 100644 (file)
@@ -267,7 +267,7 @@ pop_kbd_macro (Lisp_Object info)
   Lisp_Object tem;
   Vexecuting_kbd_macro = XCAR (info);
   tem = XCDR (info);
-  executing_kbd_macro_index = XFIXNUM (XCAR (tem));
+  integer_to_intmax (XCAR (tem), &executing_kbd_macro_index);
   Vreal_this_command = XCDR (tem);
   run_hook (Qkbd_macro_termination_hook);
 }
@@ -301,7 +301,7 @@ each iteration of the macro.  Iteration stops if LOOPFUNC returns nil.  */)
     error ("Keyboard macros must be strings or vectors");
 
   tem = Fcons (Vexecuting_kbd_macro,
-              Fcons (make_fixnum (executing_kbd_macro_index),
+              Fcons (make_int (executing_kbd_macro_index),
                      Vreal_this_command));
   record_unwind_protect (pop_kbd_macro, tem);
 
index 2bf3e0078603507318a4890b6e1137ffad64201f..d0fe206d2e3f20aba4b52af0e9d69b2e7eac83ab 100644 (file)
@@ -3911,8 +3911,9 @@ ns_dumpglyphs_image (struct glyph_string *s, NSRect r)
     {
       if (s->hl == DRAW_IMAGE_SUNKEN || s->hl == DRAW_IMAGE_RAISED)
         {
-          th = tool_bar_button_relief >= 0 ?
-            tool_bar_button_relief : DEFAULT_TOOL_BAR_BUTTON_RELIEF;
+          th = (tool_bar_button_relief < 0
+               ? DEFAULT_TOOL_BAR_BUTTON_RELIEF
+               : min (tool_bar_button_relief, 1000000));
           raised_p = (s->hl == DRAW_IMAGE_RAISED);
         }
       else
index 301a52804f0b3e313832c0544d7f6acc6bba0148..2f5c7198032ce184518b5456c2da71f9b4765812 100644 (file)
@@ -1615,7 +1615,7 @@ dump_emacs_reloc_immediate (struct dump_context *ctx,
 
 DEFINE_EMACS_IMMEDIATE_FN (dump_emacs_reloc_immediate_lv, Lisp_Object);
 DEFINE_EMACS_IMMEDIATE_FN (dump_emacs_reloc_immediate_ptrdiff_t, ptrdiff_t);
-DEFINE_EMACS_IMMEDIATE_FN (dump_emacs_reloc_immediate_emacs_int, EMACS_INT);
+DEFINE_EMACS_IMMEDIATE_FN (dump_emacs_reloc_immediate_intmax_t, intmax_t);
 DEFINE_EMACS_IMMEDIATE_FN (dump_emacs_reloc_immediate_int, int);
 DEFINE_EMACS_IMMEDIATE_FN (dump_emacs_reloc_immediate_bool, bool);
 
@@ -2286,10 +2286,10 @@ dump_float (struct dump_context *ctx, const struct Lisp_Float *lfloat)
 static dump_off
 dump_fwd_int (struct dump_context *ctx, const struct Lisp_Intfwd *intfwd)
 {
-#if CHECK_STRUCTS && !defined (HASH_Lisp_Intfwd_1225FA32CC)
+#if CHECK_STRUCTS && !defined HASH_Lisp_Intfwd_4D887A7387
 # error "Lisp_Intfwd changed. See CHECK_STRUCTS comment."
 #endif
-  dump_emacs_reloc_immediate_emacs_int (ctx, intfwd->intvar, *intfwd->intvar);
+  dump_emacs_reloc_immediate_intmax_t (ctx, intfwd->intvar, *intfwd->intvar);
   struct Lisp_Intfwd out;
   dump_object_start (ctx, &out, sizeof (out));
   DUMP_FIELD_COPY (&out, intfwd, type);
index 2aa5f345740e2250b68809c587c13437e0785414..87be30acc309c94c3a7eac8f39d145fb7e981bfe 100644 (file)
@@ -52,12 +52,16 @@ static const struct hash_table_test hashtest_profiler =
   };
 
 static Lisp_Object
-make_log (EMACS_INT heap_size, EMACS_INT max_stack_depth)
+make_log (void)
 {
   /* We use a standard Elisp hash-table object, but we use it in
      a special way.  This is OK as long as the object is not exposed
      to Elisp, i.e. until it is returned by *-profiler-log, after which
      it can't be used any more.  */
+  EMACS_INT heap_size
+    = clip_to_bounds (0, profiler_log_size, MOST_POSITIVE_FIXNUM);
+  ptrdiff_t max_stack_depth
+    = clip_to_bounds (0, profiler_max_stack_depth, PTRDIFF_MAX);;
   Lisp_Object log = make_hash_table (hashtest_profiler, heap_size,
                                     DEFAULT_REHASH_SIZE,
                                     DEFAULT_REHASH_THRESHOLD,
@@ -342,8 +346,7 @@ See also `profiler-log-size' and `profiler-max-stack-depth'.  */)
   if (NILP (cpu_log))
     {
       cpu_gc_count = 0;
-      cpu_log = make_log (profiler_log_size,
-                         profiler_max_stack_depth);
+      cpu_log = make_log ();
     }
 
   int status = setup_cpu_timer (sampling_interval);
@@ -419,9 +422,7 @@ Before returning, a new log is allocated for future samples.  */)
   /* Here we're making the log visible to Elisp, so it's not safe any
      more for our use afterwards since we can't rely on its special
      pre-allocated keys anymore.  So we have to allocate a new one.  */
-  cpu_log = (profiler_cpu_running
-            ? make_log (profiler_log_size, profiler_max_stack_depth)
-            : Qnil);
+  cpu_log = profiler_cpu_running ? make_log () : Qnil;
   Fputhash (make_vector (1, QAutomatic_GC),
            make_fixnum (cpu_gc_count),
            result);
@@ -450,8 +451,7 @@ See also `profiler-log-size' and `profiler-max-stack-depth'.  */)
     error ("Memory profiler is already running");
 
   if (NILP (memory_log))
-    memory_log = make_log (profiler_log_size,
-                          profiler_max_stack_depth);
+    memory_log = make_log ();
 
   profiler_memory_running = true;
 
@@ -494,9 +494,7 @@ Before returning, a new log is allocated for future samples.  */)
   /* Here we're making the log visible to Elisp , so it's not safe any
      more for our use afterwards since we can't rely on its special
      pre-allocated keys anymore.  So we have to allocate a new one.  */
-  memory_log = (profiler_memory_running
-               ? make_log (profiler_log_size, profiler_max_stack_depth)
-               : Qnil);
+  memory_log = profiler_memory_running ? make_log () : Qnil;
   return result;
 }
 
index e523a19ab890f14ef3ffe9093c4d62cf7a8cba1e..8eda510945f3c71ff09edc33867d15cd47bdb5e7 100644 (file)
@@ -107,10 +107,8 @@ calculate_scrolling (struct frame *frame,
   /* Discourage long scrolls on fast lines.
      Don't scroll nearly a full frame height unless it saves
      at least 1/4 second.  */
-  int extra_cost = baud_rate / (10 * 4 * frame_total_lines);
-
-  if (baud_rate <= 0)
-    extra_cost = 1;
+  int extra_cost
+    = clip_to_bounds (1, baud_rate / (10 * 4) / frame_total_lines, INT_MAX / 2);
 
   /* initialize the top left corner of the matrix */
   matrix->writecost = 0;
@@ -446,10 +444,8 @@ calculate_direct_scrolling (struct frame *frame,
   /* Discourage long scrolls on fast lines.
      Don't scroll nearly a full frame height unless it saves
      at least 1/4 second.  */
-  int extra_cost = baud_rate / (10 * 4 * frame_total_lines);
-
-  if (baud_rate <= 0)
-    extra_cost = 1;
+  int extra_cost
+    = clip_to_bounds (1, baud_rate / (10 * 4) / frame_total_lines, INT_MAX / 2);
 
   /* Overhead of setting the scroll window, plus the extra
      cost of scrolling by a distance of one.  The extra cost is
index 60ee86194841c526829e6fcd71d2ff9743cbd2cd..a492276c888fc4058f092f4fdb035c0c6f17b9e2 100644 (file)
@@ -1201,7 +1201,9 @@ calculate_costs (struct frame *frame)
       calculate_ins_del_char_costs (frame);
 
       /* Don't use TS_repeat if its padding is worse than sending the chars */
-      if (tty->TS_repeat && per_line_cost (tty->TS_repeat) * baud_rate < 9000)
+      if (tty->TS_repeat
+         && (baud_rate <= 0
+             || per_line_cost (tty->TS_repeat) < 9000 / baud_rate))
         tty->RPov = string_cost (tty->TS_repeat);
       else
         tty->RPov = FRAME_COLS (frame) * 2;
index 2f2a0b29d5e3a6a01bb7f0edf6e707e5f50f02b4..9e081baa62e82b2e16ddb1bc8f94c8a32cf31493 100644 (file)
@@ -20,10 +20,14 @@ along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
 
 /* Emacs config.h may rename various library functions such as malloc.  */
 #include <config.h>
+
+#include <stdlib.h>
 #include <sys/file.h>
 #include <fcntl.h>
 #include <unistd.h>
 
+#include <intprops.h>
+
 #include "lisp.h"
 #include "tparam.h"
 #ifdef MSDOS
@@ -265,14 +269,7 @@ char PC;
 void
 tputs (register const char *str, int nlines, int (*outfun) (int))
 {
-  register int padcount = 0;
-  register int speed;
-
-  speed = baud_rate;
-  /* For quite high speeds, convert to the smaller
-     units to avoid overflow.  */
-  if (speed > 10000)
-    speed = - speed / 100;
+  int padcount = 0;
 
   if (!str)
     return;
@@ -296,21 +293,13 @@ tputs (register const char *str, int nlines, int (*outfun) (int))
     (*outfun) (*str++);
 
   /* PADCOUNT is now in units of tenths of msec.
-     SPEED is measured in characters per 10 seconds
-     or in characters per .1 seconds (if negative).
-     We use the smaller units for larger speeds to avoid overflow.  */
-  padcount *= speed;
-  padcount += 500;
-  padcount /= 1000;
-  if (speed < 0)
-    padcount = -padcount;
-  else
-    {
-      padcount += 50;
-      padcount /= 100;
-    }
+     BAUD_RATE is measured in characters per 10 seconds.
+     Compute PADFACTOR = 100000 * (how many padding bytes are needed).  */
+  intmax_t padfactor;
+  if (INT_MULTIPLY_WRAPV (padcount, baud_rate, &padfactor))
+    padfactor = baud_rate < 0 ? INTMAX_MIN : INTMAX_MAX;
 
-  while (padcount-- > 0)
+  for (; 50000 <= padfactor; padfactor -= 100000)
     (*outfun) (PC);
 }
 \f
@@ -426,7 +415,7 @@ tgetent (char *bp, const char *name)
     }
 
   if (!termcap_name || !filep)
-    termcap_name = TERMCAP_FILE;
+    termcap_name = (char *) TERMCAP_FILE;
 
   /* Here we know we must search a file and termcap_name has its name.  */
 
index 5e003761e8510c4b7ede3f76de8167cb05b537da..e46545baf27678b40bad3bb88a2633c965ef6ba4 100644 (file)
@@ -104,7 +104,7 @@ struct thread_state
 #define specpdl_ptr (current_thread->m_specpdl_ptr)
 
   /* Depth in Lisp evaluations and function calls.  */
-  EMACS_INT m_lisp_eval_depth;
+  intmax_t m_lisp_eval_depth;
 #define lisp_eval_depth (current_thread->m_lisp_eval_depth)
 
   /* This points to the current buffer.  */
index 2929f7921285bfcb6e02727943b1110d83271e06..3c1251dae6e713cd6bbe51a271ddea07e0bb7184 100644 (file)
@@ -291,7 +291,7 @@ truncate_undo_list (struct buffer *b)
 {
   Lisp_Object list;
   Lisp_Object prev, next, last_boundary;
-  EMACS_INT size_so_far = 0;
+  intmax_t size_so_far = 0;
 
   /* Make sure that calling undo-outer-limit-function
      won't cause another GC.  */
@@ -348,14 +348,17 @@ truncate_undo_list (struct buffer *b)
 
   /* If by the first boundary we have already passed undo_outer_limit,
      we're heading for memory full, so offer to clear out the list.  */
-  if (FIXNUMP (Vundo_outer_limit)
-      && size_so_far > XFIXNUM (Vundo_outer_limit)
+  intmax_t undo_outer_limit;
+  if ((INTEGERP (Vundo_outer_limit)
+       && (integer_to_intmax (Vundo_outer_limit, &undo_outer_limit)
+          ? undo_outer_limit < size_so_far
+          : NILP (Fnatnump (Vundo_outer_limit))))
       && !NILP (Vundo_outer_limit_function))
     {
       Lisp_Object tem;
 
       /* Normally the function this calls is undo-outer-limit-truncate.  */
-      tem = call1 (Vundo_outer_limit_function, make_fixnum (size_so_far));
+      tem = call1 (Vundo_outer_limit_function, make_int (size_so_far));
       if (! NILP (tem))
        {
          /* The function is responsible for making
index 49d7fc2426ba74d953c8eb88ad9e74df4bf14fcd..fe685d5ab093c1cb625501b0414fdaa9de208b22 100644 (file)
@@ -5445,6 +5445,11 @@ window_scroll_margin (struct window *window, enum margin_unit unit)
     return 0;
 }
 
+static int
+sanitize_next_screen_context_lines (void)
+{
+  return clip_to_bounds (0, next_screen_context_lines, 1000000);
+}
 
 /* Implementation of window_scroll that works based on pixel line
    heights.  See the comment of window_scroll for parameter
@@ -5515,9 +5520,11 @@ window_scroll_pixel_based (Lisp_Object window, int n, bool whole, bool noerror)
             height.  This is important to ensure we get back to the
             same position when scrolling up, then down.  */
          if (whole)
-           dy = max ((window_box_height (w) / dy
-                      - next_screen_context_lines) * dy,
-                     dy);
+           {
+             int ht = window_box_height (w);
+             int nscls = sanitize_next_screen_context_lines ();
+             dy = max (dy, (ht / dy - nscls) * dy);
+           }
          dy *= n;
 
          if (n < 0)
@@ -5598,13 +5605,14 @@ window_scroll_pixel_based (Lisp_Object window, int n, bool whole, bool noerror)
     {
       ptrdiff_t start_pos = IT_CHARPOS (it);
       int dy = frame_line_height;
+      int ht = window_box_height (w);
+      int nscls = sanitize_next_screen_context_lines ();
       /* In the below we divide the window box height by the frame's
         line height to make the result predictable when the window
         box is not an integral multiple of the line height.  This is
         important to ensure we get back to the same position when
         scrolling up, then down.  */
-      dy = max ((window_box_height (w) / dy - next_screen_context_lines) * dy,
-               dy) * n;
+      dy = n * max (dy, (ht / dy - nscls) * dy);
 
       /* Note that move_it_vertically always moves the iterator to the
          start of a line.  So, if the last line doesn't have a newline,
@@ -5902,7 +5910,10 @@ window_scroll_line_based (Lisp_Object window, int n, bool whole, bool noerror)
   /* If scrolling screen-fulls, compute the number of lines to
      scroll from the window's height.  */
   if (whole)
-    n *= max (1, ht - next_screen_context_lines);
+    {
+      int nscls = sanitize_next_screen_context_lines ();
+      n *= max (1, ht - nscls);
+    }
 
   if (!NILP (Vscroll_preserve_screen_position))
     {
index 0bffaeb60bcff4c27b695c3e9f31be9748e57675..760c31c6768054c20a2267d7014c924cc1cbf83f 100644 (file)
@@ -12533,7 +12533,8 @@ build_desired_tool_bar_string (struct frame *f)
 
       /* Compute margin and relief to draw.  */
       relief = (tool_bar_button_relief >= 0
-               ? tool_bar_button_relief
+               ? min (tool_bar_button_relief,
+                      min (INT_MAX, MOST_POSITIVE_FIXNUM))
                : DEFAULT_TOOL_BAR_BUTTON_RELIEF);
       hmargin = vmargin = relief;
 
@@ -13334,7 +13335,8 @@ hscroll_window_tree (Lisp_Object window)
          text_area_width = window_box_width (w, TEXT_AREA);
 
          /* Scroll when cursor is inside this scroll margin.  */
-         h_margin = hscroll_margin * WINDOW_FRAME_COLUMN_WIDTH (w);
+         h_margin = (clip_to_bounds (0, hscroll_margin, 1000000)
+                     * WINDOW_FRAME_COLUMN_WIDTH (w));
 
          /* If the position of this window's point has explicitly
             changed, no more suspend auto hscrolling.  */
@@ -15765,7 +15767,7 @@ enum
 
 static int
 try_scrolling (Lisp_Object window, bool just_this_one_p,
-              ptrdiff_t arg_scroll_conservatively, ptrdiff_t scroll_step,
+              intmax_t arg_scroll_conservatively, intmax_t scroll_step,
               bool temp_scroll_step, bool last_line_misfit)
 {
   struct window *w = XWINDOW (window);
@@ -15797,12 +15799,15 @@ try_scrolling (Lisp_Object window, bool just_this_one_p,
       arg_scroll_conservatively = scroll_limit + 1;
       scroll_max = scroll_limit * frame_line_height;
     }
-  else if (scroll_step || arg_scroll_conservatively || temp_scroll_step)
+  else if (0 < scroll_step || 0 < arg_scroll_conservatively || temp_scroll_step)
     /* Compute how much we should try to scroll maximally to bring
        point into view.  */
-    scroll_max = (max (scroll_step,
-                      max (arg_scroll_conservatively, temp_scroll_step))
-                 * frame_line_height);
+    {
+      intmax_t scroll_lines_max
+       = max (scroll_step, max (arg_scroll_conservatively, temp_scroll_step));
+      int scroll_lines = clip_to_bounds (0, scroll_lines_max, 1000000);
+      scroll_max = scroll_lines * frame_line_height;
+    }
   else if (NUMBERP (BVAR (current_buffer, scroll_down_aggressively))
           || NUMBERP (BVAR (current_buffer, scroll_up_aggressively)))
     /* We're trying to scroll because of aggressive scrolling but no
@@ -17295,8 +17300,8 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
     }
 
   /* Try to scroll by specified few lines.  */
-  if ((scroll_conservatively
-       || emacs_scroll_step
+  if ((0 < scroll_conservatively
+       || 0 < emacs_scroll_step
        || temp_scroll_step
        || NUMBERP (BVAR (current_buffer, scroll_up_aggressively))
        || NUMBERP (BVAR (current_buffer, scroll_down_aggressively)))
@@ -24749,8 +24754,12 @@ decode_mode_spec (struct window *w, register int c, int field_width,
            ptrdiff_t limit = BUF_BEGV (b);
            ptrdiff_t limit_byte = BUF_BEGV_BYTE (b);
            ptrdiff_t position;
-           ptrdiff_t distance =
-             (height * 2 + 30) * line_number_display_limit_width;
+           ptrdiff_t distance
+             = (line_number_display_limit_width < 0 ? 0
+                : INT_MULTIPLY_WRAPV (line_number_display_limit_width,
+                                      height * 2 + 30,
+                                      &distance)
+                ? PTRDIFF_MAX : distance);
 
            if (startpos - distance > limit)
              {
@@ -28377,7 +28386,7 @@ x_produce_glyphs (struct it *it)
          /* If face has an overline, add the height of the overline
             (1 pixel) and a 1 pixel margin to the character height.  */
          if (face->overline_p)
-           it->ascent += overline_margin;
+           it->ascent += clip_to_bounds (0, overline_margin, 1000000);
 
          if (it->constrain_row_ascent_descent_p)
            {
@@ -28918,7 +28927,7 @@ x_produce_glyphs (struct it *it)
       /* If face has an overline, add the height of the overline
         (1 pixel) and a 1 pixel margin to the character height.  */
       if (face->overline_p)
-       it->ascent += overline_margin;
+       it->ascent += clip_to_bounds (0, overline_margin, 1000000);
 
       take_vertical_position_into_account (it);
       if (it->ascent < 0)
@@ -28967,7 +28976,7 @@ x_produce_glyphs (struct it *it)
       /* If face has an overline, add the height of the overline
         (1 pixel) and a 1 pixel margin to the character height.  */
       if (face->overline_p)
-       it->ascent += overline_margin;
+       it->ascent += clip_to_bounds (0, overline_margin, 1000000);
       take_vertical_position_into_account (it);
       if (it->ascent < 0)
        it->ascent = 0;
index 37efd43b955a0433d54e93b009c5244d706da810..5f0bb44cc9a798309aa8fc2ccd7bc50d1b4e9970 100644 (file)
@@ -1085,10 +1085,10 @@ wait_for_property_change (struct prop_location *location)
      property_change_reply, because property_change_reply_object says so.  */
   if (! location->arrived)
     {
-      EMACS_INT timeout = max (0, x_selection_timeout);
-      EMACS_INT secs = timeout / 1000;
+      intmax_t timeout = max (0, x_selection_timeout);
+      intmax_t secs = timeout / 1000;
       int nsecs = (timeout % 1000) * 1000000;
-      TRACE2 ("  Waiting %"pI"d secs, %d nsecs", secs, nsecs);
+      TRACE2 ("  Waiting %"PRIdMAX" secs, %d nsecs", secs, nsecs);
       wait_reading_process_output (secs, nsecs, 0, false,
                                   property_change_reply, NULL, 0);
 
@@ -1158,8 +1158,6 @@ x_get_foreign_selection (Lisp_Object selection_symbol, Lisp_Object target_type,
   Atom type_atom = (CONSP (target_type)
                    ? symbol_to_x_atom (dpyinfo, XCAR (target_type))
                    : symbol_to_x_atom (dpyinfo, target_type));
-  EMACS_INT timeout, secs;
-  int nsecs;
 
   if (!FRAME_LIVE_P (f))
     return Qnil;
@@ -1195,10 +1193,10 @@ x_get_foreign_selection (Lisp_Object selection_symbol, Lisp_Object target_type,
   unblock_input ();
 
   /* This allows quits.  Also, don't wait forever.  */
-  timeout = max (0, x_selection_timeout);
-  secs = timeout / 1000;
-  nsecs = (timeout % 1000) * 1000000;
-  TRACE1 ("  Start waiting %"pI"d secs for SelectionNotify", secs);
+  intmax_t timeout = max (0, x_selection_timeout);
+  intmax_t secs = timeout / 1000;
+  int nsecs = (timeout % 1000) * 1000000;
+  TRACE1 ("  Start waiting %"PRIdMAX" secs for SelectionNotify", secs);
   wait_reading_process_output (secs, nsecs, 0, false,
                               reading_selection_reply, NULL, 0);
   TRACE1 ("  Got event = %d", !NILP (XCAR (reading_selection_reply)));
index d8eb45a00c040336582548d4613e4683e70b78c8..453669f6e02a911d6ce13e86a63ab6dc3589f1b4 100644 (file)
@@ -3131,7 +3131,9 @@ x_draw_image_relief (struct glyph_string *s)
   if (s->hl == DRAW_IMAGE_SUNKEN
       || s->hl == DRAW_IMAGE_RAISED)
     {
-      thick = tool_bar_button_relief >= 0 ? tool_bar_button_relief : DEFAULT_TOOL_BAR_BUTTON_RELIEF;
+      thick = (tool_bar_button_relief < 0
+              ? DEFAULT_TOOL_BAR_BUTTON_RELIEF
+              : min (tool_bar_button_relief, 1000000));
       raised_p = s->hl == DRAW_IMAGE_RAISED;
     }
   else
@@ -4884,7 +4886,7 @@ x_x_to_emacs_modifiers (struct x_display_info *dpyinfo, int state)
 }
 
 static int
-x_emacs_to_x_modifiers (struct x_display_info *dpyinfo, EMACS_INT state)
+x_emacs_to_x_modifiers (struct x_display_info *dpyinfo, intmax_t state)
 {
   EMACS_INT mod_ctrl = ctrl_modifier;
   EMACS_INT mod_meta = meta_modifier;