diff options
Diffstat (limited to 'tools/perf/util')
26 files changed, 11 insertions, 2331 deletions
diff --git a/tools/perf/util/Build b/tools/perf/util/Build index 196beefa16a9..94b1099f2c22 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build @@ -9,13 +9,10 @@ libperf-y += env.o libperf-y += event.o libperf-y += evlist.o libperf-y += evsel.o -libperf-y += exec_cmd.o libperf-y += find_next_bit.o -libperf-y += help.o libperf-y += kallsyms.o libperf-y += levenshtein.o libperf-y += llvm-utils.o -libperf-y += parse-options.o libperf-y += parse-events.o libperf-y += perf_regs.o libperf-y += path.o @@ -23,7 +20,6 @@ libperf-y += rbtree.o libperf-y += libstring.o libperf-y += bitmap.o libperf-y += hweight.o -libperf-y += run-command.o libperf-y += quote.o libperf-y += strbuf.o libperf-y += string.o @@ -32,11 +28,9 @@ libperf-y += strfilter.o libperf-y += top.o libperf-y += usage.o libperf-y += wrapper.o -libperf-y += sigchain.o libperf-y += dso.o libperf-y += symbol.o libperf-y += color.o -libperf-y += pager.o libperf-y += header.o libperf-y += callchain.o libperf-y += values.o @@ -88,7 +82,6 @@ libperf-y += parse-branch-options.o libperf-y += parse-regs-options.o libperf-y += term.o libperf-y += help-unknown-cmd.o -libperf-y += subcmd-config.o libperf-$(CONFIG_LIBBPF) += bpf-loader.o libperf-$(CONFIG_BPF_PROLOGUE) += bpf-prologue.o diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c index 7f10430af39c..360fda01f3b0 100644 --- a/tools/perf/util/auxtrace.c +++ b/tools/perf/util/auxtrace.c @@ -45,7 +45,7 @@ #include "event.h" #include "session.h" #include "debug.h" -#include "parse-options.h" +#include <subcmd/parse-options.h> #include "intel-pt.h" #include "intel-bts.h" diff --git a/tools/perf/util/cache.h b/tools/perf/util/cache.h index fc6a745d2ec6..07b5d63947b1 100644 --- a/tools/perf/util/cache.h +++ b/tools/perf/util/cache.h @@ -4,7 +4,7 @@ #include <stdbool.h> #include "util.h" #include "strbuf.h" -#include "pager.h" +#include <subcmd/pager.h> #include "../perf.h" #include "../ui/ui.h" diff --git a/tools/perf/util/cgroup.c b/tools/perf/util/cgroup.c index 32e12ecfe9c5..90aa1b46b2e5 100644 --- a/tools/perf/util/cgroup.c +++ b/tools/perf/util/cgroup.c @@ -1,6 +1,6 @@ #include "util.h" #include "../perf.h" -#include "parse-options.h" +#include <subcmd/parse-options.h> #include "evsel.h" #include "cgroup.h" #include "evlist.h" diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c index 2e452ac1353d..d3e12e30e1d5 100644 --- a/tools/perf/util/config.c +++ b/tools/perf/util/config.c @@ -10,7 +10,7 @@ */ #include "util.h" #include "cache.h" -#include "exec_cmd.h" +#include <subcmd/exec-cmd.h> #include "util/hist.h" /* perf_hist_config */ #include "util/llvm-utils.h" /* perf_llvm_config */ diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index d1b6c206bb93..8c44aadb9810 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -18,7 +18,7 @@ #include <unistd.h> #include "parse-events.h" -#include "parse-options.h" +#include <subcmd/parse-options.h> #include <sys/mman.h> diff --git a/tools/perf/util/exec_cmd.c b/tools/perf/util/exec_cmd.c deleted file mode 100644 index e7f9ed7943e3..000000000000 --- a/tools/perf/util/exec_cmd.c +++ /dev/null @@ -1,209 +0,0 @@ -#include <linux/compiler.h> -#include <linux/string.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <unistd.h> -#include <string.h> -#include <stdlib.h> -#include <stdio.h> -#include "subcmd-util.h" -#include "exec_cmd.h" -#include "subcmd-config.h" - -#define MAX_ARGS 32 -#define PATH_MAX 4096 - -static const char *argv_exec_path; -static const char *argv0_path; - -void exec_cmd_init(const char *exec_name, const char *prefix, - const char *exec_path, const char *exec_path_env) -{ - subcmd_config.exec_name = exec_name; - subcmd_config.prefix = prefix; - subcmd_config.exec_path = exec_path; - subcmd_config.exec_path_env = exec_path_env; -} - -#define is_dir_sep(c) ((c) == '/') - -static int is_absolute_path(const char *path) -{ - return path[0] == '/'; -} - -static const char *get_pwd_cwd(void) -{ - static char cwd[PATH_MAX + 1]; - char *pwd; - struct stat cwd_stat, pwd_stat; - if (getcwd(cwd, PATH_MAX) == NULL) - return NULL; - pwd = getenv("PWD"); - if (pwd && strcmp(pwd, cwd)) { - stat(cwd, &cwd_stat); - if (!stat(pwd, &pwd_stat) && - pwd_stat.st_dev == cwd_stat.st_dev && - pwd_stat.st_ino == cwd_stat.st_ino) { - strlcpy(cwd, pwd, PATH_MAX); - } - } - return cwd; -} - -static const char *make_nonrelative_path(const char *path) -{ - static char buf[PATH_MAX + 1]; - - if (is_absolute_path(path)) { - if (strlcpy(buf, path, PATH_MAX) >= PATH_MAX) - die("Too long path: %.*s", 60, path); - } else { - const char *cwd = get_pwd_cwd(); - if (!cwd) - die("Cannot determine the current working directory"); - if (snprintf(buf, PATH_MAX, "%s/%s", cwd, path) >= PATH_MAX) - die("Too long path: %.*s", 60, path); - } - return buf; -} - -char *system_path(const char *path) -{ - char *buf = NULL; - - if (is_absolute_path(path)) - return strdup(path); - - astrcatf(&buf, "%s/%s", subcmd_config.prefix, path); - - return buf; -} - -const char *extract_argv0_path(const char *argv0) -{ - const char *slash; - - if (!argv0 || !*argv0) - return NULL; - slash = argv0 + strlen(argv0); - - while (argv0 <= slash && !is_dir_sep(*slash)) - slash--; - - if (slash >= argv0) { - argv0_path = strndup(argv0, slash - argv0); - return argv0_path ? slash + 1 : NULL; - } - - return argv0; -} - -void set_argv_exec_path(const char *exec_path) -{ - argv_exec_path = exec_path; - /* - * Propagate this setting to external programs. - */ - setenv(subcmd_config.exec_path_env, exec_path, 1); -} - - -/* Returns the highest-priority location to look for subprograms. */ -char *get_argv_exec_path(void) -{ - char *env; - - if (argv_exec_path) - return strdup(argv_exec_path); - - env = getenv(subcmd_config.exec_path_env); - if (env && *env) - return strdup(env); - - return system_path(subcmd_config.exec_path); -} - -static void add_path(char **out, const char *path) -{ - if (path && *path) { - if (is_absolute_path(path)) - astrcat(out, path); - else - astrcat(out, make_nonrelative_path(path)); - - astrcat(out, ":"); - } -} - -void setup_path(void) -{ - const char *old_path = getenv("PATH"); - char *new_path = NULL; - char *tmp = get_argv_exec_path(); - - add_path(&new_path, tmp); - add_path(&new_path, argv0_path); - free(tmp); - - if (old_path) - astrcat(&new_path, old_path); - else - astrcat(&new_path, "/usr/local/bin:/usr/bin:/bin"); - - setenv("PATH", new_path, 1); - - free(new_path); -} - -static const char **prepare_exec_cmd(const char **argv) -{ - int argc; - const char **nargv; - - for (argc = 0; argv[argc]; argc++) - ; /* just counting */ - nargv = malloc(sizeof(*nargv) * (argc + 2)); - - nargv[0] = subcmd_config.exec_name; - for (argc = 0; argv[argc]; argc++) - nargv[argc + 1] = argv[argc]; - nargv[argc + 1] = NULL; - return nargv; -} - -int execv_cmd(const char **argv) { - const char **nargv = prepare_exec_cmd(argv); - - /* execvp() can only ever return if it fails */ - execvp(subcmd_config.exec_name, (char **)nargv); - - free(nargv); - return -1; -} - - -int execl_cmd(const char *cmd,...) -{ - int argc; - const char *argv[MAX_ARGS + 1]; - const char *arg; - va_list param; - - va_start(param, cmd); - argv[0] = cmd; - argc = 1; - while (argc < MAX_ARGS) { - arg = argv[argc++] = va_arg(param, char *); - if (!arg) - break; - } - va_end(param); - if (MAX_ARGS <= argc) { - fprintf(stderr, " Error: too many args to run %s\n", cmd); - return -1; - } - - argv[argc] = NULL; - return execv_cmd(argv); -} diff --git a/tools/perf/util/exec_cmd.h b/tools/perf/util/exec_cmd.h deleted file mode 100644 index f1bd3436ad5f..000000000000 --- a/tools/perf/util/exec_cmd.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef __PERF_EXEC_CMD_H -#define __PERF_EXEC_CMD_H - -extern void exec_cmd_init(const char *exec_name, const char *prefix, - const char *exec_path, const char *exec_path_env); - -extern void set_argv_exec_path(const char *exec_path); -extern const char *extract_argv0_path(const char *path); -extern void setup_path(void); -extern int execv_cmd(const char **argv); /* NULL terminated */ -extern int execl_cmd(const char *cmd, ...); -/* get_argv_exec_path and system_path return malloc'd string, caller must free it */ -extern char *get_argv_exec_path(void); -extern char *system_path(const char *path); - -#endif /* __PERF_EXEC_CMD_H */ diff --git a/tools/perf/util/help-unknown-cmd.c b/tools/perf/util/help-unknown-cmd.c index a0820f16f511..dc1e41c9b054 100644 --- a/tools/perf/util/help-unknown-cmd.c +++ b/tools/perf/util/help-unknown-cmd.c @@ -1,5 +1,5 @@ #include "cache.h" -#include "help.h" +#include <subcmd/help.h> #include "../builtin.h" #include "levenshtein.h" diff --git a/tools/perf/util/help.c b/tools/perf/util/help.c deleted file mode 100644 index 8169480066c6..000000000000 --- a/tools/perf/util/help.c +++ /dev/null @@ -1,268 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <termios.h> -#include <sys/ioctl.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <unistd.h> -#include <dirent.h> -#include "subcmd-util.h" -#include "help.h" -#include "exec_cmd.h" - -void add_cmdname(struct cmdnames *cmds, const char *name, size_t len) -{ - struct cmdname *ent = malloc(sizeof(*ent) + len + 1); - - ent->len = len; - memcpy(ent->name, name, len); - ent->name[len] = 0; - - ALLOC_GROW(cmds->names, cmds->cnt + 1, cmds->alloc); - cmds->names[cmds->cnt++] = ent; -} - -void clean_cmdnames(struct cmdnames *cmds) -{ - unsigned int i; - - for (i = 0; i < cmds->cnt; ++i) - zfree(&cmds->names[i]); - zfree(&cmds->names); - cmds->cnt = 0; - cmds->alloc = 0; -} - -int cmdname_compare(const void *a_, const void *b_) -{ - struct cmdname *a = *(struct cmdname **)a_; - struct cmdname *b = *(struct cmdname **)b_; - return strcmp(a->name, b->name); -} - -void uniq(struct cmdnames *cmds) -{ - unsigned int i, j; - - if (!cmds->cnt) - return; - - for (i = j = 1; i < cmds->cnt; i++) - if (strcmp(cmds->names[i]->name, cmds->names[i-1]->name)) - cmds->names[j++] = cmds->names[i]; - - cmds->cnt = j; -} - -void exclude_cmds(struct cmdnames *cmds, struct cmdnames *excludes) -{ - size_t ci, cj, ei; - int cmp; - - ci = cj = ei = 0; - while (ci < cmds->cnt && ei < excludes->cnt) { - cmp = strcmp(cmds->names[ci]->name, excludes->names[ei]->name); - if (cmp < 0) - cmds->names[cj++] = cmds->names[ci++]; - else if (cmp == 0) - ci++, ei++; - else if (cmp > 0) - ei++; - } - - while (ci < cmds->cnt) - cmds->names[cj++] = cmds->names[ci++]; - - cmds->cnt = cj; -} - -static void get_term_dimensions(struct winsize *ws) -{ - char *s = getenv("LINES"); - - if (s != NULL) { - ws->ws_row = atoi(s); - s = getenv("COLUMNS"); - if (s != NULL) { - ws->ws_col = atoi(s); - if (ws->ws_row && ws->ws_col) - return; - } - } -#ifdef TIOCGWINSZ - if (ioctl(1, TIOCGWINSZ, ws) == 0 && - ws->ws_row && ws->ws_col) - return; -#endif - ws->ws_row = 25; - ws->ws_col = 80; -} - -static void pretty_print_string_list(struct cmdnames *cmds, int longest) -{ - int cols = 1, rows; - int space = longest + 1; /* min 1 SP between words */ - struct winsize win; - int max_cols; - int i, j; - - get_term_dimensions(&win); - max_cols = win.ws_col - 1; /* don't print *on* the edge */ - - if (space < max_cols) - cols = max_cols / space; - rows = (cmds->cnt + cols - 1) / cols; - - for (i = 0; i < rows; i++) { - printf(" "); - - for (j = 0; j < cols; j++) { - unsigned int n = j * rows + i; - unsigned int size = space; - - if (n >= cmds->cnt) - break; - if (j == cols-1 || n + rows >= cmds->cnt) - size = 1; - printf("%-*s", size, cmds->names[n]->name); - } - putchar('\n'); - } -} - -static int is_executable(const char *name) -{ - struct stat st; - - if (stat(name, &st) || /* stat, not lstat */ - !S_ISREG(st.st_mode)) - return 0; - - return st.st_mode & S_IXUSR; -} - -static int has_extension(const char *filename, const char *ext) -{ - size_t len = strlen(filename); - size_t extlen = strlen(ext); - - return len > extlen && !memcmp(filename + len - extlen, ext, extlen); -} - -static void list_commands_in_dir(struct cmdnames *cmds, - const char *path, - const char *prefix) -{ - int prefix_len; - DIR *dir = opendir(path); - struct dirent *de; - char *buf = NULL; - - if (!dir) - return; - if (!prefix) - prefix = "perf-"; - prefix_len = strlen(prefix); - - astrcatf(&buf, "%s/", path); - - while ((de = readdir(dir)) != NULL) { - int entlen; - - if (prefixcmp(de->d_name, prefix)) - continue; - - astrcat(&buf, de->d_name); - if (!is_executable(buf)) - continue; - - entlen = strlen(de->d_name) - prefix_len; - if (has_extension(de->d_name, ".exe")) - entlen -= 4; - - add_cmdname(cmds, de->d_name + prefix_len, entlen); - } - closedir(dir); - free(buf); -} - -void load_command_list(const char *prefix, - struct cmdnames *main_cmds, - struct cmdnames *other_cmds) -{ - const char *env_path = getenv("PATH"); - char *exec_path = get_argv_exec_path(); - - if (exec_path) { - list_commands_in_dir(main_cmds, exec_path, prefix); - qsort(main_cmds->names, main_cmds->cnt, - sizeof(*main_cmds->names), cmdname_compare); - uniq(main_cmds); - } - - if (env_path) { - char *paths, *path, *colon; - path = paths = strdup(env_path); - while (1) { - if ((colon = strchr(path, ':'))) - *colon = 0; - if (!exec_path || strcmp(path, exec_path)) - list_commands_in_dir(other_cmds, path, prefix); - - if (!colon) - break; - path = colon + 1; - } - free(paths); - - qsort(other_cmds->names, other_cmds->cnt, - sizeof(*other_cmds->names), cmdname_compare); - uniq(other_cmds); - } - free(exec_path); - exclude_cmds(other_cmds, main_cmds); -} - -void list_commands(const char *title, struct cmdnames *main_cmds, - struct cmdnames *other_cmds) -{ - unsigned int i, longest = 0; - - for (i = 0; i < main_cmds->cnt; i++) - if (longest < main_cmds->names[i]->len) - longest = main_cmds->names[i]->len; - for (i = 0; i < other_cmds->cnt; i++) - if (longest < other_cmds->names[i]->len) - longest = other_cmds->names[i]->len; - - if (main_cmds->cnt) { - char *exec_path = get_argv_exec_path(); - printf("available %s in '%s'\n", title, exec_path); - printf("----------------"); - mput_char('-', strlen(title) + strlen(exec_path)); - putchar('\n'); - pretty_print_string_list(main_cmds, longest); - putchar('\n'); - free(exec_path); - } - - if (other_cmds->cnt) { - printf("%s available from elsewhere on your $PATH\n", title); - printf("---------------------------------------"); - mput_char('-', strlen(title)); - putchar('\n'); - pretty_print_string_list(other_cmds, longest); - putchar('\n'); - } -} - -int is_in_cmdlist(struct cmdnames *c, const char *s) -{ - unsigned int i; - - for (i = 0; i < c->cnt; i++) - if (!strcmp(s, c->names[i]->name)) - return 1; - return 0; -} diff --git a/tools/perf/util/help.h b/tools/perf/util/help.h deleted file mode 100644 index 096c8bc45cd7..000000000000 --- a/tools/perf/util/help.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef __PERF_HELP_H -#define __PERF_HELP_H - -#include <sys/types.h> - -struct cmdnames { - size_t alloc; - size_t cnt; - struct cmdname { - size_t len; /* also used for similarity index in help.c */ - char name[]; - } **names; -}; - -static inline void mput_char(char c, unsigned int num) -{ - while(num--) - putchar(c); -} - -void load_command_list(const char *prefix, - struct cmdnames *main_cmds, - struct cmdnames *other_cmds); -void add_cmdname(struct cmdnames *cmds, const char *name, size_t len); -void clean_cmdnames(struct cmdnames *cmds); -int cmdname_compare(const void *a, const void *b); -void uniq(struct cmdnames *cmds); -/* Here we require that excludes is a sorted list. */ -void exclude_cmds(struct cmdnames *cmds, struct cmdnames *excludes); -int is_in_cmdlist(struct cmdnames *c, const char *s); -void list_commands(const char *title, struct cmdnames *main_cmds, - struct cmdnames *other_cmds); - -#endif /* __PERF_HELP_H */ diff --git a/tools/perf/util/pager.c b/tools/perf/util/pager.c deleted file mode 100644 index d50f3b58606b..000000000000 --- a/tools/perf/util/pager.c +++ /dev/null @@ -1,100 +0,0 @@ -#include <sys/select.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <signal.h> -#include "pager.h" -#include "run-command.h" -#include "sigchain.h" -#include "subcmd-config.h" - -/* - * This is split up from the rest of git so that we can do - * something different on Windows. - */ - -static int spawned_pager; - -void pager_init(const char *pager_env) -{ - subcmd_config.pager_env = pager_env; -} - -static void pager_preexec(void) -{ - /* - * Work around bug in "less" by not starting it until we - * have real input - */ - fd_set in; - - FD_ZERO(&in); - FD_SET(0, &in); - select(1, &in, NULL, &in, NULL); - - setenv("LESS", "FRSX", 0); -} - -static const char *pager_argv[] = { "sh", "-c", NULL, NULL }; -static struct child_process pager_process; - -static void wait_for_pager(void) -{ - fflush(stdout); - fflush(stderr); - /* signal EOF to pager */ - close(1); - close(2); - finish_command(&pager_process); -} - -static void wait_for_pager_signal(int signo) -{ - wait_for_pager(); - sigchain_pop(signo); - raise(signo); -} - -void setup_pager(void) -{ - const char *pager = getenv(subcmd_config.pager_env); - - if (!isatty(1)) - return; - if (!pager) - pager = getenv("PAGER"); - if (!(pager || access("/usr/bin/pager", X_OK))) - pager = "/usr/bin/pager"; - if (!(pager || access("/usr/bin/less", X_OK))) - pager = "/usr/bin/less"; - if (!pager) - pager = "cat"; - if (!*pager || !strcmp(pager, "cat")) - return; - - spawned_pager = 1; /* means we are emitting to terminal */ - - /* spawn the pager */ - pager_argv[2] = pager; - pager_process.argv = pager_argv; - pager_process.in = -1; - pager_process.preexec_cb = pager_preexec; - - if (start_command(&pager_process)) - return; - - /* original process continues, but writes to the pipe */ - dup2(pager_process.in, 1); - if (isatty(2)) - dup2(pager_process.in, 2); - close(pager_process.in); - - /* this makes sure that the parent terminates after the pager */ - sigchain_push_common(wait_for_pager_signal); - atexit(wait_for_pager); -} - -int pager_in_use(void) -{ - return spawned_pager; -} diff --git a/tools/perf/util/pager.h b/tools/perf/util/pager.h deleted file mode 100644 index d6a591a4c017..000000000000 --- a/tools/perf/util/pager.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef __PERF_PAGER_H -#define __PERF_PAGER_H - -extern void pager_init(const char *pager_env); - -extern void setup_pager(void); -extern int pager_in_use(void); - -#endif /* __PERF_PAGER_H */ diff --git a/tools/perf/util/parse-branch-options.c b/tools/perf/util/parse-branch-options.c index 355eecf6bf59..afc088dd7d20 100644 --- a/tools/perf/util/parse-branch-options.c +++ b/tools/perf/util/parse-branch-options.c @@ -1,7 +1,7 @@ #include "perf.h" #include "util/util.h" #include "util/debug.h" -#include "util/parse-options.h" +#include <subcmd/parse-options.h> #include "util/parse-branch-options.h" #define BRANCH_OPT(n, m) \ diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 6fc8cd753e1a..4f7b0efdde2f 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -4,9 +4,9 @@ #include "../perf.h" #include "evlist.h" #include "evsel.h" -#include "parse-options.h" +#include <subcmd/parse-options.h> #include "parse-events.h" -#include "exec_cmd.h" +#include <subcmd/exec-cmd.h> #include "string.h" #include "symbol.h" #include "cache.h" diff --git a/tools/perf/util/parse-options.c b/tools/perf/util/parse-options.c deleted file mode 100644 index 981bb4481fd5..000000000000 --- a/tools/perf/util/parse-options.c +++ /dev/null @@ -1,983 +0,0 @@ -#include <linux/compiler.h> -#include <linux/types.h> -#include <stdio.h> -#include <stdlib.h> -#include <stdint.h> -#include <string.h> -#include <ctype.h> -#include "subcmd-util.h" -#include "parse-options.h" -#include "subcmd-config.h" -#include "pager.h" - -#define OPT_SHORT 1 -#define OPT_UNSET 2 - -char *error_buf; - -static int opterror(const struct option *opt, const char *reason, int flags) -{ - if (flags & OPT_SHORT) - fprintf(stderr, " Error: switch `%c' %s", opt->short_name, reason); - else if (flags & OPT_UNSET) - fprintf(stderr, " Error: option `no-%s' %s", opt->long_name, reason); - else - fprintf(stderr, " Error: option `%s' %s", opt->long_name, reason); - - return -1; -} - -static const char *skip_prefix(const char *str, const char *prefix) -{ - size_t len = strlen(prefix); - return strncmp(str, prefix, len) ? NULL : str + len; -} - -static void optwarning(const struct option *opt, const char *reason, int flags) -{ - if (flags & OPT_SHORT) - fprintf(stderr, " Warning: switch `%c' %s", opt->short_name, reason); - else if (flags & OPT_UNSET) - fprintf(stderr, " Warning: option `no-%s' %s", opt->long_name, reason); - else - fprintf(stderr, " Warning: option `%s' %s", opt->long_name, reason); -} - -static int get_arg(struct parse_opt_ctx_t *p, const struct option *opt, - int flags, const char **arg) -{ - const char *res; - - if (p->opt) { - res = p->opt; - p->opt = NULL; - } else if ((opt->flags & PARSE_OPT_LASTARG_DEFAULT) && (p->argc == 1 || - **(p->argv + 1) == '-')) { - res = (const char *)opt->defval; - } else if (p->argc > 1) { - p->argc--; - res = *++p->argv; - } else - return opterror(opt, "requires a value", flags); - if (arg) - *arg = res; - return 0; -} - -static int get_value(struct parse_opt_ctx_t *p, - const struct option *opt, int flags) -{ - const char *s, *arg = NULL; - const int unset = flags & OPT_UNSET; - int err; - - if (unset && p->opt) - return opterror(opt, "takes no value", flags); - if (unset && (opt->flags & PARSE_OPT_NONEG)) - return opterror(opt, "isn't available", flags); - if (opt->flags & PARSE_OPT_DISABLED) - return opterror(opt, "is not usable", flags); - - if (opt->flags & PARSE_OPT_EXCLUSIVE) { - if (p->excl_opt && p->excl_opt != opt) { - char msg[128]; - - if (((flags & OPT_SHORT) && p->excl_opt->short_name) || - p->excl_opt->long_name == NULL) { - snprintf(msg, sizeof(msg), "cannot be used with switch `%c'", - p->excl_opt->short_name); - } else { - snprintf(msg, sizeof(msg), "cannot be used with %s", - p->excl_opt->long_name); - } - opterror(opt, msg, flags); - return -3; - } - p->excl_opt = opt; - } - if (!(flags & OPT_SHORT) && p->opt) { - switch (opt->type) { - case OPTION_CALLBACK: - if (!(opt->flags & PARSE_OPT_NOARG)) - break; - /* FALLTHROUGH */ - case OPTION_BOOLEAN: - case OPTION_INCR: - case OPTION_BIT: - case OPTION_SET_UINT: - case OPTION_SET_PTR: - return opterror(opt, "takes no value", flags); - case OPTION_END: - case OPTION_ARGUMENT: - case OPTION_GROUP: - case OPTION_STRING: - case OPTION_INTEGER: - case OPTION_UINTEGER: - case OPTION_LONG: - case OPTION_U64: - default: - break; - } - } - - if (opt->flags & PARSE_OPT_NOBUILD) { - char reason[128]; - bool noarg = false; - - err = snprintf(reason, sizeof(reason), - opt->flags & PARSE_OPT_CANSKIP ? - "is being ignored because %s " : - "is not available because %s", - opt->build_opt); - reason[sizeof(reason) - 1] = '\0'; - - if (err < 0) - strncpy(reason, opt->flags & PARSE_OPT_CANSKIP ? - "is being ignored" : - "is not available", - sizeof(reason)); - - if (!(opt->flags & PARSE_OPT_CANSKIP)) - return opterror(opt, reason, flags); - - err = 0; - if (unset) - noarg = true; - if (opt->flags & PARSE_OPT_NOARG) - noarg = true; - if (opt->flags & PARSE_OPT_OPTARG && !p->opt) - noarg = true; - - switch (opt->type) { - case OPTION_BOOLEAN: - case OPTION_INCR: - case OPTION_BIT: - case OPTION_SET_UINT: - case OPTION_SET_PTR: - case OPTION_END: - case OPTION_ARGUMENT: - case OPTION_GROUP: - noarg = true; - break; - case OPTION_CALLBACK: - case OPTION_STRING: - case OPTION_INTEGER: - case OPTION_UINTEGER: - case OPTION_LONG: - case OPTION_U64: - default: - break; - } - - if (!noarg) - err = get_arg(p, opt, flags, NULL); - if (err) - return err; - - optwarning(opt, reason, flags); - return 0; - } - - switch (opt->type) { - case OPTION_BIT: - if (unset) - *(int *)opt->value &= ~opt->defval; - else - *(int *)opt->value |= opt->defval; - return 0; - - case OPTION_BOOLEAN: - *(bool *)opt->value = unset ? false : true; - if (opt->set) - *(bool *)opt->set = true; - return 0; - - case OPTION_INCR: - *(int *)opt->value = unset ? 0 : *(int *)opt->value + 1; - return 0; - - case OPTION_SET_UINT: - *(unsigned int *)opt->value = unset ? 0 : opt->defval; - return 0; - - case OPTION_SET_PTR: - *(void **)opt->value = unset ? NULL : (void *)opt->defval; - return 0; - - case OPTION_STRING: - err = 0; - if (unset) - *(const char **)opt->value = NULL; - else if (opt->flags & PARSE_OPT_OPTARG && !p->opt) - *(const char **)opt->value = (const char *)opt->defval; - else - err = get_arg(p, opt, flags, (const char **)opt->value); - - /* PARSE_OPT_NOEMPTY: Allow NULL but disallow empty string. */ - if (opt->flags & PARSE_OPT_NOEMPTY) { - const char *val = *(const char **)opt->value; - - if (!val) - return err; - - /* Similar to unset if we are given an empty string. */ - if (val[0] == '\0') { - *(const char **)opt->value = NULL; - return 0; - } - } - - return err; - - case OPTION_CALLBACK: - if (unset) - return (*opt->callback)(opt, NULL, 1) ? (-1) : 0; - if (opt->flags & PARSE_OPT_NOARG) - return (*opt->callback)(opt, NULL, 0) ? (-1) : 0; - if (opt->flags & PARSE_OPT_OPTARG && !p->opt) - return (*opt->callback)(opt, NULL, 0) ? (-1) : 0; - if (get_arg(p, opt, flags, &arg)) - return -1; - return (*opt->callback)(opt, arg, 0) ? (-1) : 0; - - case OPTION_INTEGER: - if (unset) { - *(int *)opt->value = 0; - return 0; - } - if (opt->flags & PARSE_OPT_OPTARG && !p->opt) { - *(int *)opt->value = opt->defval; - return 0; - } - if (get_arg(p, opt, flags, &arg)) - return -1; - *(int *)opt->value = strtol(arg, (char **)&s, 10); - if (*s) - return opterror(opt, "expects a numerical value", flags); - return 0; - - case OPTION_UINTEGER: - if (unset) { - *(unsigned int *)opt->value = 0; - return 0; - } - if (opt->flags & PARSE_OPT_OPTARG && !p->opt) { - *(unsigned int *)opt->value = opt->defval; - return 0; - } - if (get_arg(p, opt, flags, &arg)) - return -1; - *(unsigned int *)opt->value = strtol(arg, (char **)&s, 10); - if (*s) - return opterror(opt, "expects a numerical value", flags); - return 0; - - case OPTION_LONG: - if (unset) { - *(long *)opt->value = 0; - return 0; - } - if (opt->flags & PARSE_OPT_OPTARG && !p->opt) { - *(long *)opt->value = opt->defval; - return 0; - } - if (get_arg(p, opt, flags, &arg)) - return -1; - *(long *)opt->value = strtol(arg, (char **)&s, 10); - if (*s) - return opterror(opt, "expects a numerical value", flags); - return 0; - - case OPTION_U64: - if (unset) { - *(u64 *)opt->value = 0; - return 0; - } - if (opt->flags & PARSE_OPT_OPTARG && !p->opt) { - *(u64 *)opt->value = opt->defval; - return 0; - } - if (get_arg(p, opt, flags, &arg)) - return -1; - *(u64 *)opt->value = strtoull(arg, (char **)&s, 10); - if (*s) - return opterror(opt, "expects a numerical value", flags); - return 0; - - case OPTION_END: - case OPTION_ARGUMENT: - case OPTION_GROUP: - default: - die("should not happen, someone must be hit on the forehead"); - } -} - -static int parse_short_opt(struct parse_opt_ctx_t *p, const struct option *options) -{ - for (; options->type != OPTION_END; options++) { - if (options->short_name == *p->opt) { - p->opt = p->opt[1] ? p->opt + 1 : NULL; - return get_value(p, options, OPT_SHORT); - } - } - return -2; -} - -static int parse_long_opt(struct parse_opt_ctx_t *p, const char *arg, - const struct option *options) -{ - const char *arg_end = strchr(arg, '='); - const struct option *abbrev_option = NULL, *ambiguous_option = NULL; - int abbrev_flags = 0, ambiguous_flags = 0; - - if (!arg_end) - arg_end = arg + strlen(arg); - - for (; options->type != OPTION_END; options++) { - const char *rest; - int flags = 0; - - if (!options->long_name) - continue; - - rest = skip_prefix(arg, options->long_name); - if (options->type == OPTION_ARGUMENT) { - if (!rest) - continue; - if (*rest == '=') - return opterror(options, "takes no value", flags); - if (*rest) - continue; - p->out[p->cpidx++] = arg - 2; - return 0; - } - if (!rest) { - if (!prefixcmp(options->long_name, "no-")) { - /* - * The long name itself starts with "no-", so - * accept the option without "no-" so that users - * do not have to enter "no-no-" to get the - * negation. - */ - rest = skip_prefix(arg, options->long_name + 3); - if (rest) { - flags |= OPT_UNSET; - goto match; - } - /* Abbreviated case */ - if (!prefixcmp(options->long_name + 3, arg)) { - flags |= OPT_UNSET; - goto is_abbreviated; - } - } - /* abbreviated? */ - if (!strncmp(options->long_name, arg, arg_end - arg)) { -is_abbreviated: - if (abbrev_option) { - /* - * If this is abbreviated, it is - * ambiguous. So when there is no - * exact match later, we need to - * error out. - */ - ambiguous_option = abbrev_option; - ambiguous_flags = abbrev_flags; - } - if (!(flags & OPT_UNSET) && *arg_end) - p->opt = arg_end + 1; - abbrev_option = options; - abbrev_flags = flags; - continue; - } - /* negated and abbreviated very much? */ - if (!prefixcmp("no-", arg)) { - flags |= OPT_UNSET; - goto is_abbreviated; - } - /* negated? */ - if (strncmp(arg, "no-", 3)) - continue; - flags |= OPT_UNSET; - rest = skip_prefix(arg + 3, options->long_name); - /* abbreviated and negated? */ - if (!rest && !prefixcmp(options->long_name, arg + 3)) - goto is_abbreviated; - if (!rest) - continue; - } -match: - if (*rest) { - if (*rest != '=') - continue; - p->opt = rest + 1; - } - return get_value(p, options, flags); - } - - if (ambiguous_option) { - fprintf(stderr, - " Error: Ambiguous option: %s (could be --%s%s or --%s%s)", - arg, - (ambiguous_flags & OPT_UNSET) ? "no-" : "", - ambiguous_option->long_name, - (abbrev_flags & OPT_UNSET) ? "no-" : "", - abbrev_option->long_name); - return -1; - } - if (abbrev_option) - return get_value(p, abbrev_option, abbrev_flags); - return -2; -} - -static void check_typos(const char *arg, const struct option *options) -{ - if (strlen(arg) < 3) - return; - - if (!prefixcmp(arg, "no-")) { - fprintf(stderr, " Error: did you mean `--%s` (with two dashes ?)", arg); - exit(129); - } - - for (; options->type != OPTION_END; options++) { - if (!options->long_name) - continue; - if (!prefixcmp(options->long_name, arg)) { - fprintf(stderr, " Error: did you mean `--%s` (with two dashes ?)", arg); - exit(129); - } - } -} - -static void parse_options_start(struct parse_opt_ctx_t *ctx, - int argc, const char **argv, int flags) -{ - memset(ctx, 0, sizeof(*ctx)); - ctx->argc = argc - 1; - ctx->argv = argv + 1; - ctx->out = argv; - ctx->cpidx = ((flags & PARSE_OPT_KEEP_ARGV0) != 0); - ctx->flags = flags; - if ((flags & PARSE_OPT_KEEP_UNKNOWN) && - (flags & PARSE_OPT_STOP_AT_NON_OPTION)) - die("STOP_AT_NON_OPTION and KEEP_UNKNOWN don't go together"); -} - -static int usage_with_options_internal(const char * const *, - const struct option *, int, - struct parse_opt_ctx_t *); - -static int parse_options_step(struct parse_opt_ctx_t *ctx, - const struct option *options, - const char * const usagestr[]) -{ - int internal_help = !(ctx->flags & PARSE_OPT_NO_INTERNAL_HELP); - int excl_short_opt = 1; - const char *arg; - - /* we must reset ->opt, unknown short option leave it dangling */ - ctx->opt = NULL; - - for (; ctx->argc; ctx->argc--, ctx->argv++) { - arg = ctx->argv[0]; - if (*arg != '-' || !arg[1]) { - if (ctx->flags & PARSE_OPT_STOP_AT_NON_OPTION) - break; - ctx->out[ctx->cpidx++] = ctx->argv[0]; - continue; - } - - if (arg[1] != '-') { - ctx->opt = ++arg; - if (internal_help && *ctx->opt == 'h') { - return usage_with_options_internal(usagestr, options, 0, ctx); - } - switch (parse_short_opt(ctx, options)) { - case -1: - return parse_options_usage(usagestr, options, arg, 1); - case -2: - goto unknown; - case -3: - goto exclusive; - default: - break; - } - if (ctx->opt) - check_typos(arg, options); - while (ctx->opt) { - if (internal_help && *ctx->opt == 'h') - return usage_with_options_internal(usagestr, options, 0, ctx); - arg = ctx->opt; - switch (parse_short_opt(ctx, options)) { - case -1: - return parse_options_usage(usagestr, options, arg, 1); - case -2: - /* fake a short option thing to hide the fact that we may have - * started to parse aggregated stuff - * - * This is leaky, too bad. - */ - ctx->argv[0] = strdup(ctx->opt - 1); - *(char *)ctx->argv[0] = '-'; - goto unknown; - case -3: - goto exclusive; - default: - break; - } - } - continue; - } - - if (!arg[2]) { /* "--" */ - if (!(ctx->flags & PARSE_OPT_KEEP_DASHDASH)) { - ctx->argc--; - ctx->argv++; - } - break; - } - - arg += 2; - if (internal_help && !strcmp(arg, "help-all")) - return usage_with_options_internal(usagestr, options, 1, ctx); - if (internal_help && !strcmp(arg, "help")) - return usage_with_options_internal(usagestr, options, 0, ctx); - if (!strcmp(arg, "list-opts")) - return PARSE_OPT_LIST_OPTS; - if (!strcmp(arg, "list-cmds")) - return PARSE_OPT_LIST_SUBCMDS; - switch (parse_long_opt(ctx, arg, options)) { - case -1: - return parse_options_usage(usagestr, options, arg, 0); - case -2: - goto unknown; - case -3: - excl_short_opt = 0; - goto exclusive; - default: - break; - } - continue; -unknown: - if (!(ctx->flags & PARSE_OPT_KEEP_UNKNOWN)) - return PARSE_OPT_UNKNOWN; - ctx->out[ctx->cpidx++] = ctx->argv[0]; - ctx->opt = NULL; - } - return PARSE_OPT_DONE; - -exclusive: - parse_options_usage(usagestr, options, arg, excl_short_opt); - if ((excl_short_opt && ctx->excl_opt->short_name) || - ctx->excl_opt->long_name == NULL) { - char opt = ctx->excl_opt->short_name; - parse_options_usage(NULL, options, &opt, 1); - } else { - parse_options_usage(NULL, options, ctx->excl_opt->long_name, 0); - } - return PARSE_OPT_HELP; -} - -static int parse_options_end(struct parse_opt_ctx_t *ctx) -{ - memmove(ctx->out + ctx->cpidx, ctx->argv, ctx->argc * sizeof(*ctx->out)); - ctx->out[ctx->cpidx + ctx->argc] = NULL; - return ctx->cpidx + ctx->argc; -} - -int parse_options_subcommand(int argc, const char **argv, const struct option *options, - const char *const subcommands[], const char *usagestr[], int flags) -{ - struct parse_opt_ctx_t ctx; - - /* build usage string if it's not provided */ - if (subcommands && !usagestr[0]) { - char *buf = NULL; - - astrcatf(&buf, "%s %s [<options>] {", subcmd_config.exec_name, argv[0]); - - for (int i = 0; subcommands[i]; i++) { - if (i) - astrcat(&buf, "|"); - astrcat(&buf, subcommands[i]); - } - astrcat(&buf, "}"); - - usagestr[0] = buf; - } - - parse_options_start(&ctx, argc, argv, flags); - switch (parse_options_step(&ctx, options, usagestr)) { - case PARSE_OPT_HELP: - exit(129); - case PARSE_OPT_DONE: - break; - case PARSE_OPT_LIST_OPTS: - while (options->type != OPTION_END) { - if (options->long_name) - printf("--%s ", options->long_name); - options++; - } - putchar('\n'); - exit(130); - case PARSE_OPT_LIST_SUBCMDS: - if (subcommands) { - for (int i = 0; subcommands[i]; i++) - printf("%s ", subcommands[i]); - } - putchar('\n'); - exit(130); - default: /* PARSE_OPT_UNKNOWN */ - if (ctx.argv[0][1] == '-') - astrcatf(&error_buf, "unknown option `%s'", - ctx.argv[0] + 2); - else - astrcatf(&error_buf, "unknown switch `%c'", *ctx.opt); - usage_with_options(usagestr, options); - } - - return parse_options_end(&ctx); -} - -int parse_options(int argc, const char **argv, const struct option *options, - const char * const usagestr[], int flags) -{ - return parse_options_subcommand(argc, argv, options, NULL, - (const char **) usagestr, flags); -} - -#define USAGE_OPTS_WIDTH 24 -#define USAGE_GAP 2 - -static void print_option_help(const struct option *opts, int full) -{ - size_t pos; - int pad; - - if (opts->type == OPTION_GROUP) { - fputc('\n', stderr); - if (*opts->help) - fprintf(stderr, "%s\n", opts->help); - return; - } - if (!full && (opts->flags & PARSE_OPT_HIDDEN)) - return; - if (opts->flags & PARSE_OPT_DISABLED) - return; - - pos = fprintf(stderr, " "); - if (opts->short_name) - pos += fprintf(stderr, "-%c", opts->short_name); - else - pos += fprintf(stderr, " "); - - if (opts->long_name && opts->short_name) - pos += fprintf(stderr, ", "); - if (opts->long_name) - pos += fprintf(stderr, "--%s", opts->long_name); - - switch (opts->type) { - case OPTION_ARGUMENT: - break; - case OPTION_LONG: - case OPTION_U64: - case OPTION_INTEGER: - case OPTION_UINTEGER: - if (opts->flags & PARSE_OPT_OPTARG) - if (opts->long_name) - pos += fprintf(stderr, "[=<n>]"); - else - pos += fprintf(stderr, "[<n>]"); - else - pos += fprintf(stderr, " <n>"); - break; - case OPTION_CALLBACK: - if (opts->flags & PARSE_OPT_NOARG) - break; - /* FALLTHROUGH */ - case OPTION_STRING: - if (opts->argh) { - if (opts->flags & PARSE_OPT_OPTARG) - if (opts->long_name) - pos += fprintf(stderr, "[=<%s>]", opts->argh); - else - pos += fprintf(stderr, "[<%s>]", opts->argh); - else - pos += fprintf(stderr, " <%s>", opts->argh); - } else { - if (opts->flags & PARSE_OPT_OPTARG) - if (opts->long_name) - pos += fprintf(stderr, "[=...]"); - else - pos += fprintf(stderr, "[...]"); - else - pos += fprintf(stderr, " ..."); - } - break; - default: /* OPTION_{BIT,BOOLEAN,SET_UINT,SET_PTR} */ - case OPTION_END: - case OPTION_GROUP: - case OPTION_BIT: - case OPTION_BOOLEAN: - case OPTION_INCR: - case OPTION_SET_UINT: - case OPTION_SET_PTR: - break; - } - - if (pos <= USAGE_OPTS_WIDTH) - pad = USAGE_OPTS_WIDTH - pos; - else { - fputc('\n', stderr); - pad = USAGE_OPTS_WIDTH; - } - fprintf(stderr, "%*s%s\n", pad + USAGE_GAP, "", opts->help); - if (opts->flags & PARSE_OPT_NOBUILD) - fprintf(stderr, "%*s(not built-in because %s)\n", - USAGE_OPTS_WIDTH + USAGE_GAP, "", - opts->build_opt); -} - -static int option__cmp(const void *va, const void *vb) -{ - const struct option *a = va, *b = vb; - int sa = tolower(a->short_name), sb = tolower(b->short_name), ret; - - if (sa == 0) - sa = 'z' + 1; - if (sb == 0) - sb = 'z' + 1; - - ret = sa - sb; - - if (ret == 0) { - const char *la = a->long_name ?: "", - *lb = b->long_name ?: ""; - ret = strcmp(la, lb); - } - - return ret; -} - -static struct option *options__order(const struct option *opts) -{ - int nr_opts = 0, len; - const struct option *o = opts; - struct option *ordered; - - for (o = opts; o->type != OPTION_END; o++) - ++nr_opts; - - len = sizeof(*o) * (nr_opts + 1); - ordered = malloc(len); - if (!ordered) - goto out; - memcpy(ordered, opts, len); - - qsort(ordered, nr_opts, sizeof(*o), option__cmp); -out: - return ordered; -} - -static bool option__in_argv(const struct option *opt, const struct parse_opt_ctx_t *ctx) -{ - int i; - - for (i = 1; i < ctx->argc; ++i) { - const char *arg = ctx->argv[i]; - - if (arg[0] != '-') { - if (arg[1] == '\0') { - if (arg[0] == opt->short_name) - return true; - continue; - } - - if (opt->long_name && strcmp(opt->long_name, arg) == 0) - return true; - - if (opt->help && strcasestr(opt->help, arg) != NULL) - return true; - - continue; - } - - if (arg[1] == opt->short_name || - (arg[1] == '-' && opt->long_name && strcmp(opt->long_name, arg + 2) == 0)) - return true; - } - - return false; -} - -static int usage_with_options_internal(const char * const *usagestr, - const struct option *opts, int full, - struct parse_opt_ctx_t *ctx) -{ - struct option *ordered; - - if (!usagestr) - return PARSE_OPT_HELP; - - setup_pager(); - - if (error_buf) { - fprintf(stderr, " Error: %s\n", error_buf); - zfree(&error_buf); - } - - fprintf(stderr, "\n Usage: %s\n", *usagestr++); - while (*usagestr && **usagestr) - fprintf(stderr, " or: %s\n", *usagestr++); - while (*usagestr) { - fprintf(stderr, "%s%s\n", - **usagestr ? " " : "", - *usagestr); - usagestr++; - } - - if (opts->type != OPTION_GROUP) - fputc('\n', stderr); - - ordered = options__order(opts); - if (ordered) - opts = ordered; - - for ( ; opts->type != OPTION_END; opts++) { - if (ctx && ctx->argc > 1 && !option__in_argv(opts, ctx)) - continue; - print_option_help(opts, full); - } - - fputc('\n', stderr); - - free(ordered); - - return PARSE_OPT_HELP; -} - -void usage_with_options(const char * const *usagestr, - const struct option *opts) -{ - usage_with_options_internal(usagestr, opts, 0, NULL); - exit(129); -} - -void usage_with_options_msg(const char * const *usagestr, - const struct option *opts, const char *fmt, ...) -{ - va_list ap; - char *tmp = error_buf; - - va_start(ap, fmt); - if (vasprintf(&error_buf, fmt, ap) == -1) - die("vasprintf failed"); - va_end(ap); - - free(tmp); - - usage_with_options_internal(usagestr, opts, 0, NULL); - exit(129); -} - -int parse_options_usage(const char * const *usagestr, - const struct option *opts, - const char *optstr, bool short_opt) -{ - if (!usagestr) - goto opt; - - fprintf(stderr, "\n Usage: %s\n", *usagestr++); - while (*usagestr && **usagestr) - fprintf(stderr, " or: %s\n", *usagestr++); - while (*usagestr) { - fprintf(stderr, "%s%s\n", - **usagestr ? " " : "", - *usagestr); - usagestr++; - } - fputc('\n', stderr); - -opt: - for ( ; opts->type != OPTION_END; opts++) { - if (short_opt) { - if (opts->short_name == *optstr) { - print_option_help(opts, 0); - break; - } - continue; - } - - if (opts->long_name == NULL) - continue; - - if (!prefixcmp(opts->long_name, optstr)) - print_option_help(opts, 0); - if (!prefixcmp("no-", optstr) && - !prefixcmp(opts->long_name, optstr + 3)) - print_option_help(opts, 0); - } - - return PARSE_OPT_HELP; -} - - -int parse_opt_verbosity_cb(const struct option *opt, - const char *arg __maybe_unused, - int unset) -{ - int *target = opt->value; - - if (unset) - /* --no-quiet, --no-verbose */ - *target = 0; - else if (opt->short_name == 'v') { - if (*target >= 0) - (*target)++; - else - *target = 1; - } else { - if (*target <= 0) - (*target)--; - else - *target = -1; - } - return 0; -} - -static struct option * -find_option(struct option *opts, int shortopt, const char *longopt) -{ - for (; opts->type != OPTION_END; opts++) { - if ((shortopt && opts->short_name == shortopt) || - (opts->long_name && longopt && - !strcmp(opts->long_name, longopt))) - return opts; - } - return NULL; -} - -void set_option_flag(struct option *opts, int shortopt, const char *longopt, - int flag) -{ - struct option *opt = find_option(opts, shortopt, longopt); - - if (opt) - opt->flags |= flag; - return; -} - -void set_option_nobuild(struct option *opts, int shortopt, - const char *longopt, - const char *build_opt, - bool can_skip) -{ - struct option *opt = find_option(opts, shortopt, longopt); - - if (!opt) - return; - - opt->flags |= PARSE_OPT_NOBUILD; - opt->flags |= can_skip ? PARSE_OPT_CANSKIP : 0; - opt->build_opt = build_opt; -} diff --git a/tools/perf/util/parse-options.h b/tools/perf/util/parse-options.h deleted file mode 100644 index dec893f10477..000000000000 --- a/tools/perf/util/parse-options.h +++ /dev/null @@ -1,228 +0,0 @@ -#ifndef __PERF_PARSE_OPTIONS_H -#define __PERF_PARSE_OPTIONS_H - -#include <stdbool.h> -#include <stdint.h> - -enum parse_opt_type { - /* special types */ - OPTION_END, - OPTION_ARGUMENT, - OPTION_GROUP, - /* options with no arguments */ - OPTION_BIT, - OPTION_BOOLEAN, - OPTION_INCR, - OPTION_SET_UINT, - OPTION_SET_PTR, - /* options with arguments (usually) */ - OPTION_STRING, - OPTION_INTEGER, - OPTION_LONG, - OPTION_CALLBACK, - OPTION_U64, - OPTION_UINTEGER, -}; - -enum parse_opt_flags { - PARSE_OPT_KEEP_DASHDASH = 1, - PARSE_OPT_STOP_AT_NON_OPTION = 2, - PARSE_OPT_KEEP_ARGV0 = 4, - PARSE_OPT_KEEP_UNKNOWN = 8, - PARSE_OPT_NO_INTERNAL_HELP = 16, -}; - -enum parse_opt_option_flags { - PARSE_OPT_OPTARG = 1, - PARSE_OPT_NOARG = 2, - PARSE_OPT_NONEG = 4, - PARSE_OPT_HIDDEN = 8, - PARSE_OPT_LASTARG_DEFAULT = 16, - PARSE_OPT_DISABLED = 32, - PARSE_OPT_EXCLUSIVE = 64, - PARSE_OPT_NOEMPTY = 128, - PARSE_OPT_NOBUILD = 256, - PARSE_OPT_CANSKIP = 512, -}; - -struct option; -typedef int parse_opt_cb(const struct option *, const char *arg, int unset); - -/* - * `type`:: - * holds the type of the option, you must have an OPTION_END last in your - * array. - * - * `short_name`:: - * the character to use as a short option name, '\0' if none. - * - * `long_name`:: - * the long option name, without the leading dashes, NULL if none. - * - * `value`:: - * stores pointers to the values to be filled. - * - * `argh`:: - * token to explain the kind of argument this option wants. Keep it - * homogenous across the repository. - * - * `help`:: - * the short help associated to what the option does. - * Must never be NULL (except for OPTION_END). - * OPTION_GROUP uses this pointer to store the group header. - * - * `flags`:: - * mask of parse_opt_option_flags. - * PARSE_OPT_OPTARG: says that the argument is optionnal (not for BOOLEANs) - * PARSE_OPT_NOARG: says that this option takes no argument, for CALLBACKs - * PARSE_OPT_NONEG: says that this option cannot be negated - * PARSE_OPT_HIDDEN this option is skipped in the default usage, showed in - * the long one. - * - * `callback`:: - * pointer to the callback to use for OPTION_CALLBACK. - * - * `defval`:: - * default value to fill (*->value) with for PARSE_OPT_OPTARG. - * OPTION_{BIT,SET_UINT,SET_PTR} store the {mask,integer,pointer} to put in - * the value when met. - * CALLBACKS can use it like they want. - * - * `set`:: - * whether an option was set by the user - */ -struct option { - enum parse_opt_type type; - int short_name; - const char *long_name; - void *value; - const char *argh; - const char *help; - const char *build_opt; - - int flags; - parse_opt_cb *callback; - intptr_t defval; - bool *set; - void *data; -}; - -#define check_vtype(v, type) ( BUILD_BUG_ON_ZERO(!__builtin_types_compatible_p(typeof(v), type)) + v ) - -#define OPT_END() { .type = OPTION_END } -#define OPT_ARGUMENT(l, h) { .type = OPTION_ARGUMENT, .long_name = (l), .help = (h) } -#define OPT_GROUP(h) { .type = OPTION_GROUP, .help = (h) } -#define OPT_BIT(s, l, v, h, b) { .type = OPTION_BIT, .short_name = (s), .long_name = (l), .value = check_vtype(v, int *), .help = (h), .defval = (b) } -#define OPT_BOOLEAN(s, l, v, h) { .type = OPTION_BOOLEAN, .short_name = (s), .long_name = (l), .value = check_vtype(v, bool *), .help = (h) } -#define OPT_BOOLEAN_FLAG(s, l, v, h, f) { .type = OPTION_BOOLEAN, .short_name = (s), .long_name = (l), .value = check_vtype(v, bool *), .help = (h), .flags = (f) } -#define OPT_BOOLEAN_SET(s, l, v, os, h) \ - { .type = OPTION_BOOLEAN, .short_name = (s), .long_name = (l), \ - .value = check_vtype(v, bool *), .help = (h), \ - .set = check_vtype(os, bool *)} -#define OPT_INCR(s, l, v, h) { .type = OPTION_INCR, .short_name = (s), .long_name = (l), .value = check_vtype(v, int *), .help = (h) } -#define OPT_SET_UINT(s, l, v, h, i) { .type = OPTION_SET_UINT, .short_name = (s), .long_name = (l), .value = check_vtype(v, unsigned int *), .help = (h), .defval = (i) } -#define OPT_SET_PTR(s, l, v, h, p) { .type = OPTION_SET_PTR, .short_name = (s), .long_name = (l), .value = (v), .help = (h), .defval = (p) } -#define OPT_INTEGER(s, l, v, h) { .type = OPTION_INTEGER, .short_name = (s), .long_name = (l), .value = check_vtype(v, int *), .help = (h) } -#define OPT_UINTEGER(s, l, v, h) { .type = OPTION_UINTEGER, .short_name = (s), .long_name = (l), .value = check_vtype(v, unsigned int *), .help = (h) } -#define OPT_LONG(s, l, v, h) { .type = OPTION_LONG, .short_name = (s), .long_name = (l), .value = check_vtype(v, long *), .help = (h) } -#define OPT_U64(s, l, v, h) { .type = OPTION_U64, .short_name = (s), .long_name = (l), .value = check_vtype(v, u64 *), .help = (h) } -#define OPT_STRING(s, l, v, a, h) { .type = OPTION_STRING, .short_name = (s), .long_name = (l), .value = check_vtype(v, const char **), (a), .help = (h) } -#define OPT_STRING_OPTARG(s, l, v, a, h, d) \ - { .type = OPTION_STRING, .short_name = (s), .long_name = (l), \ - .value = check_vtype(v, const char **), (a), .help = (h), \ - .flags = PARSE_OPT_OPTARG, .defval = (intptr_t)(d) } -#define OPT_STRING_NOEMPTY(s, l, v, a, h) { .type = OPTION_STRING, .short_name = (s), .long_name = (l), .value = check_vtype(v, const char **), (a), .help = (h), .flags = PARSE_OPT_NOEMPTY} -#define OPT_DATE(s, l, v, h) \ - { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), .argh = "time", .help = (h), .callback = parse_opt_approxidate_cb } -#define OPT_CALLBACK(s, l, v, a, h, f) \ - { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), (a), .help = (h), .callback = (f) } -#define OPT_CALLBACK_NOOPT(s, l, v, a, h, f) \ - { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), (a), .help = (h), .callback = (f), .flags = PARSE_OPT_NOARG } -#define OPT_CALLBACK_DEFAULT(s, l, v, a, h, f, d) \ - { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), (a), .help = (h), .callback = (f), .defval = (intptr_t)d, .flags = PARSE_OPT_LASTARG_DEFAULT } -#define OPT_CALLBACK_DEFAULT_NOOPT(s, l, v, a, h, f, d) \ - { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l),\ - .value = (v), (a), .help = (h), .callback = (f), .defval = (intptr_t)d,\ - .flags = PARSE_OPT_LASTARG_DEFAULT | PARSE_OPT_NOARG} -#define OPT_CALLBACK_OPTARG(s, l, v, d, a, h, f) \ - { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), \ - .value = (v), (a), .help = (h), .callback = (f), \ - .flags = PARSE_OPT_OPTARG, .data = (d) } - -/* parse_options() will filter out the processed options and leave the - * non-option argments in argv[]. - * Returns the number of arguments left in argv[]. - * - * NOTE: parse_options() and parse_options_subcommand() may call exit() in the - * case of an error (or for 'special' options like --list-cmds or --list-opts). - */ -extern int parse_options(int argc, const char **argv, - const struct option *options, - const char * const usagestr[], int flags); - -extern int parse_options_subcommand(int argc, const char **argv, - const struct option *options, - const char *const subcommands[], - const char *usagestr[], int flags); - -extern NORETURN void usage_with_options(const char * const *usagestr, - const struct option *options); -extern NORETURN __attribute__((format(printf,3,4))) -void usage_with_options_msg(const char * const *usagestr, - const struct option *options, - const char *fmt, ...); - -/*----- incremantal advanced APIs -----*/ - -enum { - PARSE_OPT_HELP = -1, - PARSE_OPT_DONE, - PARSE_OPT_LIST_OPTS, - PARSE_OPT_LIST_SUBCMDS, - PARSE_OPT_UNKNOWN, -}; - -/* - * It's okay for the caller to consume argv/argc in the usual way. - * Other fields of that structure are private to parse-options and should not - * be modified in any way. - */ -struct parse_opt_ctx_t { - const char **argv; - const char **out; - int argc, cpidx; - const char *opt; - const struct option *excl_opt; - int flags; -}; - -extern int parse_options_usage(const char * const *usagestr, - const struct option *opts, - const char *optstr, - bool short_opt); - - -/*----- some often used options -----*/ -extern int parse_opt_abbrev_cb(const struct option *, const char *, int); -extern int parse_opt_approxidate_cb(const struct option *, const char *, int); -extern int parse_opt_verbosity_cb(const struct option *, const char *, int); - -#define OPT__VERBOSE(var) OPT_BOOLEAN('v', "verbose", (var), "be verbose") -#define OPT__QUIET(var) OPT_BOOLEAN('q', "quiet", (var), "be quiet") -#define OPT__VERBOSITY(var) \ - { OPTION_CALLBACK, 'v', "verbose", (var), NULL, "be more verbose", \ - PARSE_OPT_NOARG, &parse_opt_verbosity_cb, 0 }, \ - { OPTION_CALLBACK, 'q', "quiet", (var), NULL, "be more quiet", \ - PARSE_OPT_NOARG, &parse_opt_verbosity_cb, 0 } -#define OPT__DRY_RUN(var) OPT_BOOLEAN('n', "dry-run", (var), "dry run") -#define OPT__ABBREV(var) \ - { OPTION_CALLBACK, 0, "abbrev", (var), "n", \ - "use <n> digits to display SHA-1s", \ - PARSE_OPT_OPTARG, &parse_opt_abbrev_cb, 0 } - -extern const char *parse_options_fix_filename(const char *prefix, const char *file); - -void set_option_flag(struct option *opts, int sopt, const char *lopt, int flag); -void set_option_nobuild(struct option *opts, int shortopt, const char *longopt, - const char *build_opt, bool can_skip); -#endif /* __PERF_PARSE_OPTIONS_H */ diff --git a/tools/perf/util/parse-regs-options.c b/tools/perf/util/parse-regs-options.c index 4f2c1c255d81..646ecf736aad 100644 --- a/tools/perf/util/parse-regs-options.c +++ b/tools/perf/util/parse-regs-options.c @@ -1,7 +1,7 @@ #include "perf.h" #include "util/util.h" #include "util/debug.h" -#include "util/parse-options.h" +#include <subcmd/parse-options.h> #include "util/parse-regs-options.h" int diff --git a/tools/perf/util/run-command.c b/tools/perf/util/run-command.c deleted file mode 100644 index fed37d6ae070..000000000000 --- a/tools/perf/util/run-command.c +++ /dev/null @@ -1,227 +0,0 @@ -#include <unistd.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <string.h> -#include <errno.h> -#include <sys/wait.h> -#include "subcmd-util.h" -#include "run-command.h" -#include "exec_cmd.h" - -#define STRERR_BUFSIZE 128 - -static inline void close_pair(int fd[2]) -{ - close(fd[0]); - close(fd[1]); -} - -static inline void dup_devnull(int to) -{ - int fd = open("/dev/null", O_RDWR); - dup2(fd, to); - close(fd); -} - -int start_command(struct child_process *cmd) -{ - int need_in, need_out, need_err; - int fdin[2], fdout[2], fderr[2]; - char sbuf[STRERR_BUFSIZE]; - - /* - * In case of errors we must keep the promise to close FDs - * that have been passed in via ->in and ->out. - */ - - need_in = !cmd->no_stdin && cmd->in < 0; - if (need_in) { - if (pipe(fdin) < 0) { - if (cmd->out > 0) - close(cmd->out); - return -ERR_RUN_COMMAND_PIPE; - } - cmd->in = fdin[1]; - } - - need_out = !cmd->no_stdout - && !cmd->stdout_to_stderr - && cmd->out < 0; - if (need_out) { - if (pipe(fdout) < 0) { - if (need_in) - close_pair(fdin); - else if (cmd->in) - close(cmd->in); - return -ERR_RUN_COMMAND_PIPE; - } - cmd->out = fdout[0]; - } - - need_err = !cmd->no_stderr && cmd->err < 0; - if (need_err) { - if (pipe(fderr) < 0) { - if (need_in) - close_pair(fdin); - else if (cmd->in) - close(cmd->in); - if (need_out) - close_pair(fdout); - else if (cmd->out) - close(cmd->out); - return -ERR_RUN_COMMAND_PIPE; - } - cmd->err = fderr[0]; - } - - fflush(NULL); - cmd->pid = fork(); - if (!cmd->pid) { - if (cmd->no_stdin) - dup_devnull(0); - else if (need_in) { - dup2(fdin[0], 0); - close_pair(fdin); - } else if (cmd->in) { - dup2(cmd->in, 0); - close(cmd->in); - } - - if (cmd->no_stderr) - dup_devnull(2); - else if (need_err) { - dup2(fderr[1], 2); - close_pair(fderr); - } - - if (cmd->no_stdout) - dup_devnull(1); - else if (cmd->stdout_to_stderr) - dup2(2, 1); - else if (need_out) { - dup2(fdout[1], 1); - close_pair(fdout); - } else if (cmd->out > 1) { - dup2(cmd->out, 1); - close(cmd->out); - } - - if (cmd->dir && chdir(cmd->dir)) - die("exec %s: cd to %s failed (%s)", cmd->argv[0], - cmd->dir, strerror_r(errno, sbuf, sizeof(sbuf))); - if (cmd->env) { - for (; *cmd->env; cmd->env++) { - if (strchr(*cmd->env, '=')) - putenv((char*)*cmd->env); - else - unsetenv(*cmd->env); - } - } - if (cmd->preexec_cb) - cmd->preexec_cb(); - if (cmd->exec_cmd) { - execv_cmd(cmd->argv); - } else { - execvp(cmd->argv[0], (char *const*) cmd->argv); - } - exit(127); - } - - if (cmd->pid < 0) { - int err = errno; - if (need_in) - close_pair(fdin); - else if (cmd->in) - close(cmd->in); - if (need_out) - close_pair(fdout); - else if (cmd->out) - close(cmd->out); - if (need_err) - close_pair(fderr); - return err == ENOENT ? - -ERR_RUN_COMMAND_EXEC : - -ERR_RUN_COMMAND_FORK; - } - - if (need_in) - close(fdin[0]); - else if (cmd->in) - close(cmd->in); - - if (need_out) - close(fdout[1]); - else if (cmd->out) - close(cmd->out); - - if (need_err) - close(fderr[1]); - - return 0; -} - -static int wait_or_whine(pid_t pid) -{ - char sbuf[STRERR_BUFSIZE]; - - for (;;) { - int status, code; - pid_t waiting = waitpid(pid, &status, 0); - - if (waiting < 0) { - if (errno == EINTR) - continue; - fprintf(stderr, " Error: waitpid failed (%s)", - strerror_r(errno, sbuf, sizeof(sbuf))); - return -ERR_RUN_COMMAND_WAITPID; - } - if (waiting != pid) - return -ERR_RUN_COMMAND_WAITPID_WRONG_PID; - if (WIFSIGNALED(status)) - return -ERR_RUN_COMMAND_WAITPID_SIGNAL; - - if (!WIFEXITED(status)) - return -ERR_RUN_COMMAND_WAITPID_NOEXIT; - code = WEXITSTATUS(status); - switch (code) { - case 127: - return -ERR_RUN_COMMAND_EXEC; - case 0: - return 0; - default: - return -code; - } - } -} - -int finish_command(struct child_process *cmd) -{ - return wait_or_whine(cmd->pid); -} - -int run_command(struct child_process *cmd) -{ - int code = start_command(cmd); - if (code) - return code; - return finish_command(cmd); -} - -static void prepare_run_command_v_opt(struct child_process *cmd, - const char **argv, - int opt) -{ - memset(cmd, 0, sizeof(*cmd)); - cmd->argv = argv; - cmd->no_stdin = opt & RUN_COMMAND_NO_STDIN ? 1 : 0; - cmd->exec_cmd = opt & RUN_EXEC_CMD ? 1 : 0; - cmd->stdout_to_stderr = opt & RUN_COMMAND_STDOUT_TO_STDERR ? 1 : 0; -} - -int run_command_v_opt(const char **argv, int opt) -{ - struct child_process cmd; - prepare_run_command_v_opt(&cmd, argv, opt); - return run_command(&cmd); -} diff --git a/tools/perf/util/run-command.h b/tools/perf/util/run-command.h deleted file mode 100644 index 4a55393a6547..000000000000 --- a/tools/perf/util/run-command.h +++ /dev/null @@ -1,60 +0,0 @@ -#ifndef __PERF_RUN_COMMAND_H -#define __PERF_RUN_COMMAND_H - -#include <unistd.h> - -enum { - ERR_RUN_COMMAND_FORK = 10000, - ERR_RUN_COMMAND_EXEC, - ERR_RUN_COMMAND_PIPE, - ERR_RUN_COMMAND_WAITPID, - ERR_RUN_COMMAND_WAITPID_WRONG_PID, - ERR_RUN_COMMAND_WAITPID_SIGNAL, - ERR_RUN_COMMAND_WAITPID_NOEXIT, -}; -#define IS_RUN_COMMAND_ERR(x) (-(x) >= ERR_RUN_COMMAND_FORK) - -struct child_process { - const char **argv; - pid_t pid; - /* - * Using .in, .out, .err: - * - Specify 0 for no redirections (child inherits stdin, stdout, - * stderr from parent). - * - Specify -1 to have a pipe allocated as follows: - * .in: returns the writable pipe end; parent writes to it, - * the readable pipe end becomes child's stdin - * .out, .err: returns the readable pipe end; parent reads from - * it, the writable pipe end becomes child's stdout/stderr - * The caller of start_command() must close the returned FDs - * after it has completed reading from/writing to it! - * - Specify > 0 to set a channel to a particular FD as follows: - * .in: a readable FD, becomes child's stdin - * .out: a writable FD, becomes child's stdout/stderr - * .err > 0 not supported - * The specified FD is closed by start_command(), even in case - * of errors! - */ - int in; - int out; - int err; - const char *dir; - const char *const *env; - unsigned no_stdin:1; - unsigned no_stdout:1; - unsigned no_stderr:1; - unsigned exec_cmd:1; /* if this is to be external sub-command */ - unsigned stdout_to_stderr:1; - void (*preexec_cb)(void); -}; - -int start_command(struct child_process *); -int finish_command(struct child_process *); -int run_command(struct child_process *); - -#define RUN_COMMAND_NO_STDIN 1 -#define RUN_EXEC_CMD 2 /*If this is to be external sub-command */ -#define RUN_COMMAND_STDOUT_TO_STDERR 4 -int run_command_v_opt(const char **argv, int opt); - -#endif /* __PERF_RUN_COMMAND_H */ diff --git a/tools/perf/util/sigchain.c b/tools/perf/util/sigchain.c deleted file mode 100644 index 3537c348a18e..000000000000 --- a/tools/perf/util/sigchain.c +++ /dev/null @@ -1,53 +0,0 @@ -#include <signal.h> -#include "subcmd-util.h" -#include "sigchain.h" - -#define SIGCHAIN_MAX_SIGNALS 32 - -struct sigchain_signal { - sigchain_fun *old; - int n; - int alloc; -}; -static struct sigchain_signal signals[SIGCHAIN_MAX_SIGNALS]; - -static void check_signum(int sig) -{ - if (sig < 1 || sig >= SIGCHAIN_MAX_SIGNALS) - die("BUG: signal out of range: %d", sig); -} - -static int sigchain_push(int sig, sigchain_fun f) -{ - struct sigchain_signal *s = signals + sig; - check_signum(sig); - - ALLOC_GROW(s->old, s->n + 1, s->alloc); - s->old[s->n] = signal(sig, f); - if (s->old[s->n] == SIG_ERR) - return -1; - s->n++; - return 0; -} - -int sigchain_pop(int sig) -{ - struct sigchain_signal *s = signals + sig; - check_signum(sig); - if (s->n < 1) - return 0; - - if (signal(sig, s->old[s->n - 1]) == SIG_ERR) - return -1; - s->n--; - return 0; -} - -void sigchain_push_common(sigchain_fun f) -{ - sigchain_push(SIGINT, f); - sigchain_push(SIGHUP, f); - sigchain_push(SIGTERM, f); - sigchain_push(SIGQUIT, f); - sigchain_push(SIGPIPE, f); -} diff --git a/tools/perf/util/sigchain.h b/tools/perf/util/sigchain.h deleted file mode 100644 index 959d64eb5557..000000000000 --- a/tools/perf/util/sigchain.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef __PERF_SIGCHAIN_H -#define __PERF_SIGCHAIN_H - -typedef void (*sigchain_fun)(int); - -int sigchain_pop(int sig); - -void sigchain_push_common(sigchain_fun f); - -#endif /* __PERF_SIGCHAIN_H */ diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h index 31228851e397..86f05e7a5566 100644 --- a/tools/perf/util/sort.h +++ b/tools/perf/util/sort.h @@ -18,7 +18,7 @@ #include "debug.h" #include "header.h" -#include "parse-options.h" +#include <subcmd/parse-options.h> #include "parse-events.h" #include "hist.h" #include "thread.h" diff --git a/tools/perf/util/subcmd-config.c b/tools/perf/util/subcmd-config.c deleted file mode 100644 index d017c728bd1b..000000000000 --- a/tools/perf/util/subcmd-config.c +++ /dev/null @@ -1,11 +0,0 @@ -#include "subcmd-config.h" - -#define UNDEFINED "SUBCMD_HAS_NOT_BEEN_INITIALIZED" - -struct subcmd_config subcmd_config = { - .exec_name = UNDEFINED, - .prefix = UNDEFINED, - .exec_path = UNDEFINED, - .exec_path_env = UNDEFINED, - .pager_env = UNDEFINED, -}; diff --git a/tools/perf/util/subcmd-config.h b/tools/perf/util/subcmd-config.h deleted file mode 100644 index cc8514030b5c..000000000000 --- a/tools/perf/util/subcmd-config.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef __PERF_SUBCMD_CONFIG_H -#define __PERF_SUBCMD_CONFIG_H - -struct subcmd_config { - const char *exec_name; - const char *prefix; - const char *exec_path; - const char *exec_path_env; - const char *pager_env; -}; - -extern struct subcmd_config subcmd_config; - -#endif /* __PERF_SUBCMD_CONFIG_H */ diff --git a/tools/perf/util/subcmd-util.h b/tools/perf/util/subcmd-util.h deleted file mode 100644 index 321aeb11a381..000000000000 --- a/tools/perf/util/subcmd-util.h +++ /dev/null @@ -1,91 +0,0 @@ -#ifndef __PERF_SUBCMD_UTIL_H -#define __PERF_SUBCMD_UTIL_H - -#include <stdarg.h> -#include <stdlib.h> -#include <stdio.h> - -#define NORETURN __attribute__((__noreturn__)) - -static inline void report(const char *prefix, const char *err, va_list params) -{ - char msg[1024]; - vsnprintf(msg, sizeof(msg), err, params); - fprintf(stderr, " %s%s\n", prefix, msg); -} - -static NORETURN inline void die(const char *err, ...) -{ - va_list params; - - va_start(params, err); - report(" Fatal: ", err, params); - exit(128); - va_end(params); -} - -#define zfree(ptr) ({ free(*ptr); *ptr = NULL; }) - -#define alloc_nr(x) (((x)+16)*3/2) - -/* - * Realloc the buffer pointed at by variable 'x' so that it can hold - * at least 'nr' entries; the number of entries currently allocated - * is 'alloc', using the standard growing factor alloc_nr() macro. - * - * DO NOT USE any expression with side-effect for 'x' or 'alloc'. - */ -#define ALLOC_GROW(x, nr, alloc) \ - do { \ - if ((nr) > alloc) { \ - if (alloc_nr(alloc) < (nr)) \ - alloc = (nr); \ - else \ - alloc = alloc_nr(alloc); \ - x = xrealloc((x), alloc * sizeof(*(x))); \ - } \ - } while(0) - -static inline void *xrealloc(void *ptr, size_t size) -{ - void *ret = realloc(ptr, size); - if (!ret && !size) - ret = realloc(ptr, 1); - if (!ret) { - ret = realloc(ptr, size); - if (!ret && !size) - ret = realloc(ptr, 1); - if (!ret) - die("Out of memory, realloc failed"); - } - return ret; -} - -#define astrcatf(out, fmt, ...) \ -({ \ - char *tmp = *(out); \ - if (asprintf((out), "%s" fmt, tmp ?: "", ## __VA_ARGS__) == -1) \ - die("asprintf failed"); \ - free(tmp); \ -}) - -static inline void astrcat(char **out, const char *add) -{ - char *tmp = *out; - - if (asprintf(out, "%s%s", tmp ?: "", add) == -1) - die("asprintf failed"); - - free(tmp); -} - -static inline int prefixcmp(const char *str, const char *prefix) -{ - for (; ; str++, prefix++) - if (!*prefix) - return 0; - else if (*str != *prefix) - return (unsigned char)*prefix - (unsigned char)*str; -} - -#endif /* __PERF_SUBCMD_UTIL_H */ |