/* String search routines for GNU Emacs.
- Copyright (C) 1985, 86, 87, 93, 94, 97, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1985, 86,87,93,94,97,98, 1999 Free Software Foundation, Inc.
This file is part of GNU Emacs.
#include <config.h>
-#ifdef STDC_HEADERS
-#include <stdlib.h>
-#endif
#include "lisp.h"
#include "syntax.h"
#include "category.h"
error ("Stack overflow in regexp matcher");
}
-#ifdef __STDC__
-#define CONST const
-#else
-#define CONST
-#endif
-
/* Compile a regexp and signal a Lisp error if anything goes wrong.
PATTERN is the pattern to compile.
CP is the place to put the result.
for (cpp = &searchbuf_head; ; cpp = &cp->next)
{
cp = *cpp;
+ /* Entries are initialized to nil, and may be set to nil by
+ compile_pattern_1 if the pattern isn't valid. Don't apply
+ XSTRING in those cases. However, compile_pattern_1 is only
+ applied to the cache entry we pick here to reuse. So nil
+ should never appear before a non-nil entry. */
+ if (NILP (cp->regexp))
+ goto compile_it;
if (XSTRING (cp->regexp)->size == XSTRING (pattern)->size
&& !NILP (Fstring_equal (cp->regexp, pattern))
&& EQ (cp->buf.translate, (! NILP (translate) ? translate : make_number (0)))
&& cp->buf.multibyte == multibyte)
break;
- /* If we're at the end of the cache, compile into the last cell. */
+ /* If we're at the end of the cache, compile into the nil cell
+ we found, or the last (least recently used) cell with a
+ string value. */
if (cp->next == 0)
{
+ compile_it:
compile_pattern_1 (cp, pattern, translate, regp, posix, multibyte);
break;
}
i = re_match_2 (bufp, (char *) p1, s1, (char *) p2, s2,
PT_BYTE - BEGV_BYTE, &search_regs,
ZV_BYTE - BEGV_BYTE);
+ immediate_quit = 0;
+
if (i == -2)
matcher_overflow ();
= BYTE_TO_CHAR (search_regs.end[i] + BEGV_BYTE);
}
XSETBUFFER (last_thing_searched, current_buffer);
- immediate_quit = 0;
return val;
}
{
while (--len >= 0)
{
- unsigned char workbuf[4], *str;
+ unsigned char str[MAX_MULTIBYTE_LENGTH];
int c, translated, inverse;
int in_charlen, charlen;
TRANSLATE (translated, trt, c);
/* If translation changed the byte-length, go back
to the original character. */
- charlen = CHAR_STRING (translated, workbuf, str);
+ charlen = CHAR_STRING (translated, str);
if (in_charlen != charlen)
{
translated = c;
- charlen = CHAR_STRING (c, workbuf, str);
+ charlen = CHAR_STRING (c, str);
}
/* If we are searching for something strange,
/* If two different rows appear, needing translation,
then we cannot use boyer_moore search. */
boyer_moore_ok = 0;
- /* ??? Handa: this must do boyer_moore_ok = 0
- if c is a composite character. */
}
/* Store this character into the translated pattern. */
while (! CHAR_HEAD_P (*charstart))
charstart--;
untranslated = STRING_CHAR (charstart, ptr - charstart + 1);
- if (charset_base == (untranslated & ~0xff))
+ if (charset_base == (untranslated & ~CHAR_FIELD3_MASK))
{
TRANSLATE (ch, trt, untranslated);
if (! CHAR_HEAD_P (*ptr))
Finsert_and_inherit (1, &newtext);
else
{
- struct gcpro gcpro1;
int length = STRING_BYTES (XSTRING (newtext));
+ unsigned char *substed;
+ int substed_alloc_size, substed_len;
+ int buf_multibyte = !NILP (current_buffer->enable_multibyte_characters);
+ int str_multibyte = STRING_MULTIBYTE (newtext);
+ Lisp_Object rev_tbl;
+
+ rev_tbl= (!buf_multibyte && CHAR_TABLE_P (Vnonascii_translation_table)
+ ? Fchar_table_extra_slot (Vnonascii_translation_table,
+ make_number (0))
+ : Qnil);
- GCPRO1 (newtext);
+ substed_alloc_size = length * 2 + 100;
+ substed = (unsigned char *) xmalloc (substed_alloc_size + 1);
+ substed_len = 0;
+
+ /* Go thru NEWTEXT, producing the actual text to insert in
+ SUBSTED while adjusting multibyteness to that of the current
+ buffer. */
for (pos_byte = 0, pos = 0; pos_byte < length;)
{
- int offset = PT - search_regs.start[sub];
+ unsigned char str[MAX_MULTIBYTE_LENGTH];
+ unsigned char *add_stuff;
+ int add_len;
+ int idx = -1;
- FETCH_STRING_CHAR_ADVANCE (c, newtext, pos, pos_byte);
+ if (str_multibyte)
+ {
+ FETCH_STRING_CHAR_ADVANCE (c, newtext, pos, pos_byte);
+ if (!buf_multibyte)
+ c = multibyte_char_to_unibyte (c, rev_tbl);
+ }
+ else
+ {
+ /* Note that we don't have to increment POS. */
+ c = XSTRING (newtext)->data[pos_byte++];
+ if (buf_multibyte)
+ c = unibyte_char_to_multibyte (c);
+ }
+
+ /* Either set ADD_STUFF and ADD_LEN to the text to put in SUBSTED,
+ or set IDX to a match index, which means put that part
+ of the buffer text into SUBSTED. */
if (c == '\\')
{
- FETCH_STRING_CHAR_ADVANCE (c, newtext, pos, pos_byte);
+ if (str_multibyte)
+ {
+ FETCH_STRING_CHAR_ADVANCE (c, newtext, pos, pos_byte);
+ if (!buf_multibyte && !SINGLE_BYTE_CHAR_P (c))
+ c = multibyte_char_to_unibyte (c, rev_tbl);
+ }
+ else
+ {
+ c = XSTRING (newtext)->data[pos_byte++];
+ if (buf_multibyte)
+ c = unibyte_char_to_multibyte (c);
+ }
+
if (c == '&')
- Finsert_buffer_substring
- (Fcurrent_buffer (),
- make_number (search_regs.start[sub] + offset),
- make_number (search_regs.end[sub] + offset));
+ idx = sub;
else if (c >= '1' && c <= '9' && c <= search_regs.num_regs + '0')
{
if (search_regs.start[c - '0'] >= 1)
- Finsert_buffer_substring
- (Fcurrent_buffer (),
- make_number (search_regs.start[c - '0'] + offset),
- make_number (search_regs.end[c - '0'] + offset));
+ idx = c - '0';
}
else if (c == '\\')
- insert_char (c);
+ add_len = 1, add_stuff = "\\";
else
- error ("Invalid use of `\\' in replacement text");
+ {
+ xfree (substed);
+ error ("Invalid use of `\\' in replacement text");
+ }
}
else
- insert_char (c);
+ {
+ add_len = CHAR_STRING (c, str);
+ add_stuff = str;
+ }
+
+ /* If we want to copy part of a previous match,
+ set up ADD_STUFF and ADD_LEN to point to it. */
+ if (idx >= 0)
+ {
+ int begbyte = CHAR_TO_BYTE (search_regs.start[idx]);
+ add_len = CHAR_TO_BYTE (search_regs.end[idx]) - begbyte;
+ if (search_regs.start[idx] < GPT && GPT < search_regs.end[idx])
+ move_gap (search_regs.start[idx]);
+ add_stuff = BYTE_POS_ADDR (begbyte);
+ }
+
+ /* Now the stuff we want to add to SUBSTED
+ is invariably ADD_LEN bytes starting at ADD_STUFF. */
+
+ /* Make sure SUBSTED is big enough. */
+ if (substed_len + add_len >= substed_alloc_size)
+ {
+ substed_alloc_size = substed_len + add_len + 500;
+ substed = (unsigned char *) xrealloc (substed,
+ substed_alloc_size + 1);
+ }
+
+ /* Now add to the end of SUBSTED. */
+ bcopy (add_stuff, substed + substed_len, add_len);
+ substed_len += add_len;
}
- UNGCPRO;
+
+ /* Now insert what we accumulated. */
+ insert_and_inherit (substed, substed_len);
+
+ xfree (substed);
}
inslen = PT - (search_regs.start[sub]);
/* If REUSE is a list, store as many value elements as will fit
into the elements of REUSE. */
for (i = 0, tail = reuse; CONSP (tail);
- i++, tail = XCONS (tail)->cdr)
+ i++, tail = XCDR (tail))
{
if (i < 2 * len + 2)
- XCONS (tail)->car = data[i];
+ XCAR (tail) = data[i];
else
- XCONS (tail)->car = Qnil;
+ XCAR (tail) = Qnil;
prev = tail;
}
/* If we couldn't fit all value elements into REUSE,
cons up the rest of them and add them to the end of REUSE. */
if (i < 2 * len + 2)
- XCONS (prev)->cdr = Flist (2 * len + 2 - i, data + i);
+ XCDR (prev) = Flist (2 * len + 2 - i, data + i);
return reuse;
}