extern const char *smp_to_type[SMP_TYPES];
-struct sample_expr *sample_parse_expr(char **str, int *idx, const char *file, int line, char **err, struct arg_list *al);
+struct sample_expr *sample_parse_expr(char **str, int *idx, const char *file, int line, char **err, struct arg_list *al, char **endptr);
struct sample_conv *find_sample_conv(const char *kw, int len);
struct sample *sample_process(struct proxy *px, struct session *sess,
struct stream *strm, unsigned int opt,
* so, we retrieve a completely parsed expression with args and
* convs already done.
*/
- smp = sample_parse_expr((char **)args, &idx, file, line, err, al);
+ smp = sample_parse_expr((char **)args, &idx, file, line, err, al, NULL);
if (!smp) {
memprintf(err, "%s in ACL expression '%s'", *err, *args);
goto out_return;
}
curproxy->conf.args.ctx = ARGC_STK;
- expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
+ expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args, NULL);
if (!expr) {
ha_alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
err_code |= ERR_ALERT | ERR_FATAL;
cur_arg = cur_arg + 1;
- expr = sample_parse_expr((char **)args, &cur_arg, px->conf.args.file, px->conf.args.line, err, &px->conf.args);
+ expr = sample_parse_expr((char **)args, &cur_arg, px->conf.args.file, px->conf.args.line, err, &px->conf.args, NULL);
if (!expr)
goto do_resolve_parse_error;
}
arg->expr = sample_parse_expr((char*[]){delim, NULL},
&idx, file, linenum, &errmsg,
- &curproxy->conf.args);
+ &curproxy->conf.args, NULL);
if (arg->expr == NULL) {
ha_alert("parsing [%s:%d] : '%s': %s.\n", file, linenum, args[0], errmsg);
err_code |= ERR_ALERT | ERR_FATAL;
}
cur_arg = *orig_arg;
- expr = sample_parse_expr((char **)args, &cur_arg, px->conf.args.file, px->conf.args.line, err, &px->conf.args);
+ expr = sample_parse_expr((char **)args, &cur_arg, px->conf.args.file, px->conf.args.line, err, &px->conf.args, NULL);
if (!expr)
return ACT_RET_PRS_ERR;
}
cur_arg = *orig_arg;
- expr = sample_parse_expr((char **)args, &cur_arg, px->conf.args.file, px->conf.args.line, err, &px->conf.args);
+ expr = sample_parse_expr((char **)args, &cur_arg, px->conf.args.file, px->conf.args.line, err, &px->conf.args, NULL);
if (!expr)
return ACT_RET_PRS_ERR;
cur_arg = *orig_arg;
expr = sample_parse_expr((char **)args, &cur_arg, px->conf.args.file, px->conf.args.line,
- err, &px->conf.args);
+ err, &px->conf.args, NULL);
if (!expr)
return ACT_RET_PRS_ERR;
cmd[1] = "";
cmd_arg = 0;
- expr = sample_parse_expr(cmd, &cmd_arg, curpx->conf.args.file, curpx->conf.args.line, err, &curpx->conf.args);
+ expr = sample_parse_expr(cmd, &cmd_arg, curpx->conf.args.file, curpx->conf.args.line, err, &curpx->conf.args, NULL);
if (!expr) {
memprintf(err, "failed to parse sample expression <%s> : %s", text, *err);
goto error_free;
unsigned int where;
cur_arg = *orig_arg;
- expr = sample_parse_expr((char **)args, &cur_arg, px->conf.args.file, px->conf.args.line, err, &px->conf.args);
+ expr = sample_parse_expr((char **)args, &cur_arg, px->conf.args.file, px->conf.args.line, err, &px->conf.args, NULL);
if (!expr)
return ACT_RET_PRS_ERR;
unsigned int where = 0;
rule->arg.expr = sample_parse_expr((char **)args, arg, px->conf.args.file,
- px->conf.args.line, err, &px->conf.args);
+ px->conf.args.line, err, &px->conf.args, NULL);
if (!rule->arg.expr)
return ACT_RET_PRS_ERR;
unsigned int where = 0;
rule->arg.expr = sample_parse_expr((char **)args, arg, px->conf.args.file,
- px->conf.args.line, err, &px->conf.args);
+ px->conf.args.line, err, &px->conf.args, NULL);
if (!rule->arg.expr)
return ACT_RET_PRS_ERR;
* fetch keyword followed by format conversion keywords.
* Returns a pointer on allocated sample expression structure.
* The caller must have set al->ctx.
+ * If <endptr> is non-nul, it will be set to the first unparsed character
+ * (which may be the final '\0') on success. If it is nul, the expression
+ * must be properly terminated by a '\0' otherwise an error is reported.
*/
-struct sample_expr *sample_parse_expr(char **str, int *idx, const char *file, int line, char **err_msg, struct arg_list *al)
+struct sample_expr *sample_parse_expr(char **str, int *idx, const char *file, int line, char **err_msg, struct arg_list *al, char **endptr)
{
const char *begw; /* beginning of word */
const char *endw; /* end of word */
int argcnt;
if (*endt && *endt != ',') {
+ if (endptr) {
+ /* end found, let's stop here */
+ break;
+ }
if (ckw)
memprintf(err_msg, "missing comma after converter '%s'", ckw);
else
conv = find_sample_conv(begw, endw - begw);
if (!conv) {
/* we found an isolated keyword that we don't know, it's not ours */
- if (begw == str[*idx])
+ if (begw == str[*idx]) {
+ endt = begw;
break;
+ }
memprintf(err_msg, "unknown converter '%s'", ckw);
goto out_error;
}
}
}
+ if (endptr) {
+ /* end found, let's stop here */
+ *endptr = (char *)endt;
+ }
+
out:
free(fkw);
free(ckw);
idx = 0;
px->conf.args.ctx = ARGC_SRV;
- return sample_parse_expr((char **)args, &idx, file, linenum, err, &px->conf.args);
+ return sample_parse_expr((char **)args, &idx, file, linenum, err, &px->conf.args, NULL);
}
static int server_parse_sni_expr(struct server *newsrv, struct proxy *px, char **err)
rule->arg.gpt.value = strtol(args[*arg], &error, 10);
if (*error != '\0') {
rule->arg.gpt.expr = sample_parse_expr((char **)args, arg, px->conf.args.file,
- px->conf.args.line, err, &px->conf.args);
+ px->conf.args.line, err, &px->conf.args, NULL);
if (!rule->arg.gpt.expr)
return ACT_RET_PRS_ERR;
arg++;
curpx->conf.args.ctx = ARGC_CAP;
- expr = sample_parse_expr(args, &arg, file, line, err, &curpx->conf.args);
+ expr = sample_parse_expr(args, &arg, file, line, err, &curpx->conf.args, NULL);
if (!expr) {
memprintf(err,
"'%s %s %s' : %s",
}
curpx->conf.args.ctx = ARGC_TRK;
- expr = sample_parse_expr(args, &arg, file, line, err, &curpx->conf.args);
+ expr = sample_parse_expr(args, &arg, file, line, err, &curpx->conf.args, NULL);
if (!expr) {
memprintf(err,
"'%s %s %s' : %s",
kw_name = args[*arg-1];
rule->arg.vars.expr = sample_parse_expr((char **)args, arg, px->conf.args.file,
- px->conf.args.line, err, &px->conf.args);
+ px->conf.args.line, err, &px->conf.args, NULL);
if (!rule->arg.vars.expr)
return ACT_RET_PRS_ERR;