unsigned int * original_cache_bits = *cache_ptr;
BOOL include_unknown = FALSE, ignore_unknown = FALSE,
include_defer = FALSE, ignore_defer = FALSE;
-const uschar *list;
-uschar *sss;
-uschar *ot = NULL;
+const uschar * list;
+uschar * sss;
+uschar * ot = NULL;
BOOL textonly_re;
/* Save time by not scanning for the option name when we don't need it. */
gstring_release_unused(g);
ot = string_from_gstring(g);
}
+HDEBUG(D_lists)
+ {
+ debug_printf_indent("%s\n", ot);
+ expand_level++;
+ }
/* Now scan the list and process each item in turn, until one of them matches,
or we hit an error. */
{
uschar * ss = sss;
+ HDEBUG(D_lists) debug_printf_indent("list element: %s\n", ss);
+
/* Address lists may contain +caseful, to restore caseful matching of the
local part. We have to know the layout of the control block, unfortunately.
The lower cased address is in a temporary buffer, so we just copy the local
{
if (*ss == '+' && anchorptr)
{
- int bits = 0;
- int offset = 0;
- int shift = 0;
- unsigned int *use_cache_bits = original_cache_bits;
- uschar *cached = US"";
- namedlist_block *nb;
+ int bits = 0, offset = 0, shift = 0;
+ unsigned int * use_cache_bits = original_cache_bits;
+ uschar * cached = US"";
+ namedlist_block * nb;
tree_node * t;
+ DEBUG(D_lists)
+ { debug_printf_indent(" start sublist %s\n", ss+1); expand_level += 2; }
+
if (!(t = tree_search(*anchorptr, ss+1)))
{
log_write(0, LOG_MAIN|LOG_PANIC, "unknown named%s list \"%s\"",
type == MCL_ADDRESS ? " address" :
type == MCL_LOCALPART ? " local part" : "",
ss);
- return DEFER;
+ goto DEFER_RETURN;
}
nb = t->data.ptr;
if (bits == 0)
{
- switch (match_check_list(&(nb->string), 0, anchorptr, &use_cache_bits,
- func, arg, type, name, valueptr))
+ int res = match_check_list(&(nb->string), 0, anchorptr, &use_cache_bits,
+ func, arg, type, name, valueptr);
+ DEBUG(D_lists)
+ { expand_level -= 2; debug_printf_indent(" end sublist %s\n", ss+1); }
+
+ switch (res)
{
case OK: bits = 1; break;
case FAIL: bits = 3; break;
else
{
- DEBUG(D_lists) debug_printf_indent("cached %s match for %s\n",
- (bits & (-bits)) == bits ? "yes" : "no", ss);
+ DEBUG(D_lists)
+ {
+ expand_level -= 2;
+ debug_printf_indent("cached %s match for %s\n",
+ (bits & (-bits)) == bits ? "yes" : "no", ss);
+ }
cached = US" - cached";
if (valueptr)
{
HDEBUG(D_lists) debug_printf_indent("%s %s (matched \"%s\"%s)\n", ot,
yield == OK ? "yes" : "no", sss, cached);
- return yield;
+ goto YIELD_RETURN;
}
}
case OK:
HDEBUG(D_lists) debug_printf_indent("%s %s (matched \"%s\")\n", ot,
(yield == OK)? "yes" : "no", sss);
- return yield;
+ goto YIELD_RETURN;
case DEFER:
if (!error)
Copy it to allocated memory now we know it matched. */
if (valueptr) *valueptr = string_copy(ss);
- return file_yield;
+ yield = file_yield;
+ goto YIELD_RETURN;
case DEFER:
if (!error)
break;
}
(void)fclose(f);
- if (include_defer)
- {
- log_write(0, LOG_MAIN, "%s: accepted by +include_defer", error);
- return OK;
- }
- goto DEFER_RETURN;
+ if (!include_defer)
+ goto DEFER_RETURN;
+ log_write(0, LOG_MAIN, "%s: accepted by +include_defer", error);
+ goto OK_RETURN;
case ERROR: /* host name lookup failed - this can only */
if (ignore_unknown) /* be for an incoming host (not outgoing) */
{
if (LOGGING(unknown_in_list))
log_write(0, LOG_MAIN, "list matching forced to fail: %s", error);
- return FAIL;
+ goto FAIL_RETURN;
}
log_write(0, LOG_MAIN, "%s: accepted by +include_unknown", error);
- return OK;
+ goto OK_RETURN;
}
}
}
/* End of list reached: if the last item was negated yield OK, else FAIL. */
HDEBUG(D_lists)
- debug_printf_indent("%s %s (end of list)\n", ot, yield == OK ? "no":"yes");
-return yield == OK ? FAIL : OK;
+ HDEBUG(D_lists)
+ {
+ expand_level--;
+ debug_printf_indent("%s %s (end of list)\n", ot, yield == OK ? "no":"yes");
+ }
+ return yield == OK ? FAIL : OK;
/* Something deferred */
DEFER_RETURN:
-HDEBUG(D_lists) debug_printf("%s list match deferred for %s\n", ot, sss);
-return DEFER;
+ HDEBUG(D_lists)
+ {
+ expand_level--;
+ debug_printf_indent("%s list match deferred for %s\n", ot, sss);
+ }
+ return DEFER;
+
+FAIL_RETURN:
+ yield = FAIL;
+ goto YIELD_RETURN;
+
+OK_RETURN:
+ yield = OK;
+
+YIELD_RETURN:
+ HDEBUG(D_lists) expand_level--;
+ return yield;
}
s string to search for
listptr ptr to ptr to colon separated list of patterns, or NULL
sep a separator value for the list (see string_nextinlist())
+ or zero for auto
anchorptr ptr to tree for named items, or NULL if no named items
cache_bits ptr to cache_bits for ditto, or NULL if not caching
type MCL_DOMAIN when matching a domain list