So our returned <code> * match</code> needn't be <code>( * prev)->next</code>, as there may be some intervening entries with <code> ->name == NULL</code>.  Do our callers expect that ?

In fact, we seem to have just one caller, below, and it wants ( * prev) to be the item whose ->next actually is * match, at least when there's no earlier entry with non-NULL ->name.  So perhaps we should rework this loop's body: <code>
if (ip->name)
{
   if (FullTextMatch(ctx, regexp, ip->name))
   {
     *match = ip;
     if (*prev == CF_UNDEFINED_ITEM) { *prev = ip_prev; } /* fall back on last if no last-with-name */
     return true;
   }
   *prev = ip; /* last entry with a name */
}
ip_prev = ip; /* last entry */
</code>
and clear *prev again if we fall off the end of the loop.