ktrace: Use the ccli_list_* helper functions for completions
Managing the list of completions is tedious and error prone, use the
helper functions now provided by the ccli library for managing the list of
completions to return.
Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
diff --git a/src/create.c b/src/create.c
index 38cb0b6..bd851d8 100644
--- a/src/create.c
+++ b/src/create.c
@@ -502,7 +502,7 @@
return cnt;
}
-static int load_available_filter(char ***list, char *match)
+static int load_available_filter(struct ccli *ccli, char ***list, char *match)
{
char **funcs = NULL;
char **mods = NULL;
@@ -511,10 +511,10 @@
char *p;
int ret;
int cnt = 0;
+ int fcnt = 0;
int mcnt = 0;
int i;
- *list = NULL;
if ((p = strchr(match, ':'))) {
mod = strdup(match);
if (!mod)
@@ -532,24 +532,23 @@
if (ret < 0)
goto out;
- cnt = tracefs_list_size(funcs);
- if (cnt < 0)
+ fcnt = tracefs_list_size(funcs);
+ if (fcnt < 0)
goto out;
- *list = calloc(cnt + mcnt, sizeof(**list));
for (i = 0; i < mcnt; i++) {
- (*list)[i] = mods[i];
+ ret = ccli_list_insert(ccli, list, &cnt, mods[i]);
+ if (ret < 0)
+ goto out;
mods[i] = NULL;
}
- for (i = 0; i < cnt; i++) {
- if (mod) {
- ret = asprintf(&p, "%s:%s", mod, funcs[i]);
- if (ret < 0)
- p = NULL;
- } else
- p = strdup(funcs[i]);
- (*list)[i + mcnt] = p;
+ for (i = 0; i < fcnt; i++) {
+ if (mod)
+ ret = ccli_list_add_printf(ccli, list, &cnt,
+ "%s:%s", mod, funcs[i]);
+ else
+ ret = ccli_list_add(ccli, list, &cnt, funcs[i]);
}
out:
tracefs_list_free(funcs);
@@ -558,46 +557,42 @@
free(mods[i]);
free(mods);
free(mod);
- /* It's possible to get here without allocating list */
- return *list ? cnt + mcnt : 0;
+ if (ret < 0)
+ ccli_list_free(ccli, list, cnt);
+ return ret;
}
-static int type_completion(char ***list, char *match, int len)
+static int type_completion(struct ccli *ccli, char ***list, char *match, int len)
{
static char *types[] = {"string" , "ustring", "x8", "x16", "x32", "x64",
"u8", "u16", "u32", "u64", "s8", "s16", "s32", "s64" };
- char **words;
- int i, x;
+ int cnt = 0;
+ int ret = 0;
+ int i;
- x = ARRAY_SIZE(types);
- words = calloc(x, sizeof(char *));
- if (!words)
- return 0;
- for (i = 0; i < x; i++) {
- asprintf(&words[i], "%.*s.%s",
- len, match, types[i]);
+ for (i = 0; ret >= 0 && i < ARRAY_SIZE(types); i++) {
+ ret = ccli_list_add_printf(ccli, list, &cnt, "%.*s.%s",
+ len, match, types[i]);
}
- *list = words;
- match[strlen(match)] = CCLI_NOSPACE;
- return x;
+ if (ret > 0)
+ match[strlen(match)] = CCLI_NOSPACE;
+ return ret;
}
-static int offset_completion(char m, char ***list, char *match, int len)
+static int offset_completion(struct ccli *ccli, char m, char ***list, char *match, int len)
{
- char **words;
+ int cnt = 0;
+ int ret;
if (!m) {
- words = calloc(1, sizeof(char *));
- if (!words)
- return 0;
- asprintf(&words[0], "%.*s->",
- len, match);
- *list = words;
+ ret = ccli_list_add_printf(ccli, list, &cnt, "%.*s->",
+ len, match);
match[strlen(match)] = CCLI_NOSPACE;
- return 1;
+ return ret;
}
return 0;
}
+
static int kprobe_completion(struct ccli *ccli, void *data,
int argc, char **argv,
char ***list, int word, char *match)
@@ -627,7 +622,7 @@
ccli_line_refresh(ccli);
return 0;
}
- ret = load_available_filter(list, match);
+ ret = load_available_filter(ccli, list, match);
match[strlen(match)] = CCLI_NOSPACE;
return ret;
default:
@@ -648,9 +643,9 @@
switch (*m) {
case '.':
- return type_completion(list, match, len);
+ return type_completion(ccli, list, match, len);
case '-':
- return offset_completion(m[1], list, match, len);
+ return offset_completion(ccli, m[1], list, match, len);
}
}
return 0;
@@ -661,10 +656,11 @@
{
char **systems;
char **events;
- char **words;
char *system;
char *event;
char *p;
+ int cnt = 0;
+ int ret = 0;
int i;
p = strchr(match, '/');
@@ -678,16 +674,17 @@
free(system);
return 0;
}
- words = calloc(tracefs_list_size(events), sizeof(char *));
i = 0;
- if (words) {
- for (; events[i]; i++) {
- asprintf(&event, "%s/%s", system, events[i]);
- if (append && event && !strcmp(event, match)) {
- asprintf(words + i, "%s.", event);
- free(event);
- } else
- words[i] = event;
+ for (; ret >= 0 && events[i]; i++) {
+ ret = asprintf(&event, "%s/%s", system, events[i]);
+ if (ret < 0)
+ break;
+ if (append && event && !strcmp(event, match)) {
+ ret = ccli_list_add_printf(ccli, list, &cnt,
+ "%s.", event);
+ free(event);
+ } else {
+ ret = ccli_list_insert(ccli, list, &cnt, event);
}
}
tracefs_list_free(events);
@@ -695,18 +692,14 @@
systems = tracefs_event_systems(NULL);
if (!systems)
return 0;
- words = calloc(tracefs_list_size(systems), sizeof(char *));
- i = 0;
- if (words) {
- for (; systems[i]; i++)
- words[i] = strdup(systems[i]);
- }
+ for (i = 0; ret >= 0 && systems[i]; i++)
+ ret = ccli_list_add(ccli, list, &cnt, systems[i]);
+
tracefs_list_free(systems);
/* Use '/' as a delim */
match[strlen(match)] = '/';
}
- *list = words;
- return i;
+ return ret;
}
static struct tep_event *find_event(struct tep_handle *tep, char *ename)
@@ -728,42 +721,30 @@
return event;
}
-static int field_completion(struct tep_event *event, char ***list, char *prefix)
+static int field_completion(struct ccli *ccli,
+ struct tep_event *event, char ***list, char *prefix,
+ int *cnt)
{
struct tep_format_field **common_fields;
struct tep_format_field **fields;
- char **words;
- char **tmp;
- int i, x;
+ int ret;
+ int i;
common_fields = tep_event_common_fields(event);
fields = tep_event_fields(event);
- words = NULL;
- x = 0;
for (i = 0; common_fields && common_fields[i]; i++) {
- tmp = realloc(words, sizeof(char *) * (x + 2));
- if (!tmp) {
- ccli_argv_free(words);
- return 0;
- }
- words = tmp;
- asprintf(&words[x++], "%s%s", prefix, common_fields[i]->name);
- words[x] = NULL;
+ ret = ccli_list_add_printf(ccli, list, cnt,
+ "%s%s", prefix, common_fields[i]->name);
}
for (i = 0; fields && fields[i]; i++) {
- tmp = realloc(words, sizeof(char *) * (x + 2));
- if (!tmp) {
- ccli_argv_free(words);
- return 0;
- }
- words = tmp;
- asprintf(&words[x++], "%s%s", prefix, fields[i]->name);
- words[x] = NULL;
+ ret = ccli_list_add_printf(ccli, list, cnt,
+ "%s%s", prefix, fields[i]->name);
}
free(common_fields);
free(fields);
- *list = words;
- return x;
+ if (ret < 0)
+ ccli_list_free(ccli, list, *cnt);
+ return ret;
}
static int eprobe_completion(struct ccli *ccli, void *data,
@@ -774,6 +755,7 @@
struct tep_event *event;
char *prefix;
char *p, *m;
+ int cnt = 0;
int len;
int ret;
@@ -810,15 +792,15 @@
asprintf(&prefix, "%.*s=", len, match);
if (!prefix)
return 0;
- ret = field_completion(event, list, prefix);
+ ret = field_completion(ccli, event, list, prefix, &cnt);
free(prefix);
if (ret > 0)
match[strlen(match)] = CCLI_NOSPACE;
return ret;
case '.':
- return type_completion(list, match, len);
+ return type_completion(ccli, list, match, len);
case '-':
- return offset_completion(m[1], list, match, len);
+ return offset_completion(ccli, m[1], list, match, len);
}
}
printf("\neprobe word=%d match=%s\n", word, match);
@@ -829,6 +811,7 @@
char *ename, char *match)
{
struct tep_event *event;
+ int cnt = 0;
char *p;
/* Find the end of the event */
@@ -850,14 +833,14 @@
p++;
*p = '\0';
- return field_completion(event, list, ename);
+ return field_completion(ccli, event, list, ename, &cnt);
}
static int append_field_ts(struct ccli *ccli, struct tep_handle *tep, char ***list,
char *ename)
{
struct tep_event *event;
- char **words;
+ int cnt = 0;
char *e;
char *p;
int ret;
@@ -885,15 +868,13 @@
*p = '.';
p[1] = '\0';
- ret = field_completion(event, list, ename);
+ ret = field_completion(ccli, event, list, ename, &cnt);
if (ret > 0) {
- words = realloc(*list, sizeof(*words) * (ret + 1));
- if (words) {
- asprintf(words + ret, "%sTIMESTAMP", ename);
- *list = words;
- ret++;
- }
+ ret = ccli_list_add_printf(ccli, list, &cnt,
+ "%sTIMESTAMP", ename);
+ if (ret < 0)
+ ccli_list_free(ccli, list, cnt);
}
return ret;
}
@@ -904,8 +885,8 @@
{
struct tep_handle *tep = data;
struct tep_event *event1, *event2;
- char **words;
char *p;
+ int cnt = 0;
int len;
int ret;
@@ -967,17 +948,13 @@
return 0;
}
- words = calloc(2, sizeof(*words));
- if (!words)
- return 0;
- asprintf(words, "%s=%s/%s", argv[word],
- event1->system, event1->name);
- asprintf(words + 1, "%s=%s/%s", argv[word],
- event2->system, event2->name);
- *list = words;
+ ccli_list_add_printf(ccli, list, &cnt, "%s=%s/%s", argv[word],
+ event1->system, event1->name);
+ ret = ccli_list_add_printf(ccli, list, &cnt, "%s=%s/%s",
+ argv[word], event2->system, event2->name);
match[strlen(match)] = '.';
- return 2;
+ return ret;
}
printf("\neprobe word=%d match=%s\n", word, match);
return 0;
@@ -988,20 +965,16 @@
char *match, char ***list, void *data)
{
char *types[] = { "kprobe", "eprobe", "synthetic" };
- char **words;
char **argv;
int argc;
+ int cnt = 0;
int ret = 0;
int i;
if (word == 1) {
- words = calloc(ARRAY_SIZE(types), sizeof(char *));
- if (!words)
- return 0;
- for (i = 0; i < ARRAY_SIZE(types); i++)
- words[i] = strdup(types[i]);
- *list = words;
- return i;
+ for (i = 0; ret >= 0 && i < ARRAY_SIZE(types); i++)
+ ret = ccli_list_add(ccli, list, &cnt, types[i]);
+ return ret;
}
argc = ccli_line_parse(line, &argv);