static char proto_name_prev[128];
static dl_t *dl;
static dl_loader_t *dl_loader;
+static const char *process_filename;
+static int process_lineno;
/** Concatenate error stack
*/
ssize_t dec_len;
char const *error = NULL;
fr_cond_t *cond;
- CONF_SECTION *this;
+ CONF_SECTION *cs;
- this = cf_section_alloc(NULL, NULL, "if", "condition");
- if (!this) {
+ cs = cf_section_alloc(NULL, NULL, "if", "condition");
+ if (!cs) {
snprintf(output, outlen, "ERROR out of memory");
return;
}
+ cf_filename_set(cs, process_filename);
+ cf_lineno_set(cs, process_lineno);
- dec_len = fr_cond_tokenize(NULL, &cond, &error, dict, this, input, NULL, 0);
- talloc_free(this);
+ dec_len = fr_cond_tokenize(cs, &cond, &error, dict, input);
if (dec_len <= 0) {
+ talloc_free(cs);
snprintf(output, outlen, "ERROR offset %d %s", (int) -dec_len, error);
return;
}
input += dec_len;
if (*input != '\0') {
- talloc_free(cond);
+ talloc_free(cs);
snprintf(output, outlen, "ERROR offset %d 'Too much text'", (int) dec_len);
return;
}
cond_snprint(output, outlen, cond);
- talloc_free(cond);
+ talloc_free(cs);
}
static void parse_xlat(fr_dict_t const *dict, char const *input, char *output, size_t outlen)
lineno = 0;
*output = '\0';
data_len = 0;
+ process_filename = filename;
while (fgets(buffer, sizeof(buffer), fp) != NULL) {
char *p = strchr(buffer, '\n'), *q;
fr_skip_whitespace(p);
if (!*p) continue;
+ process_lineno = lineno;
DEBUG2("%s[%d]: %s\n", filename, lineno, buffer);
strlcpy(input, p, sizeof(input));
cd = cf_data_find_in_parent(this, fr_dict_t **, "dictionary");
if (cd) dict = *((fr_dict_t **)cf_data_value(cd));
+ /*
+ * fr_cond_tokenize needs the current section, so we create it first.
+ */
+ css = cf_section_alloc(this, this, buff[1], buff[2]);
+ if (!css) {
+ ERROR("%s[%d]: Failed allocating memory for section", filename, *lineno);
+ return NULL;
+ }
+ css->item.filename = filename;
+ css->item.lineno = *lineno;
+
/*
* Skip (...) to find the {
*/
- slen = fr_cond_tokenize(this, &cond, &error, dict,
- this, ptr, filename, *lineno);
+ slen = fr_cond_tokenize(css, &cond, &error, dict, ptr);
if (slen < 0) {
char *spaces, *text;
talloc_free(spaces);
talloc_free(text);
- talloc_free(cond);
+ talloc_free(css);
return NULL;
}
* into.
*/
if ((size_t) slen >= (talloc_array_length(buff[2]) - 1)) {
- talloc_free(cond);
+ talloc_free(css);
ERROR("%s[%d]: Condition is too large after \"%s\"", filename, *lineno, buff[1]);
return NULL;
}
if (*ptr != '{') {
ERROR("%s[%d]: Expected '{' instead of %s", filename, *lineno, ptr);
- talloc_free(cond);
+ talloc_free(css);
return NULL;
}
ptr++;
- css = cf_section_alloc(this, this, buff[1], buff[2]);
- if (!css) {
- ERROR("%s[%d]: Failed allocating memory for section", filename, *lineno);
- talloc_free(cond);
- return NULL;
- }
- css->item.filename = filename;
- css->item.lineno = *lineno;
-
+ /*
+ * Now that the CONF_SECTION and condition are OK, add
+ * the condition to the CONF_SECTION.
+ */
cf_data_add(css, cond, NULL, false);
*ptr_p = ptr;
return css;
static ssize_t cond_preparse(TALLOC_CTX *ctx, char const **out, size_t *outlen, char const *start,
FR_TOKEN *type, char const **error,
fr_dict_attr_t const **castda, bool require_regex,
- CONF_SECTION *parent, char const *filename, int lineno)
+ CONF_SECTION *cs)
{
ssize_t slen, my_slen;
char *p, *expanded;
+ int lineno;
char buffer[8192];
/*
return slen;
}
- if (!cf_expand_variables(filename, &lineno, parent, buffer, sizeof(buffer), start, slen, NULL)) {
+ lineno = cf_lineno(cs);
+ if (!cf_expand_variables(cf_filename(cs), &lineno, cf_item_to_section(cf_parent(cs)),
+ buffer, sizeof(buffer), start, slen, NULL)) {
*error = "Failed expanding configuration variable";
return -1;
}
/** Tokenize a conditional check
*
- * @param[in] ctx for talloc
+ * @param[in] ctx talloc ctx
+ * @param[in] cs our configuration section
* @param[out] pcond pointer to the returned condition structure
* @param[out] error the parse error (if any)
- * @param[in] parent the parent CONF_SECTION
* @param[in] start the start of the string to process. Should be "(..."
* @param[in] brace look for a closing brace (how many deep we are)
* @param[in] rules for attribute parsing
- * @param[in] filename filename we read the condition from
- * @param[in] lineno line where we read the condition from
* @return
* - Length of the string skipped.
* - < 0 (the offset to the offending error) on error.
*/
-static ssize_t cond_tokenize(TALLOC_CTX *ctx, fr_cond_t **pcond, char const **error,
- CONF_SECTION *parent, char const *start, int brace,
- vp_tmpl_rules_t const *rules, char const *filename, int lineno)
+static ssize_t cond_tokenize(TALLOC_CTX *ctx, CONF_SECTION *cs,
+ fr_cond_t **pcond, char const **error,
+ char const *start, int brace,
+ vp_tmpl_rules_t const *rules)
{
ssize_t slen, tlen;
char const *p = start;
* brackets. Go recurse to get more.
*/
c->type = COND_TYPE_CHILD;
- c->ci = cf_section_to_item(parent);
- slen = cond_tokenize(c, &c->data.child, error, parent, p, brace + 1, rules, filename, lineno);
+ c->ci = cf_section_to_item(cs);
+ slen = cond_tokenize(c, cs, &c->data.child, error, p, brace + 1, rules);
if (slen <= 0) return_SLEN;
if (!c->data.child) {
/*
* Grab the LHS
*/
- slen = cond_preparse(c, &lhs, &lhs_len, p, &lhs_type, error, &c->cast, false, parent, filename, lineno);
+ slen = cond_preparse(c, &lhs, &lhs_len, p, &lhs_type, error, &c->cast, false, cs);
if (slen <= 0) {
return_SLEN;
}
}
c->type = COND_TYPE_EXISTS;
- c->ci = cf_section_to_item(parent);
+ c->ci = cf_section_to_item(cs);
tlen = tmpl_afrom_str(c, &c->data.vpt,
lhs, lhs_len, lhs_type, &parse_rules, true);
* The next thing should now be a comparison operator.
*/
c->type = COND_TYPE_MAP;
- c->ci = cf_section_to_item(parent);
+ c->ci = cf_section_to_item(cs);
switch (*p) {
default:
return_P("Expected text after operator");
}
- slen = cond_preparse(c, &rhs, &rhs_len, p, &rhs_type, error, NULL, regex, parent, filename, lineno);
+ slen = cond_preparse(c, &rhs, &rhs_len, p, &rhs_type, error, NULL, regex, cs);
if (slen <= 0) {
return_SLEN;
}
#endif
/*
- * Save the parent for later.
+ * Save the current config section for later.
*/
- c->data.map->ci = cf_section_to_item(parent);
+ c->data.map->ci = cf_section_to_item(cs);
/*
* We cannot compare lists to anything.
/*
* May still be looking for a closing brace.
*/
- slen = cond_tokenize(c, &c->next, error, parent, p, brace, rules, filename, lineno);
+ slen = cond_tokenize(c, cs, &c->next, error, p, brace, rules);
if (slen <= 0) {
return_slen:
talloc_free(c);
/** Tokenize a conditional check
*
- * @param[in] ctx for talloc
+ * @param[in] cs current CONF_SECTION and talloc ctx
* @param[out] head the parsed condition structure
* @param[out] error the parse error (if any)
* @param[in] dict dictionary to resolve attributes in.
- * @param[in] parent the parent CONF_SECTION
* @param[in] start the start of the string to process. Should be "(..."
- * @param[in] filename filename we read the condition from
- * @param[in] lineno line where we read the condition from
* @return
* - Length of the string skipped.
* - < 0 (the offset to the offending error) on error.
*/
-ssize_t fr_cond_tokenize(TALLOC_CTX *ctx,
+ssize_t fr_cond_tokenize(CONF_SECTION *cs,
fr_cond_t **head, char const **error,
- fr_dict_t const *dict,
- CONF_SECTION *parent, char const *start,
- char const *filename, int lineno)
+ fr_dict_t const *dict, char const *start)
{
- return cond_tokenize(ctx, head, error, parent, start, 0, &(vp_tmpl_rules_t){ .dict_def = dict },
- filename, lineno);
+ return cond_tokenize(cs, cs, head, error, start, 0, &(vp_tmpl_rules_t){ .dict_def = dict });
}
/*