summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorNalin Dahyabhai <nalin.dahyabhai@pobox.com>2008-06-25 17:15:48 -0400
committerNalin Dahyabhai <nalin.dahyabhai@pobox.com>2008-06-25 17:15:48 -0400
commit426d0e119a45f04baab4f007fe6526724a905edb (patch)
treef8153af276ef00691953cdd443a3be814ac919de /src
parent6b3652f1ae84efa950180095d9b78fc68974183d (diff)
- drop up/down functions
- start passing around a structure for storing values when we have more than one value -- the outbuf gets an empty string as a placeholder, and we return a list of {offset pointer, list of values}
Diffstat (limited to 'src')
-rw-r--r--src/format.c266
1 files changed, 142 insertions, 124 deletions
diff --git a/src/format.c b/src/format.c
index d360efb..ccd3c9e 100644
--- a/src/format.c
+++ b/src/format.c
@@ -48,11 +48,17 @@
#define DEFAULT_BUFFER_SIZE 0x1000
#define MAX_BUFFER_SIZE 0x100000
+struct format_choice {
+ char *offset;
+ char **values;
+ struct format_choice *next;
+};
static int format_expand(struct plugin_state *state,
Slapi_PBlock *pb, Slapi_Entry *e,
const char *domain, const char *map,
const char *fmt, const char *disallowed,
char *outbuf, int outbuf_len,
+ struct format_choice **outbuf_choices,
char ***ref_attrs,
struct format_inref_attr ***inref_attrs,
bool_t is_simple_expression);
@@ -91,6 +97,11 @@ format_dup_attr_list(char **attr_list)
}
return ret;
}
+static char **
+format_dup_strlist(char **strlist)
+{
+ return format_dup_attr_list(strlist);
+}
void
format_add_attr_list(char ***attr_list, const char *value)
@@ -135,6 +146,11 @@ format_free_attr_list(char **attr_list)
free(attr_list);
}
}
+static void
+format_free_strlist(char **strlist)
+{
+ return format_free_attr_list(strlist);
+}
struct format_inref_attr **
format_dup_inref_attrs(struct format_inref_attr **attrs)
@@ -219,6 +235,37 @@ format_free_inref_attrs(struct format_inref_attr **attrs)
}
}
+/* Add a new entry to the "choice" list. */
+static void
+format_append_choice(struct format_choice **choices,
+ struct format_choice *choice)
+{
+ struct format_choice *here;
+ if (choices == NULL) {
+ return;
+ }
+ if (*choices == NULL) {
+ *choices = choice;
+ } else {
+ here = *choices;
+ while (here->next != NULL) {
+ here = here->next;
+ }
+ here->next = choice;
+ }
+}
+static void
+format_add_choice(struct format_choice **choices, char *offset, char **values)
+{
+ struct format_choice *choice, *here;
+ choice = malloc(sizeof(*choice));
+ if (choice != NULL) {
+ choice->offset = offset;
+ choice->values = format_dup_strlist(values);
+ format_append_choice(choices, choice);
+ }
+}
+
/* Parse an argument string into an array of arguments. */
static void
format_free_parsed_args(char **argv)
@@ -287,7 +334,7 @@ static int
format_echo(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
const char *domain, const char *map,
const char *args, const char *disallowed,
- char *outbuf, int outbuf_len,
+ char *outbuf, int outbuf_len, struct format_choice **outbuf_choices,
char ***ref_attrs, struct format_inref_attr ***inref_attrs)
{
int ret, i, argc, len;
@@ -328,6 +375,7 @@ format_first(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
const char *domain, const char *map,
const char *args, const char *disallowed,
char *outbuf, int outbuf_len,
+ struct format_choice **outbuf_choices,
char ***ref_attrs, struct format_inref_attr ***inref_attrs)
{
int ret, i, len, slen, count, argc;
@@ -380,7 +428,7 @@ static int
format_list(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
const char *domain, const char *map,
const char *args, const char *disallowed,
- char *outbuf, int outbuf_len,
+ char *outbuf, int outbuf_len, struct format_choice **outbuf_choices,
char ***ref_attrs, struct format_inref_attr ***inref_attrs)
{
int ret, i, j, len, slen, count, argc;
@@ -461,6 +509,7 @@ format_deref(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
const char *domain, const char *map,
const char *args, const char *disallowed,
char *outbuf, int outbuf_len,
+ struct format_choice **outbuf_choices,
char ***ref_attrs, struct format_inref_attr ***inref_attrs)
{
int i, j, len, slen, ret, count, argc;
@@ -687,6 +736,7 @@ format_referred(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
const char *domain, const char *map,
const char *args, const char *disallowed,
char *outbuf, int outbuf_len,
+ struct format_choice **outbuf_choices,
char ***ref_attrs, struct format_inref_attr ***inref_attrs)
{
int i, j, len, slen, ret, count, argc;
@@ -816,10 +866,12 @@ format_merge(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
const char *domain, const char *map,
const char *args, const char *disallowed,
char *outbuf, int outbuf_len,
+ struct format_choice **outbuf_choices,
char ***ref_attrs, struct format_inref_attr ***inref_attrs)
{
int ret, i, argc, len, slen, count;
char **argv;
+ struct format_choice *these_choices;
ret = format_parse_args(state, args, &argc, &argv);
if (ret != 0) {
slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
@@ -837,10 +889,12 @@ format_merge(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
/* Expand this argument. */
slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
"merge: expanding ->%s<-\n", argv[i]);
+ these_choices = NULL;
len = format_expand(state, pb, e, domain, map,
argv[i], disallowed,
outbuf + ret + (count ? slen : 0),
outbuf_len - (ret + (count ? slen : 0)),
+ &these_choices,
ref_attrs, inref_attrs, FALSE);
if (len < 0) {
slapi_log_error(SLAPI_LOG_PLUGIN,
@@ -852,7 +906,15 @@ format_merge(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
}
/* If it didn't expand to anything, just keep going. */
if (len == 0) {
- continue;
+ if (these_choices == NULL) {
+ /* No choices, ignore this expression. */
+ continue;
+ } else {
+ /* Make note of the choices, and accept a
+ * zero-length value as a placeholder. */
+ format_append_choice(outbuf_choices,
+ these_choices);
+ }
}
/* Log this value. */
slapi_log_error(SLAPI_LOG_PLUGIN,
@@ -872,83 +934,6 @@ format_merge(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
return ret;
}
-/* Evaluate the only argument and upper-case it. */
-static int
-format_case(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
- const char *domain, const char *map,
- const char *args, const char *disallowed,
- char *outbuf, int outbuf_len,
- char ***ref_attrs, struct format_inref_attr ***inref_attrs,
- const char *fnname, int (*cb)(int))
-{
- int ret, i, j, argc, len;
- char **argv;
- ret = format_parse_args(state, args, &argc, &argv);
- if (ret != 0) {
- slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
- "%s: error parsing arguments\n", fnname);
- return -EINVAL;
- }
- if (argc < 1) {
- slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
- "%s: requires at least one argument\n", fnname);
- format_free_parsed_args(argv);
- return -EINVAL;
- }
- for (i = 0, ret = 0; i < argc; i++) {
- /* Get the length of the expanded value of this argument. */
- len = format_expand(state, pb, e, domain, map,
- argv[i], disallowed,
- outbuf + ret, outbuf_len - ret,
- ref_attrs, inref_attrs, FALSE);
- if (len < 0) {
- slapi_log_error(SLAPI_LOG_PLUGIN,
- state->plugin_desc->spd_id,
- "%s: error expanding \"%s\'\n",
- argv[i], fnname);
- return -ENOBUFS;
- }
- /* Check that we've got space for this argument. */
- if (ret + len > outbuf_len) {
- slapi_log_error(SLAPI_LOG_PLUGIN,
- state->plugin_desc->spd_id,
- "%s: out of space\n", fnname);
- return -ENOBUFS;
- }
- /* Append the text of the argument. */
- for (j = 0; j < len; j++) {
- outbuf[ret + j] = (*cb)(outbuf[ret + j]);
- }
- ret += len;
- }
- format_free_parsed_args(argv);
- return ret;
-}
-
-static int
-format_up(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
- const char *domain, const char *map,
- const char *args, const char *disallowed,
- char *outbuf, int outbuf_len,
- char ***ref_attrs, struct format_inref_attr ***inref_attrs)
-{
- return format_case(state, pb, e, domain, map, args, disallowed,
- outbuf, outbuf_len,
- ref_attrs, inref_attrs, "up", toupper);
-}
-
-static int
-format_down(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
- const char *domain, const char *map,
- const char *args, const char *disallowed,
- char *outbuf, int outbuf_len,
- char ***ref_attrs, struct format_inref_attr ***inref_attrs)
-{
- return format_case(state, pb, e, domain, map, args, disallowed,
- outbuf, outbuf_len,
- ref_attrs, inref_attrs, "down", tolower);
-}
-
/* Look up the entry's values for the attribute named by the first argument,
* and use the callback to check if they match the second argument. If we find
* exactly one match, store it in the output buffer, otherwise store the text
@@ -961,6 +946,7 @@ format_match_generic(struct plugin_state *state,
const char *args, int min_args, int default_arg,
const char *disallowed,
char *outbuf, int outbuf_len,
+ struct format_choice **outbuf_choices,
char ***ref_attrs,
struct format_inref_attr ***inref_attrs,
const char *fnname,
@@ -1054,28 +1040,35 @@ format_match_generic(struct plugin_state *state,
/* No errors. */
break;
default:
- /* Too many matches. */
- if (argv[default_arg] != NULL) {
- slapi_log_error(SLAPI_LOG_PLUGIN,
- state->plugin_desc->spd_id,
- "%s: too many matching values for "
- "\"%s\", using default value \"%s\"\n",
- fnname, argv[1], argv[default_arg]);
- free(matched);
- matched = strdup(argv[default_arg]);
- } else {
- slapi_log_error(SLAPI_LOG_PLUGIN,
- state->plugin_desc->spd_id,
- "%s: too many matching values for "
- "\"%s\", and no default value\n",
- fnname, argv[1]);
- if (values != NULL) {
- slapi_vattr_values_free(&values, &actual_attr,
- buffer_flags);
+ if (outbuf_choices == NULL) {
+ /* Too many matches. */
+ if (argv[default_arg] != NULL) {
+ slapi_log_error(SLAPI_LOG_PLUGIN,
+ state->plugin_desc->spd_id,
+ "%s: too many matching values "
+ "for \"%s\", using default "
+ "value \"%s\"\n",
+ fnname, argv[1],
+ argv[default_arg]);
+ free(matched);
+ matched = strdup(argv[default_arg]);
+ } else {
+ slapi_log_error(SLAPI_LOG_PLUGIN,
+ state->plugin_desc->spd_id,
+ "%s: too many matching values "
+ "for \"%s\", and no default "
+ "value\n", fnname, argv[1]);
+ if (values != NULL) {
+ slapi_vattr_values_free(&values,
+ &actual_attr,
+ buffer_flags);
+ }
+ free(matched);
+ format_free_parsed_args(argv);
+ return -ENOENT;
}
- free(matched);
- format_free_parsed_args(argv);
- return -ENOENT;
+ } else {
+ /* XXX */
}
break;
}
@@ -1112,11 +1105,13 @@ format_match(struct plugin_state *state,
const char *domain, const char *map,
const char *args, const char *disallowed,
char *outbuf, int outbuf_len,
+ struct format_choice **outbuf_choices,
char ***ref_attrs, struct format_inref_attr ***inref_attrs)
{
return format_match_generic(state, pb, e, domain, map, args, 2, 2,
disallowed,
- outbuf, outbuf_len, ref_attrs, inref_attrs,
+ outbuf, outbuf_len, outbuf_choices,
+ ref_attrs, inref_attrs,
"format_match", format_match_cb);
}
@@ -1141,11 +1136,13 @@ format_regmatch(struct plugin_state *state,
const char *domain, const char *map,
const char *args, const char *disallowed,
char *outbuf, int outbuf_len,
+ struct format_choice **outbuf_choices,
char ***ref_attrs, struct format_inref_attr ***inref_attrs)
{
return format_match_generic(state, pb, e, domain, map, args, 2, 2,
disallowed,
- outbuf, outbuf_len, ref_attrs, inref_attrs,
+ outbuf, outbuf_len, outbuf_choices,
+ ref_attrs, inref_attrs,
"format_regmatch", format_regmatch_cb);
}
@@ -1263,11 +1260,13 @@ format_regsub(struct plugin_state *state,
const char *domain, const char *map,
const char *args, const char *disallowed,
char *outbuf, int outbuf_len,
+ struct format_choice **outbuf_choices,
char ***ref_attrs, struct format_inref_attr ***inref_attrs)
{
return format_match_generic(state, pb, e, domain, map, args, 3, 3,
disallowed,
- outbuf, outbuf_len, ref_attrs, inref_attrs,
+ outbuf, outbuf_len, outbuf_choices,
+ ref_attrs, inref_attrs,
"format_regsub", format_regsub_cb);
}
@@ -1283,12 +1282,11 @@ format_lookup_fn(const char *fnname)
const char *domain, const char *map,
const char *args, const char *disallowed,
char *outbuf, int outbuf_len,
+ struct format_choice **outbuf_choices,
char ***ref_attrs,
struct format_inref_attr ***inref_attrs);
} fns[] = {
{"echo", format_echo},
- {"up", format_up},
- {"down", format_down},
{"first", format_first},
{"list", format_list},
{"deref", format_deref},
@@ -1361,7 +1359,7 @@ format_single(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
tmp_values[j++] = strdup(cret);
}
tmp_values[j] = NULL;
- *values = format_dup_attr_list(tmp_values);
+ *values = format_dup_strlist(tmp_values);
for (i = 0; tmp_values[i] != NULL; i++) {
free(tmp_values[i]);
}
@@ -1610,6 +1608,7 @@ format_expand_simple(struct plugin_state *state,
const char *domain, const char *map,
const char *fmt, const char *disallowed,
char *outbuf, int outbuf_len,
+ struct format_choice **outbuf_choices,
char ***ref_attrs, struct format_inref_attr ***inref_attrs)
{
char *shortstart, *longstart, *shortend, *longend, **value_list;
@@ -1706,31 +1705,42 @@ format_expand_simple(struct plugin_state *state,
/* Retrieve the value. */
value_list = NULL;
tmp = format_single(state, pb, e, attribute, disallowed, &value_list);
- format_free_attr_list(value_list);
if (tmp == NULL) {
/* The attribute is undefined, or we're treating it as if it
* is. */
- if (default_value != NULL) {
- /* Supply the default value, expanding it if needed. */
- i = format_expand(state, pb, e,
- domain, map, default_value, NULL,
- outbuf, outbuf_len,
- ref_attrs, inref_attrs, FALSE);
- free(expr);
- return i;
+ if (value_list == NULL) {
+ if (default_value != NULL) {
+ /* Supply the default value, expanding it if
+ * needed. */
+ i = format_expand(state, pb, e,
+ domain, map,
+ default_value, NULL,
+ outbuf, outbuf_len,
+ outbuf_choices,
+ ref_attrs, inref_attrs,
+ FALSE);
+ free(expr);
+ return i;
+ } else {
+ /* No value, and no default: FAIL. */
+ free(expr);
+ return -ENOENT;
+ }
} else {
- /* No value, and no default: FAIL. */
- free(expr);
- return -ENOENT;
+ /* Store nothing in the immediate position, but return
+ * a note that any of these values would be fine at
+ * this point in the output string. */
+ format_add_choice(outbuf_choices, outbuf, value_list);
+ format_free_strlist(value_list);
+ return 0;
}
} else {
- /* There's no value defined (or it's multi-valued, which is
- * usually trouble). */
+ /* There's a value defined. */
if (alternate_value != NULL) {
/* Supply the alternate value. */
i = format_expand(state, pb, e,
domain, map, alternate_value, NULL,
- outbuf, outbuf_len,
+ outbuf, outbuf_len, outbuf_choices,
ref_attrs, inref_attrs, FALSE);
free(tmp);
free(expr);
@@ -1770,6 +1780,7 @@ format_expand(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
const char *domain, const char *map,
const char *fmt, const char *disallowed,
char *outbuf, int outbuf_len,
+ struct format_choice **outbuf_choices,
char ***ref_attrs, struct format_inref_attr ***inref_attrs,
bool_t is_simple_expression)
{
@@ -1787,6 +1798,7 @@ format_expand(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
const char *domain, const char *map,
const char *args, const char *disallowed,
char *outbuf, int outbuf_len,
+ struct format_choice **outbuf_choices,
char ***ref_attrs,
struct format_inref_attr ***inref_attrs);
@@ -1854,6 +1866,7 @@ format_expand(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
disallowed,
expr + j,
exp_size - j,
+ outbuf_choices,
ref_attrs,
inref_attrs);
if (exp_used < 0) {
@@ -1962,6 +1975,7 @@ format_expand(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
domain, map,
tmp, disallowed,
expr + j, exp_size - j,
+ outbuf_choices,
ref_attrs, inref_attrs);
free(tmp);
if (exp_used < 0) {
@@ -2007,6 +2021,7 @@ format_expand(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
exp_used = format_expand_simple(state, pb, e, domain, map,
expr, disallowed,
outbuf, outbuf_len,
+ outbuf_choices,
ref_attrs, inref_attrs);
if (exp_used < 0) {
free(expr);
@@ -2031,6 +2046,7 @@ static char *
format_format(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
const char *domain, const char *map,
const char *fmt, const char *disallowed,
+ struct format_choice **choices,
char ***ref_attrs, struct format_inref_attr ***inref_attrs)
{
char *buf, *tmp, *ret, *spd_id;
@@ -2052,7 +2068,8 @@ format_format(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
}
i = format_expand(state, pb, e, domain, map, fmt, disallowed,
- buf, buflen, ref_attrs, inref_attrs, FALSE);
+ buf, buflen, choices,
+ ref_attrs, inref_attrs, FALSE);
if ((i >= 0) && (i < buflen)) {
buf[i] = '\0';
ret = strdup(buf);
@@ -2104,6 +2121,7 @@ format_get_data(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
{
Slapi_PBlock *local_pb;
char ***ndn_list, **local_ndn_list, *ret;
+ struct format_choice *choices;
/* Supply a PBlock if the caller didn't. */
if (pb == NULL) {
@@ -2114,7 +2132,7 @@ format_get_data(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
}
ret = format_format(state, pb, e, domain, map, fmt, disallowed,
- ref_attrs, inref_attrs);
+ NULL, ref_attrs, inref_attrs);
/* If we supplied a PBlock, clean it up. */
if (pb == local_pb) {