Yeah I've reproduced this in the current code.
I think the bug is in 'name_from_drinkcon()'
Manipulating strings is definitely not my strong suite..
I googled up some C code which removes duplicate words from strings, and also removes trailing whitespace, this is what I ended up with:
Code:
/**
* Remove all occurrences of a given word in string.
*/
void removeAll(char *str, const char *toRemove)
{
int i, j, stringLen, toRemoveLen;
int found;
stringLen = strlen(str); // Length of string
toRemoveLen = strlen(toRemove); // Length of word to remove
for(i=0; i <= stringLen - toRemoveLen; i++)
{
/* Match word with string */
found = 1;
for(j=0; j<toRemoveLen; j++)
{
if(str[i + j] != toRemove[j])
{
found = 0;
break;
}
}
/* If it is not a word */
if(str[i + j] != ' ' && str[i + j] != '\t' && str[i + j] != '\n' && str[i + j] != '\0')
{
found = 0;
}
/*
* If word is found then shift all characters to left
* and decrement the string length
*/
if(found == 1)
{
for(j=i; j<=stringLen - toRemoveLen; j++)
{
str[j] = str[j + toRemoveLen];
}
stringLen = stringLen - toRemoveLen;
// We will match next occurrence of word from current index.
i--;
}
}
}
char *ltrim(const char *s)
{
char *r = strdup(s);
if (r != NULL)
{
char *fr = r + strlen(s) - 1;
while( (isspace(*fr) || !isprint(*fr) || *fr == 0) && fr >= r) --fr;
*++fr = 0;
}
return r;
}
void name_from_drinkcon(struct obj_data *obj)
{
const char *liqname;
if (!obj || (GET_OBJ_TYPE(obj) != ITEM_DRINKCON && GET_OBJ_TYPE(obj) != ITEM_FOUNTAIN))
return;
liqname = drinknames[GET_OBJ_VAL(obj, 2)];
removeAll(obj->name, liqname);
obj->name = ltrim(obj->name);
}
I'm not sure this is the correct way to handle changing strings, I suspect I need to free the old one and create a new one? If anyone can confirm that would be great