Rework and simplify $remw() implementation

This replaces calls to alloca() followed by two strcpy()s with a single
call to memmove(), and removes a confusing for/break structure.

The function should behave exactly as it did before.
This commit is contained in:
Kevin Easton
2016-12-14 23:39:31 +11:00
parent 39dd68b67b
commit 678adbdd40

View File

@@ -2130,46 +2130,54 @@ BUILT_IN_FUNCTION(function_restw, word)
* returns "string of text" with the word "word" removed
* EX: $remw(the now is the time for) returns "now is time for"
*/
BUILT_IN_FUNCTION(function_remw, word)
BUILT_IN_FUNCTION(function_remw, text)
{
char *word_to_remove;
int len;
size_t len;
char *str;
GET_STR_ARG(word_to_remove, word);
GET_STR_ARG(word_to_remove, text);
len = strlen(word_to_remove);
str = stristr(word, word_to_remove);
for (; str && *str; str = stristr(str + 1, word_to_remove))
/* Find the first instance of word_to_remove that's either at the start
* of the text or preceded by a space, and is either at the end of the
* text or followed by a space. */
str = stristr(text, word_to_remove);
while (str &&
((str != text && !isspace((unsigned char)str[-1])) ||
(str[len] && !isspace((unsigned char)str[len]))))
{
if (str == word || isspace((unsigned char)str[-1]))
{
if (!str[len] || isspace((unsigned char)str[len]))
{
if (!str[len])
{
if (str != word)
str--;
*str = 0;
str = stristr(str + 1, word_to_remove);
}
else if (str > word)
if (str)
{
char *safe = (char *)alloca(strlen(str));
strcpy(safe, str + len);
strcpy(str - 1, safe);
/* Move from the following space (if any) */
char *src = str + len;
char *dest;
/* We always discard at least one space around the word (except for the
* special case where the text is exactly equal to the word). If the
* word was found in the middle or end of text, we discard the space
* preceding the word, but if the word was found at the start of text
* we have to discard the space following the word, if any.
*/
if (str == text)
{
dest = str;
if (*src)
src++;
}
else
{
char *safe = (char *)alloca(strlen(str));
strcpy(safe, str + len + 1);
strcpy(str, safe);
}
break;
}
}
dest = str - 1;
}
RETURN_STR(word);
memmove(dest, src, strlen(src) + 1);
}
RETURN_STR(text);
}
/* $insertw(num word string of text)