aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorStefan Monnier2023-09-29 14:55:24 -0400
committerStefan Monnier2023-09-29 14:55:24 -0400
commitcc0d7d7a3867e4554f89262e4641c9845ee0d647 (patch)
treea3c3ee2a6ce207bb969b21f50f802bf55954d1d1 /src
parent01229fe0096e936ea8f4fad0d64967671c4b1892 (diff)
downloademacs-cc0d7d7a3867e4554f89262e4641c9845ee0d647.tar.gz
emacs-cc0d7d7a3867e4554f89262e4641c9845ee0d647.zip
search.c (re--describe-compiled): New function (bug#66261)
This provides a fairly primitive but handy way to see what a regexp compiles to without having to enable REGEX_EMACS_DEBUG and wade through tons of stderr output. * doc/lispref/searching.texi (Regexp Problems): Mention `re--describe-compiled`. * src/regex-emacs.c (debug_putchar, print_fastmap) (print_partial_compiled_pattern, print_compiled_pattern): Add `dest` argument, and compile also when `ENABLE_CHECKING` is set. (DEBUG_PRINT_COMPILED_PATTERN, print_double_string, regex_compile): Adjust to additional argument. * src/regex-emacs.h (print_compiled_pattern): Declare. * src/search.c (Fre__describe_compiled): New function. (syms_of_search): Defsubr it.
Diffstat (limited to 'src')
-rw-r--r--src/regex-emacs.c176
-rw-r--r--src/regex-emacs.h4
-rw-r--r--src/search.c41
3 files changed, 136 insertions, 85 deletions
diff --git a/src/regex-emacs.c b/src/regex-emacs.c
index ad140908609..f4ea867f3c0 100644
--- a/src/regex-emacs.c
+++ b/src/regex-emacs.c
@@ -268,7 +268,9 @@ typedef enum
268 on_failure_jump, 268 on_failure_jump,
269 269
270 /* Like on_failure_jump, but pushes a placeholder instead of the 270 /* Like on_failure_jump, but pushes a placeholder instead of the
271 current string position when executed. */ 271 current string position when executed. Upon failure,
272 the current string position is thus not restored.
273 Used only for single-char loops that don't require backtracking. */
272 on_failure_keep_string_jump, 274 on_failure_keep_string_jump,
273 275
274 /* Just like 'on_failure_jump', except that it checks that we 276 /* Just like 'on_failure_jump', except that it checks that we
@@ -434,38 +436,27 @@ extract_number_and_incr (re_char **source)
434/* If REGEX_EMACS_DEBUG is defined, print many voluminous messages 436/* If REGEX_EMACS_DEBUG is defined, print many voluminous messages
435 (if the variable regex_emacs_debug is positive). */ 437 (if the variable regex_emacs_debug is positive). */
436 438
437#ifdef REGEX_EMACS_DEBUG 439#if defined REGEX_EMACS_DEBUG || ENABLE_CHECKING
438 440
439/* Use standard I/O for debugging. */ 441/* Use standard I/O for debugging. */
440# include "sysstdio.h" 442# include "sysstdio.h"
441 443
442static int regex_emacs_debug = -100000;
443
444# define DEBUG_STATEMENT(e) e
445# define DEBUG_PRINT(...) \
446 if (regex_emacs_debug > 0) fprintf (stderr, __VA_ARGS__)
447# define DEBUG_COMPILES_ARGUMENTS
448# define DEBUG_PRINT_COMPILED_PATTERN(p, s, e) \
449 if (regex_emacs_debug > 0) print_partial_compiled_pattern (s, e)
450# define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2) \
451 if (regex_emacs_debug > 0) print_double_string (w, s1, sz1, s2, sz2)
452
453static void 444static void
454debug_putchar (int c) 445debug_putchar (FILE *dest, int c)
455{ 446{
456 if (c >= 32 && c <= 126) 447 if (c >= 32 && c <= 126)
457 putc (c, stderr); 448 putc (c, dest);
458 else 449 else
459 { 450 {
460 unsigned int uc = c; 451 unsigned int uc = c;
461 fprintf (stderr, "{%02x}", uc); 452 fprintf (dest, "{%02x}", uc);
462 } 453 }
463} 454}
464 455
465/* Print the fastmap in human-readable form. */ 456/* Print the fastmap in human-readable form. */
466 457
467static void 458static void
468print_fastmap (char *fastmap) 459print_fastmap (FILE *dest, char *fastmap)
469{ 460{
470 bool was_a_range = false; 461 bool was_a_range = false;
471 int i = 0; 462 int i = 0;
@@ -475,7 +466,7 @@ print_fastmap (char *fastmap)
475 if (fastmap[i++]) 466 if (fastmap[i++])
476 { 467 {
477 was_a_range = false; 468 was_a_range = false;
478 debug_putchar (i - 1); 469 debug_putchar (dest, i - 1);
479 while (i < (1 << BYTEWIDTH) && fastmap[i]) 470 while (i < (1 << BYTEWIDTH) && fastmap[i])
480 { 471 {
481 was_a_range = true; 472 was_a_range = true;
@@ -483,12 +474,12 @@ print_fastmap (char *fastmap)
483 } 474 }
484 if (was_a_range) 475 if (was_a_range)
485 { 476 {
486 debug_putchar ('-'); 477 debug_putchar (dest, '-');
487 debug_putchar (i - 1); 478 debug_putchar (dest, i - 1);
488 } 479 }
489 } 480 }
490 } 481 }
491 putc ('\n', stderr); 482 putc ('\n', dest);
492} 483}
493 484
494 485
@@ -496,7 +487,7 @@ print_fastmap (char *fastmap)
496 the START pointer into it and ending just before the pointer END. */ 487 the START pointer into it and ending just before the pointer END. */
497 488
498static void 489static void
499print_partial_compiled_pattern (re_char *start, re_char *end) 490print_partial_compiled_pattern (FILE *dest, re_char *start, re_char *end)
500{ 491{
501 int mcnt, mcnt2; 492 int mcnt, mcnt2;
502 re_char *p = start; 493 re_char *p = start;
@@ -504,50 +495,50 @@ print_partial_compiled_pattern (re_char *start, re_char *end)
504 495
505 if (start == NULL) 496 if (start == NULL)
506 { 497 {
507 fputs ("(null)\n", stderr); 498 fputs ("(null)\n", dest);
508 return; 499 return;
509 } 500 }
510 501
511 /* Loop over pattern commands. */ 502 /* Loop over pattern commands. */
512 while (p < pend) 503 while (p < pend)
513 { 504 {
514 fprintf (stderr, "%td:\t", p - start); 505 fprintf (dest, "%td:\t", p - start);
515 506
516 switch ((re_opcode_t) *p++) 507 switch ((re_opcode_t) *p++)
517 { 508 {
518 case no_op: 509 case no_op:
519 fputs ("/no_op", stderr); 510 fputs ("/no_op", dest);
520 break; 511 break;
521 512
522 case succeed: 513 case succeed:
523 fputs ("/succeed", stderr); 514 fputs ("/succeed", dest);
524 break; 515 break;
525 516
526 case exactn: 517 case exactn:
527 mcnt = *p++; 518 mcnt = *p++;
528 fprintf (stderr, "/exactn/%d", mcnt); 519 fprintf (dest, "/exactn/%d", mcnt);
529 do 520 do
530 { 521 {
531 debug_putchar ('/'); 522 debug_putchar (dest, '/');
532 debug_putchar (*p++); 523 debug_putchar (dest, *p++);
533 } 524 }
534 while (--mcnt); 525 while (--mcnt);
535 break; 526 break;
536 527
537 case start_memory: 528 case start_memory:
538 fprintf (stderr, "/start_memory/%d", *p++); 529 fprintf (dest, "/start_memory/%d", *p++);
539 break; 530 break;
540 531
541 case stop_memory: 532 case stop_memory:
542 fprintf (stderr, "/stop_memory/%d", *p++); 533 fprintf (dest, "/stop_memory/%d", *p++);
543 break; 534 break;
544 535
545 case duplicate: 536 case duplicate:
546 fprintf (stderr, "/duplicate/%d", *p++); 537 fprintf (dest, "/duplicate/%d", *p++);
547 break; 538 break;
548 539
549 case anychar: 540 case anychar:
550 fputs ("/anychar", stderr); 541 fputs ("/anychar", dest);
551 break; 542 break;
552 543
553 case charset: 544 case charset:
@@ -558,11 +549,11 @@ print_partial_compiled_pattern (re_char *start, re_char *end)
558 int length = CHARSET_BITMAP_SIZE (p - 1); 549 int length = CHARSET_BITMAP_SIZE (p - 1);
559 bool has_range_table = CHARSET_RANGE_TABLE_EXISTS_P (p - 1); 550 bool has_range_table = CHARSET_RANGE_TABLE_EXISTS_P (p - 1);
560 551
561 fprintf (stderr, "/charset [%s", 552 fprintf (dest, "/charset [%s",
562 (re_opcode_t) *(p - 1) == charset_not ? "^" : ""); 553 (re_opcode_t) *(p - 1) == charset_not ? "^" : "");
563 554
564 if (p + (*p & 0x7f) >= pend) 555 if (p + (*p & 0x7f) >= pend)
565 fputs (" !extends past end of pattern! ", stderr); 556 fputs (" !extends past end of pattern! ", dest);
566 557
567 for (c = 0; c < 256; c++) 558 for (c = 0; c < 256; c++)
568 if (c / 8 < length 559 if (c / 8 < length
@@ -571,33 +562,33 @@ print_partial_compiled_pattern (re_char *start, re_char *end)
571 /* Are we starting a range? */ 562 /* Are we starting a range? */
572 if (last + 1 == c && ! in_range) 563 if (last + 1 == c && ! in_range)
573 { 564 {
574 debug_putchar ('-'); 565 debug_putchar (dest, '-');
575 in_range = true; 566 in_range = true;
576 } 567 }
577 /* Have we broken a range? */ 568 /* Have we broken a range? */
578 else if (last + 1 != c && in_range) 569 else if (last + 1 != c && in_range)
579 { 570 {
580 debug_putchar (last); 571 debug_putchar (dest, last);
581 in_range = false; 572 in_range = false;
582 } 573 }
583 574
584 if (! in_range) 575 if (! in_range)
585 debug_putchar (c); 576 debug_putchar (dest, c);
586 577
587 last = c; 578 last = c;
588 } 579 }
589 580
590 if (in_range) 581 if (in_range)
591 debug_putchar (last); 582 debug_putchar (dest, last);
592 583
593 debug_putchar (']'); 584 debug_putchar (dest, ']');
594 585
595 p += 1 + length; 586 p += 1 + length;
596 587
597 if (has_range_table) 588 if (has_range_table)
598 { 589 {
599 int count; 590 int count;
600 fputs ("has-range-table", stderr); 591 fputs ("has-range-table", dest);
601 592
602 /* ??? Should print the range table; for now, just skip it. */ 593 /* ??? Should print the range table; for now, just skip it. */
603 p += 2; /* skip range table bits */ 594 p += 2; /* skip range table bits */
@@ -608,160 +599,175 @@ print_partial_compiled_pattern (re_char *start, re_char *end)
608 break; 599 break;
609 600
610 case begline: 601 case begline:
611 fputs ("/begline", stderr); 602 fputs ("/begline", dest);
612 break; 603 break;
613 604
614 case endline: 605 case endline:
615 fputs ("/endline", stderr); 606 fputs ("/endline", dest);
616 break; 607 break;
617 608
618 case on_failure_jump: 609 case on_failure_jump:
619 EXTRACT_NUMBER_AND_INCR (mcnt, p); 610 EXTRACT_NUMBER_AND_INCR (mcnt, p);
620 fprintf (stderr, "/on_failure_jump to %td", p + mcnt - start); 611 fprintf (dest, "/on_failure_jump to %td", p + mcnt - start);
621 break; 612 break;
622 613
623 case on_failure_keep_string_jump: 614 case on_failure_keep_string_jump:
624 EXTRACT_NUMBER_AND_INCR (mcnt, p); 615 EXTRACT_NUMBER_AND_INCR (mcnt, p);
625 fprintf (stderr, "/on_failure_keep_string_jump to %td", 616 fprintf (dest, "/on_failure_keep_string_jump to %td",
626 p + mcnt - start); 617 p + mcnt - start);
627 break; 618 break;
628 619
629 case on_failure_jump_nastyloop: 620 case on_failure_jump_nastyloop:
630 EXTRACT_NUMBER_AND_INCR (mcnt, p); 621 EXTRACT_NUMBER_AND_INCR (mcnt, p);
631 fprintf (stderr, "/on_failure_jump_nastyloop to %td", 622 fprintf (dest, "/on_failure_jump_nastyloop to %td",
632 p + mcnt - start); 623 p + mcnt - start);
633 break; 624 break;
634 625
635 case on_failure_jump_loop: 626 case on_failure_jump_loop:
636 EXTRACT_NUMBER_AND_INCR (mcnt, p); 627 EXTRACT_NUMBER_AND_INCR (mcnt, p);
637 fprintf (stderr, "/on_failure_jump_loop to %td", 628 fprintf (dest, "/on_failure_jump_loop to %td",
638 p + mcnt - start); 629 p + mcnt - start);
639 break; 630 break;
640 631
641 case on_failure_jump_smart: 632 case on_failure_jump_smart:
642 EXTRACT_NUMBER_AND_INCR (mcnt, p); 633 EXTRACT_NUMBER_AND_INCR (mcnt, p);
643 fprintf (stderr, "/on_failure_jump_smart to %td", 634 fprintf (dest, "/on_failure_jump_smart to %td",
644 p + mcnt - start); 635 p + mcnt - start);
645 break; 636 break;
646 637
647 case jump: 638 case jump:
648 EXTRACT_NUMBER_AND_INCR (mcnt, p); 639 EXTRACT_NUMBER_AND_INCR (mcnt, p);
649 fprintf (stderr, "/jump to %td", p + mcnt - start); 640 fprintf (dest, "/jump to %td", p + mcnt - start);
650 break; 641 break;
651 642
652 case succeed_n: 643 case succeed_n:
653 EXTRACT_NUMBER_AND_INCR (mcnt, p); 644 EXTRACT_NUMBER_AND_INCR (mcnt, p);
654 EXTRACT_NUMBER_AND_INCR (mcnt2, p); 645 EXTRACT_NUMBER_AND_INCR (mcnt2, p);
655 fprintf (stderr, "/succeed_n to %td, %d times", 646 fprintf (dest, "/succeed_n to %td, %d times",
656 p - 2 + mcnt - start, mcnt2); 647 p - 2 + mcnt - start, mcnt2);
657 break; 648 break;
658 649
659 case jump_n: 650 case jump_n:
660 EXTRACT_NUMBER_AND_INCR (mcnt, p); 651 EXTRACT_NUMBER_AND_INCR (mcnt, p);
661 EXTRACT_NUMBER_AND_INCR (mcnt2, p); 652 EXTRACT_NUMBER_AND_INCR (mcnt2, p);
662 fprintf (stderr, "/jump_n to %td, %d times", 653 fprintf (dest, "/jump_n to %td, %d times",
663 p - 2 + mcnt - start, mcnt2); 654 p - 2 + mcnt - start, mcnt2);
664 break; 655 break;
665 656
666 case set_number_at: 657 case set_number_at:
667 EXTRACT_NUMBER_AND_INCR (mcnt, p); 658 EXTRACT_NUMBER_AND_INCR (mcnt, p);
668 EXTRACT_NUMBER_AND_INCR (mcnt2, p); 659 EXTRACT_NUMBER_AND_INCR (mcnt2, p);
669 fprintf (stderr, "/set_number_at location %td to %d", 660 fprintf (dest, "/set_number_at location %td to %d",
670 p - 2 + mcnt - start, mcnt2); 661 p - 2 + mcnt - start, mcnt2);
671 break; 662 break;
672 663
673 case wordbound: 664 case wordbound:
674 fputs ("/wordbound", stderr); 665 fputs ("/wordbound", dest);
675 break; 666 break;
676 667
677 case notwordbound: 668 case notwordbound:
678 fputs ("/notwordbound", stderr); 669 fputs ("/notwordbound", dest);
679 break; 670 break;
680 671
681 case wordbeg: 672 case wordbeg:
682 fputs ("/wordbeg", stderr); 673 fputs ("/wordbeg", dest);
683 break; 674 break;
684 675
685 case wordend: 676 case wordend:
686 fputs ("/wordend", stderr); 677 fputs ("/wordend", dest);
687 break; 678 break;
688 679
689 case symbeg: 680 case symbeg:
690 fputs ("/symbeg", stderr); 681 fputs ("/symbeg", dest);
691 break; 682 break;
692 683
693 case symend: 684 case symend:
694 fputs ("/symend", stderr); 685 fputs ("/symend", dest);
695 break; 686 break;
696 687
697 case syntaxspec: 688 case syntaxspec:
698 fputs ("/syntaxspec", stderr); 689 fputs ("/syntaxspec", dest);
699 mcnt = *p++; 690 mcnt = *p++;
700 fprintf (stderr, "/%d", mcnt); 691 fprintf (dest, "/%d", mcnt);
701 break; 692 break;
702 693
703 case notsyntaxspec: 694 case notsyntaxspec:
704 fputs ("/notsyntaxspec", stderr); 695 fputs ("/notsyntaxspec", dest);
705 mcnt = *p++; 696 mcnt = *p++;
706 fprintf (stderr, "/%d", mcnt); 697 fprintf (dest, "/%d", mcnt);
707 break; 698 break;
708 699
709 case at_dot: 700 case at_dot:
710 fputs ("/at_dot", stderr); 701 fputs ("/at_dot", dest);
711 break; 702 break;
712 703
713 case categoryspec: 704 case categoryspec:
714 fputs ("/categoryspec", stderr); 705 fputs ("/categoryspec", dest);
715 mcnt = *p++; 706 mcnt = *p++;
716 fprintf (stderr, "/%d", mcnt); 707 fprintf (dest, "/%d", mcnt);
717 break; 708 break;
718 709
719 case notcategoryspec: 710 case notcategoryspec:
720 fputs ("/notcategoryspec", stderr); 711 fputs ("/notcategoryspec", dest);
721 mcnt = *p++; 712 mcnt = *p++;
722 fprintf (stderr, "/%d", mcnt); 713 fprintf (dest, "/%d", mcnt);
723 break; 714 break;
724 715
725 case begbuf: 716 case begbuf:
726 fputs ("/begbuf", stderr); 717 fputs ("/begbuf", dest);
727 break; 718 break;
728 719
729 case endbuf: 720 case endbuf:
730 fputs ("/endbuf", stderr); 721 fputs ("/endbuf", dest);
731 break; 722 break;
732 723
733 default: 724 default:
734 fprintf (stderr, "?%d", *(p-1)); 725 fprintf (dest, "?%d", *(p-1));
735 } 726 }
736 727
737 putc ('\n', stderr); 728 putc ('\n', dest);
738 } 729 }
739 730
740 fprintf (stderr, "%td:\tend of pattern.\n", p - start); 731 fprintf (dest, "%td:\tend of pattern.\n", p - start);
741} 732}
742 733
743 734void
744static void 735print_compiled_pattern (FILE *dest, struct re_pattern_buffer *bufp)
745print_compiled_pattern (struct re_pattern_buffer *bufp)
746{ 736{
737 if (!dest)
738 dest = stderr;
747 re_char *buffer = bufp->buffer; 739 re_char *buffer = bufp->buffer;
748 740
749 print_partial_compiled_pattern (buffer, buffer + bufp->used); 741 print_partial_compiled_pattern (dest, buffer, buffer + bufp->used);
750 fprintf (stderr, "%td bytes used/%td bytes allocated.\n", 742 fprintf (dest, "%td bytes used/%td bytes allocated.\n",
751 bufp->used, bufp->allocated); 743 bufp->used, bufp->allocated);
752 744
753 if (bufp->fastmap_accurate && bufp->fastmap) 745 if (bufp->fastmap_accurate && bufp->fastmap)
754 { 746 {
755 fputs ("fastmap: ", stderr); 747 fputs ("fastmap: ", dest);
756 print_fastmap (bufp->fastmap); 748 print_fastmap (dest, bufp->fastmap);
757 } 749 }
758 750
759 fprintf (stderr, "re_nsub: %td\t", bufp->re_nsub); 751 fprintf (dest, "re_nsub: %td\t", bufp->re_nsub);
760 fprintf (stderr, "regs_alloc: %d\t", bufp->regs_allocated); 752 fprintf (dest, "regs_alloc: %d\t", bufp->regs_allocated);
761 fprintf (stderr, "can_be_null: %d\n", bufp->can_be_null); 753 fprintf (dest, "can_be_null: %d\n", bufp->can_be_null);
762 /* Perhaps we should print the translate table? */ 754 /* Perhaps we should print the translate table? */
763} 755}
764 756
757#endif
758
759#ifdef REGEX_EMACS_DEBUG
760
761static int regex_emacs_debug = -100000;
762
763# define DEBUG_STATEMENT(e) e
764# define DEBUG_PRINT(...) \
765 if (regex_emacs_debug > 0) fprintf (stderr, __VA_ARGS__)
766# define DEBUG_COMPILES_ARGUMENTS
767# define DEBUG_PRINT_COMPILED_PATTERN(p, s, e) \
768 if (regex_emacs_debug > 0) print_partial_compiled_pattern (stderr, s, e)
769# define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2) \
770 if (regex_emacs_debug > 0) print_double_string (w, s1, sz1, s2, sz2)
765 771
766static void 772static void
767print_double_string (re_char *where, re_char *string1, ptrdiff_t size1, 773print_double_string (re_char *where, re_char *string1, ptrdiff_t size1,
@@ -775,12 +781,12 @@ print_double_string (re_char *where, re_char *string1, ptrdiff_t size1,
775 if (FIRST_STRING_P (where)) 781 if (FIRST_STRING_P (where))
776 { 782 {
777 for (i = 0; i < string1 + size1 - where; i++) 783 for (i = 0; i < string1 + size1 - where; i++)
778 debug_putchar (where[i]); 784 debug_putchar (stderr, where[i]);
779 where = string2; 785 where = string2;
780 } 786 }
781 787
782 for (i = 0; i < string2 + size2 - where; i++) 788 for (i = 0; i < string2 + size2 - where; i++)
783 debug_putchar (where[i]); 789 debug_putchar (stderr, where[i]);
784 } 790 }
785} 791}
786 792
@@ -1760,7 +1766,7 @@ regex_compile (re_char *pattern, ptrdiff_t size,
1760 if (regex_emacs_debug > 0) 1766 if (regex_emacs_debug > 0)
1761 { 1767 {
1762 for (ptrdiff_t debug_count = 0; debug_count < size; debug_count++) 1768 for (ptrdiff_t debug_count = 0; debug_count < size; debug_count++)
1763 debug_putchar (pattern[debug_count]); 1769 debug_putchar (stderr, pattern[debug_count]);
1764 putc ('\n', stderr); 1770 putc ('\n', stderr);
1765 } 1771 }
1766#endif 1772#endif
diff --git a/src/regex-emacs.h b/src/regex-emacs.h
index bc357633135..d9adcc69443 100644
--- a/src/regex-emacs.h
+++ b/src/regex-emacs.h
@@ -195,4 +195,8 @@ extern bool re_iswctype (int ch, re_wctype_t cc);
195extern re_wctype_t re_wctype_parse (const unsigned char **strp, 195extern re_wctype_t re_wctype_parse (const unsigned char **strp,
196 ptrdiff_t limit); 196 ptrdiff_t limit);
197 197
198#if ENABLE_CHECKING
199extern void print_compiled_pattern (FILE *dest, struct re_pattern_buffer *bufp);
200#endif
201
198#endif /* EMACS_REGEX_H */ 202#endif /* EMACS_REGEX_H */
diff --git a/src/search.c b/src/search.c
index 742a78cb0cd..014fd97d423 100644
--- a/src/search.c
+++ b/src/search.c
@@ -3376,6 +3376,46 @@ the buffer. If the buffer doesn't have a cache, the value is nil. */)
3376 set_buffer_internal_1 (old); 3376 set_buffer_internal_1 (old);
3377 return val; 3377 return val;
3378} 3378}
3379
3380DEFUN ("re--describe-compiled", Fre__describe_compiled, Sre__describe_compiled,
3381 1, 2, 0,
3382 doc: /* Return a string describing the compiled form of REGEXP.
3383If RAW is non-nil, just return the actual bytecode. */)
3384 (Lisp_Object regexp, Lisp_Object raw)
3385{
3386 struct regexp_cache *cache_entry
3387 = compile_pattern (regexp, NULL,
3388 (!NILP (BVAR (current_buffer, case_fold_search))
3389 ? BVAR (current_buffer, case_canon_table) : Qnil),
3390 false,
3391 !NILP (BVAR (current_buffer,
3392 enable_multibyte_characters)));
3393 if (!NILP (raw))
3394 return make_unibyte_string (cache_entry->buf.buffer,
3395 cache_entry->buf.used);
3396 else
3397 { /* FIXME: Why ENABLE_CHECKING? */
3398#if !ENABLE_CHECKING
3399 error ("Not available: rebuild with --enable-checking");
3400#elsif HAVE_OPEN_MEMSTREAM
3401 char *buffer = NULL;
3402 size_t size = 0;
3403 FILE* f = open_memstream (&buffer, &size);
3404 if (!f)
3405 report_file_error ("open_memstream failed", regexp);
3406 print_compiled_pattern (f, &cache_entry->buf);
3407 fclose (f);
3408 if (!buffer)
3409 return Qnil;
3410 Lisp_Object description = make_unibyte_string (buffer, size);
3411 free (buffer);
3412 return description;
3413#else
3414 print_compiled_pattern (stderr, &cache_entry->buf);
3415 return build_string ("Description was sent to standard error");
3416#endif
3417 }
3418}
3379 3419
3380 3420
3381static void syms_of_search_for_pdumper (void); 3421static void syms_of_search_for_pdumper (void);
@@ -3455,6 +3495,7 @@ is to bind it with `let' around a small expression. */);
3455 defsubr (&Smatch_data__translate); 3495 defsubr (&Smatch_data__translate);
3456 defsubr (&Sregexp_quote); 3496 defsubr (&Sregexp_quote);
3457 defsubr (&Snewline_cache_check); 3497 defsubr (&Snewline_cache_check);
3498 defsubr (&Sre__describe_compiled);
3458 3499
3459 pdumper_do_now_and_after_load (syms_of_search_for_pdumper); 3500 pdumper_do_now_and_after_load (syms_of_search_for_pdumper);
3460} 3501}