diff options
| author | Nalin Dahyabhai <nalin.dahyabhai@pobox.com> | 2008-06-25 17:15:48 -0400 |
|---|---|---|
| committer | Nalin Dahyabhai <nalin.dahyabhai@pobox.com> | 2008-06-25 17:15:48 -0400 |
| commit | 426d0e119a45f04baab4f007fe6526724a905edb (patch) | |
| tree | f8153af276ef00691953cdd443a3be814ac919de /src/format.c | |
| parent | 6b3652f1ae84efa950180095d9b78fc68974183d (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/format.c')
| -rw-r--r-- | src/format.c | 266 |
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) { |
