--- var.c 2002/03/04 11:37:34 1.75
+++ var.c 2002/03/04 11:53:27 1.76
@@ -72,19 +72,21 @@
/* the external context structure */
struct var_st {
- var_syntax_t syntax;
- char_class_t syntax_nameclass;
- var_cb_value_t cb_value_fct;
- void *cb_value_ctx;
+ var_syntax_t syntax;
+ char_class_t syntax_nameclass;
+ var_cb_value_t cb_value_fct;
+ void *cb_value_ctx;
+ var_cb_operation_t cb_operation_fct;
+ void *cb_operation_ctx;
};
/* the internal expansion context structure */
struct var_parse_st {
struct var_parse_st *lower;
- int force_expand;
- int rel_lookup_flag;
- int rel_lookup_cnt;
- int index_this;
+ int force_expand;
+ int rel_lookup_flag;
+ int rel_lookup_cnt;
+ int index_this;
};
typedef struct var_parse_st var_parse_t;
@@ -443,6 +445,7 @@
/* forward declarations */
static int parse_variable(var_t *var, var_parse_t *ctx, const char *begin, const char *end, tokenbuf_t *result);
static int parse_numexp (var_t *var, var_parse_t *ctx, const char *begin, const char *end, int *result, int *failed);
+static int parse_name (var_t *var, var_parse_t *ctx, const char *begin, const char *end);
/* parse substitution text */
static int
@@ -485,6 +488,71 @@
return (p - begin);
}
+/* parse opertion argument text */
+static int
+parse_opargtext(
+ var_t *var, var_parse_t *ctx,
+ const char *begin, const char *end)
+{
+ const char *p;
+
+ /* parse until delim_init or ')' */
+ for (p = begin; p != end && *p != var->syntax.delim_init && *p != ')'; p++) {
+ if (*p == var->syntax.escape) {
+ if (p + 1 == end)
+ return VAR_ERR_INCOMPLETE_QUOTED_PAIR;
+ p++;
+ }
+ }
+ return (p - begin);
+}
+
+static int
+parse_opargtext_or_variable(
+ var_t *var, var_parse_t *ctx,
+ const char *begin, const char *end,
+ tokenbuf_t *result)
+{
+ const char *p;
+ tokenbuf_t tmp;
+ int rc;
+
+ tokenbuf_init(result);
+ tokenbuf_init(&tmp);
+ p = begin;
+ if (p == end)
+ return 0;
+ do {
+ rc = parse_opargtext(var, ctx, p, end);
+ if (rc < 0)
+ goto error_return;
+ if (rc > 0) {
+ if (!tokenbuf_append(result, p, rc)) {
+ rc = VAR_ERR_OUT_OF_MEMORY;
+ goto error_return;
+ }
+ p += rc;
+ }
+ rc = parse_variable(var, ctx, p, end, &tmp);
+ if (rc < 0)
+ goto error_return;
+ if (rc > 0) {
+ p += rc;
+ if (!tokenbuf_merge(result, &tmp)) {
+ rc = VAR_ERR_OUT_OF_MEMORY;
+ goto error_return;
+ }
+ }
+ } while (rc > 0);
+ tokenbuf_free(&tmp);
+ return (p - begin);
+
+ error_return:
+ tokenbuf_free(&tmp);
+ tokenbuf_free(result);
+ return rc;
+}
+
/* parse expression or variable */
static int
parse_exptext_or_variable(
@@ -1314,6 +1382,62 @@
}
break;
}
+ case '%': {
+ /* operation callback function */
+ const char *op_ptr;
+ size_t op_len;
+ const char *arg_ptr;
+ size_t arg_len;
+ const char *val_ptr;
+ size_t val_len;
+ const char *out_ptr;
+ size_t out_len;
+ size_t out_size;
+ tokenbuf_t args;
+
+ p++;
+ rc = parse_name(var, ctx, p, end);
+ if (rc < 0)
+ goto error_return;
+ op_ptr = p;
+ op_len = rc;
+ p += rc;
+ if (*p == '(') {
+ p++;
+ tokenbuf_init(&args);
+ rc = parse_opargtext_or_variable(var, ctx, p, end, &args);
+ if (rc < 0)
+ goto error_return;
+ p += rc;
+ arg_ptr = args.begin;
+ arg_len = args.end - args.begin;
+ if (*p != ')') {
+ rc = VAR_ERR_MALFORMED_OPERATION_ARGUMENTS;
+ goto error_return;
+ }
+ p++;
+ }
+ else {
+ arg_ptr = NULL;
+ arg_len = 0;
+ }
+ val_ptr = data->begin;
+ val_len = data->end - data->begin;
+
+ if (data->begin != NULL && var->cb_operation_fct != NULL) {
+ /* call operation callback function */
+ rc = (*var->cb_operation_fct)(var, var->cb_operation_ctx,
+ op_ptr, op_len,
+ arg_ptr, arg_len,
+ val_ptr, val_len,
+ &out_ptr, &out_len, &out_size);
+ if (rc < 0)
+ goto error_return;
+ tokenbuf_free(data);
+ tokenbuf_set(data, out_ptr, out_ptr+out_len, out_size);
+ }
+ break;
+ }
default:
return VAR_ERR_UNKNOWN_COMMAND_CHAR;
}
@@ -2141,6 +2265,15 @@
var->cb_value_ctx = ctx;
break;
}
+ case VAR_CONFIG_CB_OPERATION: {
+ var_cb_operation_t fct;
+ void *ctx;
+ fct = (var_cb_operation_t)va_arg(ap, void *);
+ ctx = (void *)va_arg(ap, void *);
+ var->cb_operation_fct = fct;
+ var->cb_operation_ctx = ctx;
+ break;
+ }
default:
return VAR_RC(VAR_ERR_INVALID_ARGUMENT);
}
@@ -2266,6 +2399,8 @@
/* var_rc_t to string mapping table */
static const char *var_errors[] = {
"everything ok", /* VAR_OK = 0 */
+ "undefined operation", /* VAR_ERR_UNDEFINED_OPERATION */
+ "malformed operation argument list", /* VAR_ERR_MALFORMED_OPERATION_ARGUMENTS */
"incomplete named character", /* VAR_ERR_INCOMPLETE_NAMED_CHARACTER */
"incomplete hexadecimal value", /* VAR_ERR_INCOMPLETE_HEX */
"invalid hexadecimal value", /* VAR_ERR_INVALID_HEX */
|