MEDIUM: sample: pass an empty list instead of a null for fetch args

ACL and sample fetches use args list and it is really not convenient to
check for null args everywhere. Now for empty args we pass a constant
list of end of lists. It will allow us to remove many useless checks.
This commit is contained in:
Willy Tarreau 2012-10-19 19:49:09 +02:00
parent f22a50836d
commit 2e845be249
5 changed files with 28 additions and 6 deletions

View File

@ -54,6 +54,11 @@
#define ARG7(m, t1, t2, t3, t4, t5, t6, t7) \
(ARG6(m, t1, t2, t3, t4, t5, t6) + (ARGT_##t7 << 28))
/* This dummy arg list may be used by default when no arg is found, it helps
* parsers by removing pointer checks.
*/
extern struct arg empty_arg_list[8];
int make_arg_list(const char *in, int len, unsigned int mask, struct arg **argp,
char **err_msg, const char **err_ptr, int *err_arg);

View File

@ -1224,7 +1224,8 @@ static struct acl_expr *prune_acl_expr(struct acl_expr *expr)
arg++;
}
free(expr->args);
if (expr->args != empty_arg_list)
free(expr->args);
expr->kw->use_cnt--;
return expr;
}
@ -1352,6 +1353,7 @@ struct acl_expr *parse_acl_expr(const char **args, char **err)
aclkw->use_cnt++;
LIST_INIT(&expr->patterns);
expr->pattern_tree = EB_ROOT_UNIQUE;
expr->args = empty_arg_list;
arg = strchr(args[0], '(');
if (aclkw->arg_mask) {
@ -1380,6 +1382,9 @@ struct acl_expr *parse_acl_expr(const char **args, char **err)
goto out_free_expr;
}
if (!expr->args)
expr->args = empty_arg_list;
if (aclkw->val_args && !aclkw->val_args(expr->args, err)) {
/* invalid keyword argument, error must have been
* set by val_args().
@ -2030,10 +2035,8 @@ acl_find_targets(struct proxy *p)
list_for_each_entry(acl, &p->acl, list) {
list_for_each_entry(expr, &acl->expr, list) {
for (arg = expr->args; arg; arg++) {
if (arg->type == ARGT_STOP)
break;
else if (!arg->unresolved)
for (arg = expr->args; arg && arg->type != ARGT_STOP; arg++) {
if (!arg->unresolved)
continue;
else if (arg->type == ARGT_SRV) {
struct proxy *px;

View File

@ -36,6 +36,11 @@ static const char *arg_type_names[ARGT_NBTYPES] = {
/* Unassigned types must never happen. Better crash during parsing if they do. */
};
/* This dummy arg list may be used by default when no arg is found, it helps
* parsers by removing pointer checks.
*/
struct arg empty_arg_list[8] = { };
/* This function builds an argument list from a config line. It returns the
* number of arguments found, or <0 in case of any error. Everything needed
* it automatically allocated. A pointer to an error message might be returned

View File

@ -73,6 +73,7 @@
#include <proto/auth.h>
#include <proto/acl.h>
#include <proto/arg.h>
#include <proto/backend.h>
#include <proto/channel.h>
#include <proto/checks.h>
@ -818,7 +819,8 @@ static void deinit_sample_arg(struct arg *p)
p++;
}
free(p_back);
if (p_back != empty_arg_list)
free(p_back);
}
static void deinit_stick_rules(struct list *rules)

View File

@ -320,6 +320,7 @@ struct sample_expr *sample_parse_expr(char **str, int *idx, char *err, int err_s
LIST_INIT(&(expr->conv_exprs));
expr->fetch = fetch;
expr->arg_p = empty_arg_list;
if (end != endw) {
char *err_msg = NULL;
@ -344,6 +345,9 @@ struct sample_expr *sample_parse_expr(char **str, int *idx, char *err, int err_s
goto out_error;
}
if (!expr->arg_p)
expr->arg_p = empty_arg_list;
if (fetch->val_args && !fetch->val_args(expr->arg_p, &err_msg)) {
p = my_strndup(str[*idx], endw - str[*idx]);
if (p) {
@ -436,6 +440,9 @@ struct sample_expr *sample_parse_expr(char **str, int *idx, char *err, int err_s
goto out_error;
}
if (!conv_expr->arg_p)
conv_expr->arg_p = empty_arg_list;
if (conv->val_args && !conv->val_args(conv_expr->arg_p, &err_msg)) {
p = my_strndup(str[*idx], endw - str[*idx]);
if (p) {