bug#58883:

Po Lu via CC-Mode-help <[email protected]> Fri, 18 Nov 2022 09:53:43 +0800
Newsgroups gmane.emacs.cc-mode.general
Message-ID <[email protected]>
Po Lu <[email protected]> writes:

> Thanks!  This seems to be working very well.
>
> Unfortunately, there is one small problem: editing inside an identifier
> name becomes a little sluggish: if you go down to `x_initialize' (in
> xterm.c), type "int", TAB, and hold down "ddddddddddddddddddddddd" on
> any line, you will see Emacs slow down to a crawl.
>
> That seems to only be a problem in big files, however.

Big problem: trying to edit in a string literal in a big file results is
very slow.  Quitting reveals the following call stack:

Debugger entered--entering a function:
* re-search-forward("[[:alpha:]_]" 25554 bound)
  c-unfind-tokens-in-region(1 25554)
  c-before-change(1 25554)
  c-after-change(25546 25547 0)
  self-insert-command(1 100)
  funcall-interactively(self-insert-command 1 100)
  command-execute(self-insert-command)

here is some text to reproduce the problem.  Insert the following text
in a c-mode buffer:

void
verify_image_data (struct test_display *display, Window window,
		   const char *filename)
{
  XImage *image;
  XWindowAttributes attrs;
  unsigned char *data;
  struct image_data_header header;
  unsigned short data_bpp, i;
  int byte_order;
  struct image_difference_statistics statistics;

  statistics.min_diff = 0;
  statistics.max_diff = 0;

  if (write_image_data_instead)
    write_image_data (display, window, filename);

  data = load_image_data (filename, &header);

  if (!data)
    report_test_failure ("failed to load input file: %s", filename);

  XGetWindowAttributes (display->x_display, window, &attrs);
  image = XGetImage (display->x_display, window, 0, 0, attrs.width,
		     attrs.height, ~0, ZPixmap);

  test_log ("verifying image data from: %s", filename);

  if (!image)
    report_test_failure ("failed to load from drawable 0x%lx", window);

  /* Check if the image data is compatible.  */
  data_bpp = bytes_per_pixel_for_format (header.format);
  byte_order = byte_order_for_format (header.format);

  if (byte_order != image->byte_order)
    report_test_failure ("image data has wrong byte order");

  if (data_bpp * 8 != image->bits_per_pixel)
    report_test_failure ("image data has %d bits per pixel, but reference"
			 " data has %hd * 8", image->bits_per_pixel, data_bpp);

  if (image->width != header.width
      || image->height != header.height)
    report_test_failure ("image data is %d by %d, but reference data is"
			 " %hd by %hd", image->width, image->height,
			 header.width, header.height);

  /* Now compare the actual image data.  Make sure this is done with
     the same visual as the reference data was saved in!  */

  for (i = 0; i < header.height; ++i)
    compare_single_row (data, i, &header, image, &statistics);

  /* Note that statistics is not always used by
     compare_single_row.  */

  test_log ("comparison finished.  channel differences were: %d, %d",
	    statistics.min_diff, statistics.max_diff);

  if (statistics.min_diff < -3 || statistics.max_diff > 4)
    {
      /* Write the reject to a file.  */
      test_log ("writing reject to reject.dump");
      write_image_data_1 (image, "reject.dump");

      report_test_failure ("differences exceeded thresholds (-3, 4)");
    }

  /* Destroy the images.  */
  free (data);
  XDestroyImage (image);

  test_log ("verified image data");
}
void
verify_image_data (struct test_display *display, Window window,
		   const char *filename)
{
  XImage *image;
  XWindowAttributes attrs;
  unsigned char *data;
  struct image_data_header header;
  unsigned short data_bpp, i;
  int byte_order;
  struct image_difference_statistics statistics;

  statistics.min_diff = 0;
  statistics.max_diff = 0;

  if (write_image_data_instead)
    write_image_data (display, window, filename);

  data = load_image_data (filename, &header);

  if (!data)
    report_test_failure ("failed to load input file: %s", filename);

  XGetWindowAttributes (display->x_display, window, &attrs);
  image = XGetImage (display->x_display, window, 0, 0, attrs.width,
		     attrs.height, ~0, ZPixmap);

  test_log ("verifying image data from: %s", filename);

  if (!image)
    report_test_failure ("failed to load from drawable 0x%lx", window);

  /* Check if the image data is compatible.  */
  data_bpp = bytes_per_pixel_for_format (header.format);
  byte_order = byte_order_for_format (header.format);

  if (byte_order != image->byte_order)
    report_test_failure ("image data has wrong byte order");

  if (data_bpp * 8 != image->bits_per_pixel)
    report_test_failure ("image data has %d bits per pixel, but reference"
			 " data has %hd * 8", image->bits_per_pixel, data_bpp);

  if (image->width != header.width
      || image->height != header.height)
    report_test_failure ("image data is %d by %d, but reference data is"
			 " %hd by %hd", image->width, image->height,
			 header.width, header.height);

  /* Now compare the actual image data.  Make sure this is done with
     the same visual as the reference data was saved in!  */

  for (i = 0; i < header.height; ++i)
    compare_single_row (data, i, &header, image, &statistics);

  /* Note that statistics is not always used by
     compare_single_row.  */

  test_log ("comparison finished.  channel differences were: %d, %d",
	    statistics.min_diff, statistics.max_diff);

  if (statistics.min_diff < -3 || statistics.max_diff > 4)
    {
      /* Write the reject to a file.  */
      test_log ("writing reject to reject.dump");
      write_image_data_1 (image, "reject.dump");

      report_test_failure ("differences exceeded thresholds (-3, 4)");
    }

  /* Destroy the images.  */
  free (data);
  XDestroyImage (image);

  test_log ("verified image data");
}

/* Verify the image data against a file.  */

void
verify_image_data (struct test_display *display, Window window,
		   const char *filename)
{
  XImage *image;
  XWindowAttributes attrs;
  unsigned char *data;
  struct image_data_header header;
  unsigned short data_bpp, i;
  int byte_order;
  struct image_difference_statistics statistics;

  statistics.min_diff = 0;
  statistics.max_diff = 0;

  if (write_image_data_instead)
    write_image_data (display, window, filename);

  data = load_image_data (filename, &header);

  if (!data)
    report_test_failure ("failed to load input file: %s", filename);

  XGetWindowAttributes (display->x_display, window, &attrs);
  image = XGetImage (display->x_display, window, 0, 0, attrs.width,
		     attrs.height, ~0, ZPixmap);

  test_log ("verifying image data from: %s", filename);

  if (!image)
    report_test_failure ("failed to load from drawable 0x%lx", window);

  /* Check if the image data is compatible.  */
  data_bpp = bytes_per_pixel_for_format (header.format);
  byte_order = byte_order_for_format (header.format);

  if (byte_order != image->byte_order)
    report_test_failure ("image data has wrong byte order");

  if (data_bpp * 8 != image->bits_per_pixel)
    report_test_failure ("image data has %d bits per pixel, but reference"
			 " data has %hd * 8", image->bits_per_pixel, data_bpp);

  if (image->width != header.width
      || image->height != header.height)
    report_test_failure ("image data is %d by %d, but reference data is"
			 " %hd by %hd", image->width, image->height,
			 header.width, header.height);

  /* Now compare the actual image data.  Make sure this is done with
     the same visual as the reference data was saved in!  */

  for (i = 0; i < header.height; ++i)
    compare_single_row (data, i, &header, image, &statistics);

  /* Note that statistics is not always used by
     compare_single_row.  */

  test_log ("comparison finished.  channel differences were: %d, %d",
	    statistics.min_diff, statistics.max_diff);

  if (statistics.min_diff < -3 || statistics.max_diff > 4)
    {
      /* Write the reject to a file.  */
      test_log ("writing reject to reject.dump");
      write_image_data_1 (image, "reject.dump");

      report_test_failure ("differences exceeded thresholds (-3, 4)");
    }

  /* Destroy the images.  */
  free (data);
  XDestroyImage (image);

  test_log ("verified image data");
}

void
test_set_scale (struct test_display *display, int scale)
{
  test_scale_lock_set_scale (display->scale_lock, scale);
}

void
test_init (void)
{
  write_image_data_instead
    = getenv ("TEST_WRITE_REFERENCE") != NULL;
}



static void
handle_seat_controller_device_id (void *data,
				  struct test_seat_controller *controller,
				  uint32_t device_id)
{
  struct test_display *display;

  display = data;
  display->seat->device_id = device_id;
}

static const struct test_seat_controller_listener seat_controller_listener =
  {
    handle_seat_controller_device_id,
  };



void
test_init_seat (struct test_display *display)
{
  if (display->seat)
    report_test_internal_error ("tried to initialize seat twice");

  display->seat = malloc (sizeof *display->seat);

  if (!display->seat)
    report_test_failure ("failed to allocate seat");

  display->seat->controller
    = test_manager_get_test_seat (display->test_manager);

  if (!display->seat->controller)
    report_test_failure ("failed to obtain seat controller");

  display->seat->device_controller
    = test_seat_controller_get_device_controller (display->seat->controller);

  if (!display->seat->device_controller)
    report_test_failure ("failed to obtain device controller");

  /* Fetch the device ID of the seat.  */
  display->seat->device_id = 0;
  test_seat_controller_add_listener (display->seat->controller,
				     &seat_controller_listener,
				     display);
  wl_display_roundtrip (display->display);

  if (!display->seat->device_id)
    report_test_failure ("failed to obtain device ID");

  /* The protocol translator currently supports version 8 of wl_seat,
     so bind to that.  */

  display->seat->seat
    = test_seat_controller_bind_seat (display->seat->controller,
				      8);

  if (!display->seat->seat)
    report_test_failure ("failed to bind to test seat");

  display->seat->pointer
    = wl_seat_get_pointer (display->seat->seat);

  if (!display->seat->pointer)
    report_test_failure ("failed to bind to test pointer");

  display->seat->keyboard
    = wl_seat_get_keyboard (display->seat->seat);

  if (!display->seat->keyboard)
    report_test_failure ("failed to bind to test keyboard");
}

void __attribute__ ((noreturn))
test_complete (void)
{
  test_log ("test ran successfully");
  exit_with_code (0);
}

uint32_t
test_get_serial (struct test_display *display)
{
  test_manager_get_serial (display->test_manager);
  wl_display_roundtrip (display->display);

  return display->serial;
}

void
verify_window_size (struct test_display *display,
		    Window window, int width, int height)
{
  XWindowAttributes attrs;

  XGetWindowAttributes (display->x_display, window, &attrs);

  if (width != attrs.width || height != attrs.height)
    report_test_failure ("window is incorrect size.  expected: %d %d"
			 ", actual: %d %d", width, height,
			 attrs.width, attrs.height);
}



static void
handle_wl_buffer_release (void *data, struct wl_buffer *buffer)
{
  struct test_buffer *test_buffer;

  test_buffer = data;
  test_buffer->busy = false;
}

static const struct wl_buffer_listener test_buffer_listener =
  {
    handle_wl_buffer_release,
  };



struct test_buffer *
get_test_buffer (struct test_display *display, struct wl_buffer *buffer)
{
  struct test_buffer *test_buffer;

  test_buffer = malloc (sizeof *test_buffer);

  if (!test_buffer)
    return NULL;

  test_buffer->buffer = buffer;
  test_buffer->busy = false;

  wl_buffer_add_listener (buffer, &test_buffer_listener, test_buffer);
}

void
test_buffer_committed (struct test_buffer *test_buffer)
{
  test_buffer->busy = true;
}

void
verify_buffer_released (struct test_buffer *buffer)
{
  if (!test_buffer->busy)
    report_test_failure ("buffer %p");
}

and type " is busy, but should have been released" after "%p".  Editing
will slow down to a crawl.

Thanks.